github.com/codemac/docker@v1.2.1-0.20150518222241-6a18412d5b9c/runconfig/config_test.go (about) 1 package runconfig 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "strings" 8 "testing" 9 10 "github.com/docker/docker/nat" 11 ) 12 13 func parse(t *testing.T, args string) (*Config, *HostConfig, error) { 14 config, hostConfig, _, err := parseRun(strings.Split(args+" ubuntu bash", " ")) 15 return config, hostConfig, err 16 } 17 18 func mustParse(t *testing.T, args string) (*Config, *HostConfig) { 19 config, hostConfig, err := parse(t, args) 20 if err != nil { 21 t.Fatal(err) 22 } 23 return config, hostConfig 24 } 25 26 // check if (a == c && b == d) || (a == d && b == c) 27 // because maps are randomized 28 func compareRandomizedStrings(a, b, c, d string) error { 29 if a == c && b == d { 30 return nil 31 } 32 if a == d && b == c { 33 return nil 34 } 35 return fmt.Errorf("strings don't match") 36 } 37 38 func TestParseRunLinks(t *testing.T) { 39 if _, hostConfig := mustParse(t, "--link a:b"); len(hostConfig.Links) == 0 || hostConfig.Links[0] != "a:b" { 40 t.Fatalf("Error parsing links. Expected []string{\"a:b\"}, received: %v", hostConfig.Links) 41 } 42 if _, hostConfig := mustParse(t, "--link a:b --link c:d"); len(hostConfig.Links) < 2 || hostConfig.Links[0] != "a:b" || hostConfig.Links[1] != "c:d" { 43 t.Fatalf("Error parsing links. Expected []string{\"a:b\", \"c:d\"}, received: %v", hostConfig.Links) 44 } 45 if _, hostConfig := mustParse(t, ""); len(hostConfig.Links) != 0 { 46 t.Fatalf("Error parsing links. No link expected, received: %v", hostConfig.Links) 47 } 48 } 49 50 func TestParseRunAttach(t *testing.T) { 51 if config, _ := mustParse(t, "-a stdin"); !config.AttachStdin || config.AttachStdout || config.AttachStderr { 52 t.Fatalf("Error parsing attach flags. Expect only Stdin enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) 53 } 54 if config, _ := mustParse(t, "-a stdin -a stdout"); !config.AttachStdin || !config.AttachStdout || config.AttachStderr { 55 t.Fatalf("Error parsing attach flags. Expect only Stdin and Stdout enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) 56 } 57 if config, _ := mustParse(t, "-a stdin -a stdout -a stderr"); !config.AttachStdin || !config.AttachStdout || !config.AttachStderr { 58 t.Fatalf("Error parsing attach flags. Expect all attach enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) 59 } 60 if config, _ := mustParse(t, ""); config.AttachStdin || !config.AttachStdout || !config.AttachStderr { 61 t.Fatalf("Error parsing attach flags. Expect Stdin disabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) 62 } 63 64 if _, _, err := parse(t, "-a"); err == nil { 65 t.Fatalf("Error parsing attach flags, `-a` should be an error but is not") 66 } 67 if _, _, err := parse(t, "-a invalid"); err == nil { 68 t.Fatalf("Error parsing attach flags, `-a invalid` should be an error but is not") 69 } 70 if _, _, err := parse(t, "-a invalid -a stdout"); err == nil { 71 t.Fatalf("Error parsing attach flags, `-a stdout -a invalid` should be an error but is not") 72 } 73 if _, _, err := parse(t, "-a stdout -a stderr -d"); err == nil { 74 t.Fatalf("Error parsing attach flags, `-a stdout -a stderr -d` should be an error but is not") 75 } 76 if _, _, err := parse(t, "-a stdin -d"); err == nil { 77 t.Fatalf("Error parsing attach flags, `-a stdin -d` should be an error but is not") 78 } 79 if _, _, err := parse(t, "-a stdout -d"); err == nil { 80 t.Fatalf("Error parsing attach flags, `-a stdout -d` should be an error but is not") 81 } 82 if _, _, err := parse(t, "-a stderr -d"); err == nil { 83 t.Fatalf("Error parsing attach flags, `-a stderr -d` should be an error but is not") 84 } 85 if _, _, err := parse(t, "-d --rm"); err == nil { 86 t.Fatalf("Error parsing attach flags, `-d --rm` should be an error but is not") 87 } 88 } 89 90 func TestParseRunVolumes(t *testing.T) { 91 if config, hostConfig := mustParse(t, "-v /tmp"); hostConfig.Binds != nil { 92 t.Fatalf("Error parsing volume flags, `-v /tmp` should not mount-bind anything. Received %v", hostConfig.Binds) 93 } else if _, exists := config.Volumes["/tmp"]; !exists { 94 t.Fatalf("Error parsing volume flags, `-v /tmp` is missing from volumes. Received %v", config.Volumes) 95 } 96 97 if config, hostConfig := mustParse(t, "-v /tmp -v /var"); hostConfig.Binds != nil { 98 t.Fatalf("Error parsing volume flags, `-v /tmp -v /var` should not mount-bind anything. Received %v", hostConfig.Binds) 99 } else if _, exists := config.Volumes["/tmp"]; !exists { 100 t.Fatalf("Error parsing volume flags, `-v /tmp` is missing from volumes. Received %v", config.Volumes) 101 } else if _, exists := config.Volumes["/var"]; !exists { 102 t.Fatalf("Error parsing volume flags, `-v /var` is missing from volumes. Received %v", config.Volumes) 103 } 104 105 if _, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp"); hostConfig.Binds == nil || hostConfig.Binds[0] != "/hostTmp:/containerTmp" { 106 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp` should mount-bind /hostTmp into /containeTmp. Received %v", hostConfig.Binds) 107 } 108 109 if _, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp -v /hostVar:/containerVar"); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], "/hostTmp:/containerTmp", "/hostVar:/containerVar") != nil { 110 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp -v /hostVar:/containerVar` should mount-bind /hostTmp into /containeTmp and /hostVar into /hostContainer. Received %v", hostConfig.Binds) 111 } 112 113 if _, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp:ro -v /hostVar:/containerVar:rw"); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], "/hostTmp:/containerTmp:ro", "/hostVar:/containerVar:rw") != nil { 114 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp:ro -v /hostVar:/containerVar:rw` should mount-bind /hostTmp into /containeTmp and /hostVar into /hostContainer. Received %v", hostConfig.Binds) 115 } 116 117 if config, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp -v /containerVar"); hostConfig.Binds == nil || len(hostConfig.Binds) > 1 || hostConfig.Binds[0] != "/hostTmp:/containerTmp" { 118 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp -v /containerVar` should mount-bind only /hostTmp into /containeTmp. Received %v", hostConfig.Binds) 119 } else if _, exists := config.Volumes["/containerVar"]; !exists { 120 t.Fatalf("Error parsing volume flags, `-v /containerVar` is missing from volumes. Received %v", config.Volumes) 121 } 122 123 if config, hostConfig := mustParse(t, ""); hostConfig.Binds != nil { 124 t.Fatalf("Error parsing volume flags, without volume, nothing should be mount-binded. Received %v", hostConfig.Binds) 125 } else if len(config.Volumes) != 0 { 126 t.Fatalf("Error parsing volume flags, without volume, no volume should be present. Received %v", config.Volumes) 127 } 128 129 if _, _, err := parse(t, "-v /"); err == nil { 130 t.Fatalf("Expected error, but got none") 131 } 132 133 if _, _, err := parse(t, "-v /:/"); err == nil { 134 t.Fatalf("Error parsing volume flags, `-v /:/` should fail but didn't") 135 } 136 if _, _, err := parse(t, "-v"); err == nil { 137 t.Fatalf("Error parsing volume flags, `-v` should fail but didn't") 138 } 139 if _, _, err := parse(t, "-v /tmp:"); err == nil { 140 t.Fatalf("Error parsing volume flags, `-v /tmp:` should fail but didn't") 141 } 142 if _, _, err := parse(t, "-v /tmp:ro"); err == nil { 143 t.Fatalf("Error parsing volume flags, `-v /tmp:ro` should fail but didn't") 144 } 145 if _, _, err := parse(t, "-v /tmp::"); err == nil { 146 t.Fatalf("Error parsing volume flags, `-v /tmp::` should fail but didn't") 147 } 148 if _, _, err := parse(t, "-v :"); err == nil { 149 t.Fatalf("Error parsing volume flags, `-v :` should fail but didn't") 150 } 151 if _, _, err := parse(t, "-v ::"); err == nil { 152 t.Fatalf("Error parsing volume flags, `-v ::` should fail but didn't") 153 } 154 if _, _, err := parse(t, "-v /tmp:/tmp:/tmp:/tmp"); err == nil { 155 t.Fatalf("Error parsing volume flags, `-v /tmp:/tmp:/tmp:/tmp` should fail but didn't") 156 } 157 } 158 159 func TestCompare(t *testing.T) { 160 volumes1 := make(map[string]struct{}) 161 volumes1["/test1"] = struct{}{} 162 config1 := Config{ 163 PortSpecs: []string{"1111:1111", "2222:2222"}, 164 Env: []string{"VAR1=1", "VAR2=2"}, 165 Volumes: volumes1, 166 } 167 config3 := Config{ 168 PortSpecs: []string{"0000:0000", "2222:2222"}, 169 Env: []string{"VAR1=1", "VAR2=2"}, 170 Volumes: volumes1, 171 } 172 volumes2 := make(map[string]struct{}) 173 volumes2["/test2"] = struct{}{} 174 config5 := Config{ 175 PortSpecs: []string{"0000:0000", "2222:2222"}, 176 Env: []string{"VAR1=1", "VAR2=2"}, 177 Volumes: volumes2, 178 } 179 if Compare(&config1, &config3) { 180 t.Fatalf("Compare should return false, PortSpecs are different") 181 } 182 if Compare(&config1, &config5) { 183 t.Fatalf("Compare should return false, Volumes are different") 184 } 185 if !Compare(&config1, &config1) { 186 t.Fatalf("Compare should return true") 187 } 188 } 189 190 func TestMerge(t *testing.T) { 191 volumesImage := make(map[string]struct{}) 192 volumesImage["/test1"] = struct{}{} 193 volumesImage["/test2"] = struct{}{} 194 configImage := &Config{ 195 PortSpecs: []string{"1111:1111", "2222:2222"}, 196 Env: []string{"VAR1=1", "VAR2=2"}, 197 Volumes: volumesImage, 198 } 199 200 volumesUser := make(map[string]struct{}) 201 volumesUser["/test3"] = struct{}{} 202 configUser := &Config{ 203 PortSpecs: []string{"3333:2222", "3333:3333"}, 204 Env: []string{"VAR2=3", "VAR3=3"}, 205 Volumes: volumesUser, 206 } 207 208 if err := Merge(configUser, configImage); err != nil { 209 t.Error(err) 210 } 211 212 if len(configUser.ExposedPorts) != 3 { 213 t.Fatalf("Expected 3 ExposedPorts, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts)) 214 } 215 for portSpecs := range configUser.ExposedPorts { 216 if portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" { 217 t.Fatalf("Expected 1111 or 2222 or 3333, found %s", portSpecs) 218 } 219 } 220 if len(configUser.Env) != 3 { 221 t.Fatalf("Expected 3 env var, VAR1=1, VAR2=3 and VAR3=3, found %d", len(configUser.Env)) 222 } 223 for _, env := range configUser.Env { 224 if env != "VAR1=1" && env != "VAR2=3" && env != "VAR3=3" { 225 t.Fatalf("Expected VAR1=1 or VAR2=3 or VAR3=3, found %s", env) 226 } 227 } 228 229 if len(configUser.Volumes) != 3 { 230 t.Fatalf("Expected 3 volumes, /test1, /test2 and /test3, found %d", len(configUser.Volumes)) 231 } 232 for v := range configUser.Volumes { 233 if v != "/test1" && v != "/test2" && v != "/test3" { 234 t.Fatalf("Expected /test1 or /test2 or /test3, found %s", v) 235 } 236 } 237 238 ports, _, err := nat.ParsePortSpecs([]string{"0000"}) 239 if err != nil { 240 t.Error(err) 241 } 242 configImage2 := &Config{ 243 ExposedPorts: ports, 244 } 245 246 if err := Merge(configUser, configImage2); err != nil { 247 t.Error(err) 248 } 249 250 if len(configUser.ExposedPorts) != 4 { 251 t.Fatalf("Expected 4 ExposedPorts, 0000, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts)) 252 } 253 for portSpecs := range configUser.ExposedPorts { 254 if portSpecs.Port() != "0" && portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" { 255 t.Fatalf("Expected %q or %q or %q or %q, found %s", 0, 1111, 2222, 3333, portSpecs) 256 } 257 } 258 } 259 260 func TestDecodeContainerConfig(t *testing.T) { 261 fixtures := []struct { 262 file string 263 entrypoint *Entrypoint 264 }{ 265 {"fixtures/container_config_1_14.json", NewEntrypoint()}, 266 {"fixtures/container_config_1_17.json", NewEntrypoint("bash")}, 267 {"fixtures/container_config_1_19.json", NewEntrypoint("bash")}, 268 } 269 270 for _, f := range fixtures { 271 b, err := ioutil.ReadFile(f.file) 272 if err != nil { 273 t.Fatal(err) 274 } 275 276 c, h, err := DecodeContainerConfig(bytes.NewReader(b)) 277 if err != nil { 278 t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err)) 279 } 280 281 if c.Image != "ubuntu" { 282 t.Fatalf("Expected ubuntu image, found %s\n", c.Image) 283 } 284 285 if c.Entrypoint.Len() != f.entrypoint.Len() { 286 t.Fatalf("Expected %v, found %v\n", f.entrypoint, c.Entrypoint) 287 } 288 289 if h.Memory != 1000 { 290 t.Fatalf("Expected memory to be 1000, found %d\n", h.Memory) 291 } 292 } 293 }