github.com/tsuna/docker@v1.7.0-rc3/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 _, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp:roZ -v /hostVar:/containerVar:rwZ"); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], "/hostTmp:/containerTmp:roZ", "/hostVar:/containerVar:rwZ") != nil { 118 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp:roZ -v /hostVar:/containerVar:rwZ` should mount-bind /hostTmp into /containeTmp and /hostVar into /hostContainer. Received %v", hostConfig.Binds) 119 } 120 121 if _, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp:Z -v /hostVar:/containerVar:z"); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], "/hostTmp:/containerTmp:Z", "/hostVar:/containerVar:z") != nil { 122 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp:Z -v /hostVar:/containerVar:z` should mount-bind /hostTmp into /containeTmp and /hostVar into /hostContainer. Received %v", hostConfig.Binds) 123 } 124 125 if config, hostConfig := mustParse(t, "-v /hostTmp:/containerTmp -v /containerVar"); hostConfig.Binds == nil || len(hostConfig.Binds) > 1 || hostConfig.Binds[0] != "/hostTmp:/containerTmp" { 126 t.Fatalf("Error parsing volume flags, `-v /hostTmp:/containerTmp -v /containerVar` should mount-bind only /hostTmp into /containeTmp. Received %v", hostConfig.Binds) 127 } else if _, exists := config.Volumes["/containerVar"]; !exists { 128 t.Fatalf("Error parsing volume flags, `-v /containerVar` is missing from volumes. Received %v", config.Volumes) 129 } 130 131 if config, hostConfig := mustParse(t, ""); hostConfig.Binds != nil { 132 t.Fatalf("Error parsing volume flags, without volume, nothing should be mount-binded. Received %v", hostConfig.Binds) 133 } else if len(config.Volumes) != 0 { 134 t.Fatalf("Error parsing volume flags, without volume, no volume should be present. Received %v", config.Volumes) 135 } 136 137 if _, _, err := parse(t, "-v /"); err == nil { 138 t.Fatalf("Expected error, but got none") 139 } 140 141 if _, _, err := parse(t, "-v /:/"); err == nil { 142 t.Fatalf("Error parsing volume flags, `-v /:/` should fail but didn't") 143 } 144 if _, _, err := parse(t, "-v"); err == nil { 145 t.Fatalf("Error parsing volume flags, `-v` should fail but didn't") 146 } 147 if _, _, err := parse(t, "-v /tmp:"); err == nil { 148 t.Fatalf("Error parsing volume flags, `-v /tmp:` should fail but didn't") 149 } 150 if _, _, err := parse(t, "-v /tmp:ro"); err == nil { 151 t.Fatalf("Error parsing volume flags, `-v /tmp:ro` should fail but didn't") 152 } 153 if _, _, err := parse(t, "-v /tmp::"); err == nil { 154 t.Fatalf("Error parsing volume flags, `-v /tmp::` should fail but didn't") 155 } 156 if _, _, err := parse(t, "-v :"); err == nil { 157 t.Fatalf("Error parsing volume flags, `-v :` should fail but didn't") 158 } 159 if _, _, err := parse(t, "-v ::"); err == nil { 160 t.Fatalf("Error parsing volume flags, `-v ::` should fail but didn't") 161 } 162 if _, _, err := parse(t, "-v /tmp:/tmp:/tmp:/tmp"); err == nil { 163 t.Fatalf("Error parsing volume flags, `-v /tmp:/tmp:/tmp:/tmp` should fail but didn't") 164 } 165 } 166 167 func TestCompare(t *testing.T) { 168 volumes1 := make(map[string]struct{}) 169 volumes1["/test1"] = struct{}{} 170 config1 := Config{ 171 PortSpecs: []string{"1111:1111", "2222:2222"}, 172 Env: []string{"VAR1=1", "VAR2=2"}, 173 Volumes: volumes1, 174 } 175 config3 := Config{ 176 PortSpecs: []string{"0000:0000", "2222:2222"}, 177 Env: []string{"VAR1=1", "VAR2=2"}, 178 Volumes: volumes1, 179 } 180 volumes2 := make(map[string]struct{}) 181 volumes2["/test2"] = struct{}{} 182 config5 := Config{ 183 PortSpecs: []string{"0000:0000", "2222:2222"}, 184 Env: []string{"VAR1=1", "VAR2=2"}, 185 Volumes: volumes2, 186 } 187 if Compare(&config1, &config3) { 188 t.Fatalf("Compare should return false, PortSpecs are different") 189 } 190 if Compare(&config1, &config5) { 191 t.Fatalf("Compare should return false, Volumes are different") 192 } 193 if !Compare(&config1, &config1) { 194 t.Fatalf("Compare should return true") 195 } 196 } 197 198 func TestMerge(t *testing.T) { 199 volumesImage := make(map[string]struct{}) 200 volumesImage["/test1"] = struct{}{} 201 volumesImage["/test2"] = struct{}{} 202 configImage := &Config{ 203 PortSpecs: []string{"1111:1111", "2222:2222"}, 204 Env: []string{"VAR1=1", "VAR2=2"}, 205 Volumes: volumesImage, 206 } 207 208 volumesUser := make(map[string]struct{}) 209 volumesUser["/test3"] = struct{}{} 210 configUser := &Config{ 211 PortSpecs: []string{"3333:2222", "3333:3333"}, 212 Env: []string{"VAR2=3", "VAR3=3"}, 213 Volumes: volumesUser, 214 } 215 216 if err := Merge(configUser, configImage); err != nil { 217 t.Error(err) 218 } 219 220 if len(configUser.ExposedPorts) != 3 { 221 t.Fatalf("Expected 3 ExposedPorts, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts)) 222 } 223 for portSpecs := range configUser.ExposedPorts { 224 if portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" { 225 t.Fatalf("Expected 1111 or 2222 or 3333, found %s", portSpecs) 226 } 227 } 228 if len(configUser.Env) != 3 { 229 t.Fatalf("Expected 3 env var, VAR1=1, VAR2=3 and VAR3=3, found %d", len(configUser.Env)) 230 } 231 for _, env := range configUser.Env { 232 if env != "VAR1=1" && env != "VAR2=3" && env != "VAR3=3" { 233 t.Fatalf("Expected VAR1=1 or VAR2=3 or VAR3=3, found %s", env) 234 } 235 } 236 237 if len(configUser.Volumes) != 3 { 238 t.Fatalf("Expected 3 volumes, /test1, /test2 and /test3, found %d", len(configUser.Volumes)) 239 } 240 for v := range configUser.Volumes { 241 if v != "/test1" && v != "/test2" && v != "/test3" { 242 t.Fatalf("Expected /test1 or /test2 or /test3, found %s", v) 243 } 244 } 245 246 ports, _, err := nat.ParsePortSpecs([]string{"0000"}) 247 if err != nil { 248 t.Error(err) 249 } 250 configImage2 := &Config{ 251 ExposedPorts: ports, 252 } 253 254 if err := Merge(configUser, configImage2); err != nil { 255 t.Error(err) 256 } 257 258 if len(configUser.ExposedPorts) != 4 { 259 t.Fatalf("Expected 4 ExposedPorts, 0000, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts)) 260 } 261 for portSpecs := range configUser.ExposedPorts { 262 if portSpecs.Port() != "0" && portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" { 263 t.Fatalf("Expected %q or %q or %q or %q, found %s", 0, 1111, 2222, 3333, portSpecs) 264 } 265 } 266 } 267 268 func TestDecodeContainerConfig(t *testing.T) { 269 fixtures := []struct { 270 file string 271 entrypoint *Entrypoint 272 }{ 273 {"fixtures/container_config_1_14.json", NewEntrypoint()}, 274 {"fixtures/container_config_1_17.json", NewEntrypoint("bash")}, 275 {"fixtures/container_config_1_19.json", NewEntrypoint("bash")}, 276 } 277 278 for _, f := range fixtures { 279 b, err := ioutil.ReadFile(f.file) 280 if err != nil { 281 t.Fatal(err) 282 } 283 284 c, h, err := DecodeContainerConfig(bytes.NewReader(b)) 285 if err != nil { 286 t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err)) 287 } 288 289 if c.Image != "ubuntu" { 290 t.Fatalf("Expected ubuntu image, found %s\n", c.Image) 291 } 292 293 if c.Entrypoint.Len() != f.entrypoint.Len() { 294 t.Fatalf("Expected %v, found %v\n", f.entrypoint, c.Entrypoint) 295 } 296 297 if h.Memory != 1000 { 298 t.Fatalf("Expected memory to be 1000, found %d\n", h.Memory) 299 } 300 } 301 }