stats_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package formatter
  2. import (
  3. "bytes"
  4. "testing"
  5. "github.com/docker/docker/pkg/stringid"
  6. "github.com/docker/docker/pkg/testutil/assert"
  7. )
  8. func TestContainerStatsContext(t *testing.T) {
  9. containerID := stringid.GenerateRandomID()
  10. var ctx containerStatsContext
  11. tt := []struct {
  12. stats StatsEntry
  13. osType string
  14. expValue string
  15. expHeader string
  16. call func() string
  17. }{
  18. {StatsEntry{Container: containerID}, "", containerID, containerHeader, ctx.Container},
  19. {StatsEntry{CPUPercentage: 5.5}, "", "5.50%", cpuPercHeader, ctx.CPUPerc},
  20. {StatsEntry{CPUPercentage: 5.5, IsInvalid: true}, "", "--", cpuPercHeader, ctx.CPUPerc},
  21. {StatsEntry{NetworkRx: 0.31, NetworkTx: 12.3}, "", "0.31B / 12.3B", netIOHeader, ctx.NetIO},
  22. {StatsEntry{NetworkRx: 0.31, NetworkTx: 12.3, IsInvalid: true}, "", "--", netIOHeader, ctx.NetIO},
  23. {StatsEntry{BlockRead: 0.1, BlockWrite: 2.3}, "", "0.1B / 2.3B", blockIOHeader, ctx.BlockIO},
  24. {StatsEntry{BlockRead: 0.1, BlockWrite: 2.3, IsInvalid: true}, "", "--", blockIOHeader, ctx.BlockIO},
  25. {StatsEntry{MemoryPercentage: 10.2}, "", "10.20%", memPercHeader, ctx.MemPerc},
  26. {StatsEntry{MemoryPercentage: 10.2, IsInvalid: true}, "", "--", memPercHeader, ctx.MemPerc},
  27. {StatsEntry{MemoryPercentage: 10.2}, "windows", "--", memPercHeader, ctx.MemPerc},
  28. {StatsEntry{Memory: 24, MemoryLimit: 30}, "", "24B / 30B", memUseHeader, ctx.MemUsage},
  29. {StatsEntry{Memory: 24, MemoryLimit: 30, IsInvalid: true}, "", "-- / --", memUseHeader, ctx.MemUsage},
  30. {StatsEntry{Memory: 24, MemoryLimit: 30}, "windows", "24B", winMemUseHeader, ctx.MemUsage},
  31. {StatsEntry{PidsCurrent: 10}, "", "10", pidsHeader, ctx.PIDs},
  32. {StatsEntry{PidsCurrent: 10, IsInvalid: true}, "", "--", pidsHeader, ctx.PIDs},
  33. {StatsEntry{PidsCurrent: 10}, "windows", "--", pidsHeader, ctx.PIDs},
  34. }
  35. for _, te := range tt {
  36. ctx = containerStatsContext{s: te.stats, os: te.osType}
  37. if v := te.call(); v != te.expValue {
  38. t.Fatalf("Expected %q, got %q", te.expValue, v)
  39. }
  40. h := ctx.FullHeader()
  41. if h != te.expHeader {
  42. t.Fatalf("Expected %q, got %q", te.expHeader, h)
  43. }
  44. }
  45. }
  46. func TestContainerStatsContextWrite(t *testing.T) {
  47. tt := []struct {
  48. context Context
  49. expected string
  50. }{
  51. {
  52. Context{Format: "{{InvalidFunction}}"},
  53. `Template parsing error: template: :1: function "InvalidFunction" not defined
  54. `,
  55. },
  56. {
  57. Context{Format: "{{nil}}"},
  58. `Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
  59. `,
  60. },
  61. {
  62. Context{Format: "table {{.MemUsage}}"},
  63. `MEM USAGE / LIMIT
  64. 20B / 20B
  65. -- / --
  66. `,
  67. },
  68. {
  69. Context{Format: "{{.Container}} {{.ID}} {{.Name}}"},
  70. `container1 abcdef foo
  71. container2 --
  72. `,
  73. },
  74. {
  75. Context{Format: "{{.Container}} {{.CPUPerc}}"},
  76. `container1 20.00%
  77. container2 --
  78. `,
  79. },
  80. }
  81. for _, te := range tt {
  82. stats := []StatsEntry{
  83. {
  84. Container: "container1",
  85. ID: "abcdef",
  86. Name: "/foo",
  87. CPUPercentage: 20,
  88. Memory: 20,
  89. MemoryLimit: 20,
  90. MemoryPercentage: 20,
  91. NetworkRx: 20,
  92. NetworkTx: 20,
  93. BlockRead: 20,
  94. BlockWrite: 20,
  95. PidsCurrent: 2,
  96. IsInvalid: false,
  97. },
  98. {
  99. Container: "container2",
  100. CPUPercentage: 30,
  101. Memory: 30,
  102. MemoryLimit: 30,
  103. MemoryPercentage: 30,
  104. NetworkRx: 30,
  105. NetworkTx: 30,
  106. BlockRead: 30,
  107. BlockWrite: 30,
  108. PidsCurrent: 3,
  109. IsInvalid: true,
  110. },
  111. }
  112. var out bytes.Buffer
  113. te.context.Output = &out
  114. err := ContainerStatsWrite(te.context, stats, "linux")
  115. if err != nil {
  116. assert.Error(t, err, te.expected)
  117. } else {
  118. assert.Equal(t, out.String(), te.expected)
  119. }
  120. }
  121. }
  122. func TestContainerStatsContextWriteWindows(t *testing.T) {
  123. tt := []struct {
  124. context Context
  125. expected string
  126. }{
  127. {
  128. Context{Format: "table {{.MemUsage}}"},
  129. `PRIV WORKING SET
  130. 20B
  131. -- / --
  132. `,
  133. },
  134. {
  135. Context{Format: "{{.Container}} {{.CPUPerc}}"},
  136. `container1 20.00%
  137. container2 --
  138. `,
  139. },
  140. {
  141. Context{Format: "{{.Container}} {{.MemPerc}} {{.PIDs}}"},
  142. `container1 -- --
  143. container2 -- --
  144. `,
  145. },
  146. }
  147. for _, te := range tt {
  148. stats := []StatsEntry{
  149. {
  150. Container: "container1",
  151. CPUPercentage: 20,
  152. Memory: 20,
  153. MemoryLimit: 20,
  154. MemoryPercentage: 20,
  155. NetworkRx: 20,
  156. NetworkTx: 20,
  157. BlockRead: 20,
  158. BlockWrite: 20,
  159. PidsCurrent: 2,
  160. IsInvalid: false,
  161. },
  162. {
  163. Container: "container2",
  164. CPUPercentage: 30,
  165. Memory: 30,
  166. MemoryLimit: 30,
  167. MemoryPercentage: 30,
  168. NetworkRx: 30,
  169. NetworkTx: 30,
  170. BlockRead: 30,
  171. BlockWrite: 30,
  172. PidsCurrent: 3,
  173. IsInvalid: true,
  174. },
  175. }
  176. var out bytes.Buffer
  177. te.context.Output = &out
  178. err := ContainerStatsWrite(te.context, stats, "windows")
  179. if err != nil {
  180. assert.Error(t, err, te.expected)
  181. } else {
  182. assert.Equal(t, out.String(), te.expected)
  183. }
  184. }
  185. }
  186. func TestContainerStatsContextWriteWithNoStats(t *testing.T) {
  187. var out bytes.Buffer
  188. contexts := []struct {
  189. context Context
  190. expected string
  191. }{
  192. {
  193. Context{
  194. Format: "{{.Container}}",
  195. Output: &out,
  196. },
  197. "",
  198. },
  199. {
  200. Context{
  201. Format: "table {{.Container}}",
  202. Output: &out,
  203. },
  204. "CONTAINER\n",
  205. },
  206. {
  207. Context{
  208. Format: "table {{.Container}}\t{{.CPUPerc}}",
  209. Output: &out,
  210. },
  211. "CONTAINER CPU %\n",
  212. },
  213. }
  214. for _, context := range contexts {
  215. ContainerStatsWrite(context.context, []StatsEntry{}, "linux")
  216. assert.Equal(t, context.expected, out.String())
  217. // Clean buffer
  218. out.Reset()
  219. }
  220. }
  221. func TestContainerStatsContextWriteWithNoStatsWindows(t *testing.T) {
  222. var out bytes.Buffer
  223. contexts := []struct {
  224. context Context
  225. expected string
  226. }{
  227. {
  228. Context{
  229. Format: "{{.Container}}",
  230. Output: &out,
  231. },
  232. "",
  233. },
  234. {
  235. Context{
  236. Format: "table {{.Container}}\t{{.MemUsage}}",
  237. Output: &out,
  238. },
  239. "CONTAINER PRIV WORKING SET\n",
  240. },
  241. {
  242. Context{
  243. Format: "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}",
  244. Output: &out,
  245. },
  246. "CONTAINER CPU % PRIV WORKING SET\n",
  247. },
  248. }
  249. for _, context := range contexts {
  250. ContainerStatsWrite(context.context, []StatsEntry{}, "windows")
  251. assert.Equal(t, out.String(), context.expected)
  252. // Clean buffer
  253. out.Reset()
  254. }
  255. }