github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/api/client/formatter/container_test.go (about) 1 package formatter 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/docker/docker/pkg/stringid" 11 "github.com/docker/engine-api/types" 12 ) 13 14 func TestContainerPsContext(t *testing.T) { 15 containerID := stringid.GenerateRandomID() 16 unix := time.Now().Add(-65 * time.Second).Unix() 17 18 var ctx containerContext 19 cases := []struct { 20 container types.Container 21 trunc bool 22 expValue string 23 expHeader string 24 call func() string 25 }{ 26 {types.Container{ID: containerID}, true, stringid.TruncateID(containerID), containerIDHeader, ctx.ID}, 27 {types.Container{ID: containerID}, false, containerID, containerIDHeader, ctx.ID}, 28 {types.Container{Names: []string{"/foobar_baz"}}, true, "foobar_baz", namesHeader, ctx.Names}, 29 {types.Container{Image: "ubuntu"}, true, "ubuntu", imageHeader, ctx.Image}, 30 {types.Container{Image: "verylongimagename"}, true, "verylongimagename", imageHeader, ctx.Image}, 31 {types.Container{Image: "verylongimagename"}, false, "verylongimagename", imageHeader, ctx.Image}, 32 {types.Container{ 33 Image: "a5a665ff33eced1e0803148700880edab4", 34 ImageID: "a5a665ff33eced1e0803148700880edab4269067ed77e27737a708d0d293fbf5", 35 }, 36 true, 37 "a5a665ff33ec", 38 imageHeader, 39 ctx.Image, 40 }, 41 {types.Container{ 42 Image: "a5a665ff33eced1e0803148700880edab4", 43 ImageID: "a5a665ff33eced1e0803148700880edab4269067ed77e27737a708d0d293fbf5", 44 }, 45 false, 46 "a5a665ff33eced1e0803148700880edab4", 47 imageHeader, 48 ctx.Image, 49 }, 50 {types.Container{Image: ""}, true, "<no image>", imageHeader, ctx.Image}, 51 {types.Container{Command: "sh -c 'ls -la'"}, true, `"sh -c 'ls -la'"`, commandHeader, ctx.Command}, 52 {types.Container{Created: unix}, true, time.Unix(unix, 0).String(), createdAtHeader, ctx.CreatedAt}, 53 {types.Container{Ports: []types.Port{{PrivatePort: 8080, PublicPort: 8080, Type: "tcp"}}}, true, "8080/tcp", portsHeader, ctx.Ports}, 54 {types.Container{Status: "RUNNING"}, true, "RUNNING", statusHeader, ctx.Status}, 55 {types.Container{SizeRw: 10}, true, "10 B", sizeHeader, ctx.Size}, 56 {types.Container{SizeRw: 10, SizeRootFs: 20}, true, "10 B (virtual 20 B)", sizeHeader, ctx.Size}, 57 {types.Container{}, true, "", labelsHeader, ctx.Labels}, 58 {types.Container{Labels: map[string]string{"cpu": "6", "storage": "ssd"}}, true, "cpu=6,storage=ssd", labelsHeader, ctx.Labels}, 59 {types.Container{Created: unix}, true, "About a minute", runningForHeader, ctx.RunningFor}, 60 {types.Container{ 61 Mounts: []types.MountPoint{ 62 { 63 Name: "733908409c91817de8e92b0096373245f329f19a88e2c849f02460e9b3d1c203", 64 Driver: "local", 65 Source: "/a/path", 66 }, 67 }, 68 }, true, "733908409c91817", mountsHeader, ctx.Mounts}, 69 {types.Container{ 70 Mounts: []types.MountPoint{ 71 { 72 Driver: "local", 73 Source: "/a/path", 74 }, 75 }, 76 }, false, "/a/path", mountsHeader, ctx.Mounts}, 77 {types.Container{ 78 Mounts: []types.MountPoint{ 79 { 80 Name: "733908409c91817de8e92b0096373245f329f19a88e2c849f02460e9b3d1c203", 81 Driver: "local", 82 Source: "/a/path", 83 }, 84 }, 85 }, false, "733908409c91817de8e92b0096373245f329f19a88e2c849f02460e9b3d1c203", mountsHeader, ctx.Mounts}, 86 } 87 88 for _, c := range cases { 89 ctx = containerContext{c: c.container, trunc: c.trunc} 90 v := c.call() 91 if strings.Contains(v, ",") { 92 compareMultipleValues(t, v, c.expValue) 93 } else if v != c.expValue { 94 t.Fatalf("Expected %s, was %s\n", c.expValue, v) 95 } 96 97 h := ctx.fullHeader() 98 if h != c.expHeader { 99 t.Fatalf("Expected %s, was %s\n", c.expHeader, h) 100 } 101 } 102 103 c1 := types.Container{Labels: map[string]string{"com.docker.swarm.swarm-id": "33", "com.docker.swarm.node_name": "ubuntu"}} 104 ctx = containerContext{c: c1, trunc: true} 105 106 sid := ctx.Label("com.docker.swarm.swarm-id") 107 node := ctx.Label("com.docker.swarm.node_name") 108 if sid != "33" { 109 t.Fatalf("Expected 33, was %s\n", sid) 110 } 111 112 if node != "ubuntu" { 113 t.Fatalf("Expected ubuntu, was %s\n", node) 114 } 115 116 h := ctx.fullHeader() 117 if h != "SWARM ID\tNODE NAME" { 118 t.Fatalf("Expected %s, was %s\n", "SWARM ID\tNODE NAME", h) 119 120 } 121 122 c2 := types.Container{} 123 ctx = containerContext{c: c2, trunc: true} 124 125 label := ctx.Label("anything.really") 126 if label != "" { 127 t.Fatalf("Expected an empty string, was %s", label) 128 } 129 130 ctx = containerContext{c: c2, trunc: true} 131 fullHeader := ctx.fullHeader() 132 if fullHeader != "" { 133 t.Fatalf("Expected fullHeader to be empty, was %s", fullHeader) 134 } 135 136 } 137 138 func TestContainerContextWrite(t *testing.T) { 139 unixTime := time.Now().AddDate(0, 0, -1).Unix() 140 expectedTime := time.Unix(unixTime, 0).String() 141 142 contexts := []struct { 143 context ContainerContext 144 expected string 145 }{ 146 // Errors 147 { 148 ContainerContext{ 149 Context: Context{ 150 Format: "{{InvalidFunction}}", 151 }, 152 }, 153 `Template parsing error: template: :1: function "InvalidFunction" not defined 154 `, 155 }, 156 { 157 ContainerContext{ 158 Context: Context{ 159 Format: "{{nil}}", 160 }, 161 }, 162 `Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command 163 `, 164 }, 165 // Table Format 166 { 167 ContainerContext{ 168 Context: Context{ 169 Format: "table", 170 }, 171 Size: true, 172 }, 173 `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 174 containerID1 ubuntu "" 24 hours ago foobar_baz 0 B 175 containerID2 ubuntu "" 24 hours ago foobar_bar 0 B 176 `, 177 }, 178 { 179 ContainerContext{ 180 Context: Context{ 181 Format: "table", 182 }, 183 }, 184 `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 185 containerID1 ubuntu "" 24 hours ago foobar_baz 186 containerID2 ubuntu "" 24 hours ago foobar_bar 187 `, 188 }, 189 { 190 ContainerContext{ 191 Context: Context{ 192 Format: "table {{.Image}}", 193 }, 194 }, 195 "IMAGE\nubuntu\nubuntu\n", 196 }, 197 { 198 ContainerContext{ 199 Context: Context{ 200 Format: "table {{.Image}}", 201 }, 202 Size: true, 203 }, 204 "IMAGE\nubuntu\nubuntu\n", 205 }, 206 { 207 ContainerContext{ 208 Context: Context{ 209 Format: "table {{.Image}}", 210 Quiet: true, 211 }, 212 }, 213 "IMAGE\nubuntu\nubuntu\n", 214 }, 215 { 216 ContainerContext{ 217 Context: Context{ 218 Format: "table", 219 Quiet: true, 220 }, 221 }, 222 "containerID1\ncontainerID2\n", 223 }, 224 // Raw Format 225 { 226 ContainerContext{ 227 Context: Context{ 228 Format: "raw", 229 }, 230 }, 231 fmt.Sprintf(`container_id: containerID1 232 image: ubuntu 233 command: "" 234 created_at: %s 235 status: 236 names: foobar_baz 237 labels: 238 ports: 239 240 container_id: containerID2 241 image: ubuntu 242 command: "" 243 created_at: %s 244 status: 245 names: foobar_bar 246 labels: 247 ports: 248 249 `, expectedTime, expectedTime), 250 }, 251 { 252 ContainerContext{ 253 Context: Context{ 254 Format: "raw", 255 }, 256 Size: true, 257 }, 258 fmt.Sprintf(`container_id: containerID1 259 image: ubuntu 260 command: "" 261 created_at: %s 262 status: 263 names: foobar_baz 264 labels: 265 ports: 266 size: 0 B 267 268 container_id: containerID2 269 image: ubuntu 270 command: "" 271 created_at: %s 272 status: 273 names: foobar_bar 274 labels: 275 ports: 276 size: 0 B 277 278 `, expectedTime, expectedTime), 279 }, 280 { 281 ContainerContext{ 282 Context: Context{ 283 Format: "raw", 284 Quiet: true, 285 }, 286 }, 287 "container_id: containerID1\ncontainer_id: containerID2\n", 288 }, 289 // Custom Format 290 { 291 ContainerContext{ 292 Context: Context{ 293 Format: "{{.Image}}", 294 }, 295 }, 296 "ubuntu\nubuntu\n", 297 }, 298 { 299 ContainerContext{ 300 Context: Context{ 301 Format: "{{.Image}}", 302 }, 303 Size: true, 304 }, 305 "ubuntu\nubuntu\n", 306 }, 307 } 308 309 for _, context := range contexts { 310 containers := []types.Container{ 311 {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime}, 312 {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime}, 313 } 314 out := bytes.NewBufferString("") 315 context.context.Output = out 316 context.context.Containers = containers 317 context.context.Write() 318 actual := out.String() 319 if actual != context.expected { 320 t.Fatalf("Expected \n%s, got \n%s", context.expected, actual) 321 } 322 // Clean buffer 323 out.Reset() 324 } 325 } 326 327 func TestContainerContextWriteWithNoContainers(t *testing.T) { 328 out := bytes.NewBufferString("") 329 containers := []types.Container{} 330 331 contexts := []struct { 332 context ContainerContext 333 expected string 334 }{ 335 { 336 ContainerContext{ 337 Context: Context{ 338 Format: "{{.Image}}", 339 Output: out, 340 }, 341 }, 342 "", 343 }, 344 { 345 ContainerContext{ 346 Context: Context{ 347 Format: "table {{.Image}}", 348 Output: out, 349 }, 350 }, 351 "IMAGE\n", 352 }, 353 { 354 ContainerContext{ 355 Context: Context{ 356 Format: "{{.Image}}", 357 Output: out, 358 }, 359 Size: true, 360 }, 361 "", 362 }, 363 { 364 ContainerContext{ 365 Context: Context{ 366 Format: "table {{.Image}}", 367 Output: out, 368 }, 369 Size: true, 370 }, 371 "IMAGE\n", 372 }, 373 { 374 ContainerContext{ 375 Context: Context{ 376 Format: "table {{.Image}}\t{{.Size}}", 377 Output: out, 378 }, 379 }, 380 "IMAGE SIZE\n", 381 }, 382 { 383 ContainerContext{ 384 Context: Context{ 385 Format: "table {{.Image}}\t{{.Size}}", 386 Output: out, 387 }, 388 Size: true, 389 }, 390 "IMAGE SIZE\n", 391 }, 392 } 393 394 for _, context := range contexts { 395 context.context.Containers = containers 396 context.context.Write() 397 actual := out.String() 398 if actual != context.expected { 399 t.Fatalf("Expected \n%s, got \n%s", context.expected, actual) 400 } 401 // Clean buffer 402 out.Reset() 403 } 404 }