stats_test.go 6.2 KB

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