stats_test.go 5.7 KB

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