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