image_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package formatter
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. "testing"
  7. "time"
  8. "github.com/docker/docker/api/types"
  9. "github.com/docker/docker/pkg/stringid"
  10. )
  11. func TestImageContext(t *testing.T) {
  12. imageID := stringid.GenerateRandomID()
  13. unix := time.Now().Unix()
  14. var ctx imageContext
  15. cases := []struct {
  16. imageCtx imageContext
  17. expValue string
  18. expHeader string
  19. call func() string
  20. }{
  21. {imageContext{
  22. i: types.Image{ID: imageID},
  23. trunc: true,
  24. }, stringid.TruncateID(imageID), imageIDHeader, ctx.ID},
  25. {imageContext{
  26. i: types.Image{ID: imageID},
  27. trunc: false,
  28. }, imageID, imageIDHeader, ctx.ID},
  29. {imageContext{
  30. i: types.Image{Size: 10},
  31. trunc: true,
  32. }, "10 B", sizeHeader, ctx.Size},
  33. {imageContext{
  34. i: types.Image{Created: unix},
  35. trunc: true,
  36. }, time.Unix(unix, 0).String(), createdAtHeader, ctx.CreatedAt},
  37. // FIXME
  38. // {imageContext{
  39. // i: types.Image{Created: unix},
  40. // trunc: true,
  41. // }, units.HumanDuration(time.Unix(unix, 0)), createdSinceHeader, ctx.CreatedSince},
  42. {imageContext{
  43. i: types.Image{},
  44. repo: "busybox",
  45. }, "busybox", repositoryHeader, ctx.Repository},
  46. {imageContext{
  47. i: types.Image{},
  48. tag: "latest",
  49. }, "latest", tagHeader, ctx.Tag},
  50. {imageContext{
  51. i: types.Image{},
  52. digest: "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a",
  53. }, "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", digestHeader, ctx.Digest},
  54. }
  55. for _, c := range cases {
  56. ctx = c.imageCtx
  57. v := c.call()
  58. if strings.Contains(v, ",") {
  59. compareMultipleValues(t, v, c.expValue)
  60. } else if v != c.expValue {
  61. t.Fatalf("Expected %s, was %s\n", c.expValue, v)
  62. }
  63. h := ctx.fullHeader()
  64. if h != c.expHeader {
  65. t.Fatalf("Expected %s, was %s\n", c.expHeader, h)
  66. }
  67. }
  68. }
  69. func TestImageContextWrite(t *testing.T) {
  70. unixTime := time.Now().AddDate(0, 0, -1).Unix()
  71. expectedTime := time.Unix(unixTime, 0).String()
  72. contexts := []struct {
  73. context ImageContext
  74. expected string
  75. }{
  76. // Errors
  77. {
  78. ImageContext{
  79. Context: Context{
  80. Format: "{{InvalidFunction}}",
  81. },
  82. },
  83. `Template parsing error: template: :1: function "InvalidFunction" not defined
  84. `,
  85. },
  86. {
  87. ImageContext{
  88. Context: Context{
  89. Format: "{{nil}}",
  90. },
  91. },
  92. `Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
  93. `,
  94. },
  95. // Table Format
  96. {
  97. ImageContext{
  98. Context: Context{
  99. Format: "table",
  100. },
  101. },
  102. `REPOSITORY TAG IMAGE ID CREATED SIZE
  103. image tag1 imageID1 24 hours ago 0 B
  104. image tag2 imageID2 24 hours ago 0 B
  105. <none> <none> imageID3 24 hours ago 0 B
  106. `,
  107. },
  108. {
  109. ImageContext{
  110. Context: Context{
  111. Format: "table {{.Repository}}",
  112. },
  113. },
  114. "REPOSITORY\nimage\nimage\n<none>\n",
  115. },
  116. {
  117. ImageContext{
  118. Context: Context{
  119. Format: "table {{.Repository}}",
  120. },
  121. Digest: true,
  122. },
  123. `REPOSITORY DIGEST
  124. image sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
  125. image <none>
  126. <none> <none>
  127. `,
  128. },
  129. {
  130. ImageContext{
  131. Context: Context{
  132. Format: "table {{.Repository}}",
  133. Quiet: true,
  134. },
  135. },
  136. "REPOSITORY\nimage\nimage\n<none>\n",
  137. },
  138. {
  139. ImageContext{
  140. Context: Context{
  141. Format: "table",
  142. Quiet: true,
  143. },
  144. },
  145. "imageID1\nimageID2\nimageID3\n",
  146. },
  147. {
  148. ImageContext{
  149. Context: Context{
  150. Format: "table",
  151. Quiet: false,
  152. },
  153. Digest: true,
  154. },
  155. `REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
  156. image tag1 sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf imageID1 24 hours ago 0 B
  157. image tag2 <none> imageID2 24 hours ago 0 B
  158. <none> <none> <none> imageID3 24 hours ago 0 B
  159. `,
  160. },
  161. {
  162. ImageContext{
  163. Context: Context{
  164. Format: "table",
  165. Quiet: true,
  166. },
  167. Digest: true,
  168. },
  169. "imageID1\nimageID2\nimageID3\n",
  170. },
  171. // Raw Format
  172. {
  173. ImageContext{
  174. Context: Context{
  175. Format: "raw",
  176. },
  177. },
  178. fmt.Sprintf(`repository: image
  179. tag: tag1
  180. image_id: imageID1
  181. created_at: %s
  182. virtual_size: 0 B
  183. repository: image
  184. tag: tag2
  185. image_id: imageID2
  186. created_at: %s
  187. virtual_size: 0 B
  188. repository: <none>
  189. tag: <none>
  190. image_id: imageID3
  191. created_at: %s
  192. virtual_size: 0 B
  193. `, expectedTime, expectedTime, expectedTime),
  194. },
  195. {
  196. ImageContext{
  197. Context: Context{
  198. Format: "raw",
  199. },
  200. Digest: true,
  201. },
  202. fmt.Sprintf(`repository: image
  203. tag: tag1
  204. digest: sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
  205. image_id: imageID1
  206. created_at: %s
  207. virtual_size: 0 B
  208. repository: image
  209. tag: tag2
  210. digest: <none>
  211. image_id: imageID2
  212. created_at: %s
  213. virtual_size: 0 B
  214. repository: <none>
  215. tag: <none>
  216. digest: <none>
  217. image_id: imageID3
  218. created_at: %s
  219. virtual_size: 0 B
  220. `, expectedTime, expectedTime, expectedTime),
  221. },
  222. {
  223. ImageContext{
  224. Context: Context{
  225. Format: "raw",
  226. Quiet: true,
  227. },
  228. },
  229. `image_id: imageID1
  230. image_id: imageID2
  231. image_id: imageID3
  232. `,
  233. },
  234. // Custom Format
  235. {
  236. ImageContext{
  237. Context: Context{
  238. Format: "{{.Repository}}",
  239. },
  240. },
  241. "image\nimage\n<none>\n",
  242. },
  243. {
  244. ImageContext{
  245. Context: Context{
  246. Format: "{{.Repository}}",
  247. },
  248. Digest: true,
  249. },
  250. "image\nimage\n<none>\n",
  251. },
  252. }
  253. for _, context := range contexts {
  254. images := []types.Image{
  255. {ID: "imageID1", RepoTags: []string{"image:tag1"}, RepoDigests: []string{"image@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf"}, Created: unixTime},
  256. {ID: "imageID2", RepoTags: []string{"image:tag2"}, Created: unixTime},
  257. {ID: "imageID3", RepoTags: []string{"<none>:<none>"}, RepoDigests: []string{"<none>@<none>"}, Created: unixTime},
  258. }
  259. out := bytes.NewBufferString("")
  260. context.context.Output = out
  261. context.context.Images = images
  262. context.context.Write()
  263. actual := out.String()
  264. if actual != context.expected {
  265. t.Fatalf("Expected \n%s, got \n%s", context.expected, actual)
  266. }
  267. // Clean buffer
  268. out.Reset()
  269. }
  270. }
  271. func TestImageContextWriteWithNoImage(t *testing.T) {
  272. out := bytes.NewBufferString("")
  273. images := []types.Image{}
  274. contexts := []struct {
  275. context ImageContext
  276. expected string
  277. }{
  278. {
  279. ImageContext{
  280. Context: Context{
  281. Format: "{{.Repository}}",
  282. Output: out,
  283. },
  284. },
  285. "",
  286. },
  287. {
  288. ImageContext{
  289. Context: Context{
  290. Format: "table {{.Repository}}",
  291. Output: out,
  292. },
  293. },
  294. "REPOSITORY\n",
  295. },
  296. {
  297. ImageContext{
  298. Context: Context{
  299. Format: "{{.Repository}}",
  300. Output: out,
  301. },
  302. Digest: true,
  303. },
  304. "",
  305. },
  306. {
  307. ImageContext{
  308. Context: Context{
  309. Format: "table {{.Repository}}",
  310. Output: out,
  311. },
  312. Digest: true,
  313. },
  314. "REPOSITORY DIGEST\n",
  315. },
  316. }
  317. for _, context := range contexts {
  318. context.context.Images = images
  319. context.context.Write()
  320. actual := out.String()
  321. if actual != context.expected {
  322. t.Fatalf("Expected \n%s, got \n%s", context.expected, actual)
  323. }
  324. // Clean buffer
  325. out.Reset()
  326. }
  327. }