github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/runconfig/config_test.go (about) 1 package runconfig 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "runtime" 9 "strings" 10 "testing" 11 12 "github.com/docker/docker/api/types/container" 13 networktypes "github.com/docker/docker/api/types/network" 14 "github.com/docker/docker/api/types/strslice" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 type f struct { 20 file string 21 entrypoint strslice.StrSlice 22 } 23 24 func TestDecodeContainerConfig(t *testing.T) { 25 26 var ( 27 fixtures []f 28 image string 29 ) 30 31 if runtime.GOOS != "windows" { 32 image = "ubuntu" 33 fixtures = []f{ 34 {"fixtures/unix/container_config_1_14.json", strslice.StrSlice{}}, 35 {"fixtures/unix/container_config_1_17.json", strslice.StrSlice{"bash"}}, 36 {"fixtures/unix/container_config_1_19.json", strslice.StrSlice{"bash"}}, 37 } 38 } else { 39 image = "windows" 40 fixtures = []f{ 41 {"fixtures/windows/container_config_1_19.json", strslice.StrSlice{"cmd"}}, 42 } 43 } 44 45 for _, f := range fixtures { 46 b, err := ioutil.ReadFile(f.file) 47 if err != nil { 48 t.Fatal(err) 49 } 50 51 c, h, _, err := decodeContainerConfig(bytes.NewReader(b)) 52 if err != nil { 53 t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err)) 54 } 55 56 if c.Image != image { 57 t.Fatalf("Expected %s image, found %s\n", image, c.Image) 58 } 59 60 if len(c.Entrypoint) != len(f.entrypoint) { 61 t.Fatalf("Expected %v, found %v\n", f.entrypoint, c.Entrypoint) 62 } 63 64 if h != nil && h.Memory != 1000 { 65 t.Fatalf("Expected memory to be 1000, found %d\n", h.Memory) 66 } 67 } 68 } 69 70 // TestDecodeContainerConfigIsolation validates isolation passed 71 // to the daemon in the hostConfig structure. Note this is platform specific 72 // as to what level of container isolation is supported. 73 func TestDecodeContainerConfigIsolation(t *testing.T) { 74 75 // An Invalid isolation level 76 if _, _, _, err := callDecodeContainerConfigIsolation("invalid"); err != nil { 77 if !strings.Contains(err.Error(), `Invalid isolation: "invalid"`) { 78 t.Fatal(err) 79 } 80 } 81 82 // Blank isolation (== default) 83 if _, _, _, err := callDecodeContainerConfigIsolation(""); err != nil { 84 t.Fatal("Blank isolation should have succeeded") 85 } 86 87 // Default isolation 88 if _, _, _, err := callDecodeContainerConfigIsolation("default"); err != nil { 89 t.Fatal("default isolation should have succeeded") 90 } 91 92 // Process isolation (Valid on Windows only) 93 if runtime.GOOS == "windows" { 94 if _, _, _, err := callDecodeContainerConfigIsolation("process"); err != nil { 95 t.Fatal("process isolation should have succeeded") 96 } 97 } else { 98 if _, _, _, err := callDecodeContainerConfigIsolation("process"); err != nil { 99 if !strings.Contains(err.Error(), `Invalid isolation: "process"`) { 100 t.Fatal(err) 101 } 102 } 103 } 104 105 // Hyper-V Containers isolation (Valid on Windows only) 106 if runtime.GOOS == "windows" { 107 if _, _, _, err := callDecodeContainerConfigIsolation("hyperv"); err != nil { 108 t.Fatal("hyperv isolation should have succeeded") 109 } 110 } else { 111 if _, _, _, err := callDecodeContainerConfigIsolation("hyperv"); err != nil { 112 if !strings.Contains(err.Error(), `Invalid isolation: "hyperv"`) { 113 t.Fatal(err) 114 } 115 } 116 } 117 } 118 119 // callDecodeContainerConfigIsolation is a utility function to call 120 // DecodeContainerConfig for validating isolation 121 func callDecodeContainerConfigIsolation(isolation string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) { 122 var ( 123 b []byte 124 err error 125 ) 126 w := ContainerConfigWrapper{ 127 Config: &container.Config{}, 128 HostConfig: &container.HostConfig{ 129 NetworkMode: "none", 130 Isolation: container.Isolation(isolation)}, 131 } 132 if b, err = json.Marshal(w); err != nil { 133 return nil, nil, nil, fmt.Errorf("Error on marshal %s", err.Error()) 134 } 135 return decodeContainerConfig(bytes.NewReader(b)) 136 } 137 138 type decodeConfigTestcase struct { 139 doc string 140 wrapper ContainerConfigWrapper 141 expectedErr string 142 expectedConfig *container.Config 143 expectedHostConfig *container.HostConfig 144 goos string 145 } 146 147 func runDecodeContainerConfigTestCase(testcase decodeConfigTestcase) func(t *testing.T) { 148 return func(t *testing.T) { 149 raw := marshal(t, testcase.wrapper, testcase.doc) 150 config, hostConfig, _, err := decodeContainerConfig(bytes.NewReader(raw)) 151 if testcase.expectedErr != "" { 152 if !assert.Error(t, err) { 153 return 154 } 155 assert.Contains(t, err.Error(), testcase.expectedErr) 156 return 157 } 158 assert.NoError(t, err) 159 assert.Equal(t, testcase.expectedConfig, config) 160 assert.Equal(t, testcase.expectedHostConfig, hostConfig) 161 } 162 } 163 164 func marshal(t *testing.T, w ContainerConfigWrapper, doc string) []byte { 165 b, err := json.Marshal(w) 166 require.NoError(t, err, "%s: failed to encode config wrapper", doc) 167 return b 168 } 169 170 func containerWrapperWithVolume(volume string) ContainerConfigWrapper { 171 return ContainerConfigWrapper{ 172 Config: &container.Config{ 173 Volumes: map[string]struct{}{ 174 volume: {}, 175 }, 176 }, 177 HostConfig: &container.HostConfig{}, 178 } 179 } 180 181 func containerWrapperWithBind(bind string) ContainerConfigWrapper { 182 return ContainerConfigWrapper{ 183 Config: &container.Config{ 184 Volumes: map[string]struct{}{}, 185 }, 186 HostConfig: &container.HostConfig{ 187 Binds: []string{bind}, 188 }, 189 } 190 }