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