jsonmessage_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package jsonmessage
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. "testing"
  7. "time"
  8. "github.com/docker/docker/pkg/jsonlog"
  9. "github.com/docker/docker/pkg/term"
  10. )
  11. func TestError(t *testing.T) {
  12. je := JSONError{404, "Not found"}
  13. if je.Error() != "Not found" {
  14. t.Fatalf("Expected 'Not found' got '%s'", je.Error())
  15. }
  16. }
  17. func TestProgress(t *testing.T) {
  18. termsz, err := term.GetWinsize(0)
  19. if err != nil {
  20. // we can safely ignore the err here
  21. termsz = nil
  22. }
  23. jp := JSONProgress{}
  24. if jp.String() != "" {
  25. t.Fatalf("Expected empty string, got '%s'", jp.String())
  26. }
  27. expected := " 1 B"
  28. jp2 := JSONProgress{Current: 1}
  29. if jp2.String() != expected {
  30. t.Fatalf("Expected %q, got %q", expected, jp2.String())
  31. }
  32. expectedStart := "[==========> ] 20 B/100 B"
  33. if termsz != nil && termsz.Width <= 110 {
  34. expectedStart = " 20 B/100 B"
  35. }
  36. jp3 := JSONProgress{Current: 20, Total: 100, Start: time.Now().Unix()}
  37. // Just look at the start of the string
  38. // (the remaining time is really hard to test -_-)
  39. if jp3.String()[:len(expectedStart)] != expectedStart {
  40. t.Fatalf("Expected to start with %q, got %q", expectedStart, jp3.String())
  41. }
  42. expected = "[=========================> ] 50 B/100 B"
  43. if termsz != nil && termsz.Width <= 110 {
  44. expected = " 50 B/100 B"
  45. }
  46. jp4 := JSONProgress{Current: 50, Total: 100}
  47. if jp4.String() != expected {
  48. t.Fatalf("Expected %q, got %q", expected, jp4.String())
  49. }
  50. // this number can't be negative gh#7136
  51. expected = "[==================================================>] 50 B"
  52. if termsz != nil && termsz.Width <= 110 {
  53. expected = " 50 B"
  54. }
  55. jp5 := JSONProgress{Current: 50, Total: 40}
  56. if jp5.String() != expected {
  57. t.Fatalf("Expected %q, got %q", expected, jp5.String())
  58. }
  59. }
  60. func TestJSONMessageDisplay(t *testing.T) {
  61. now := time.Now()
  62. messages := map[JSONMessage][]string{
  63. // Empty
  64. JSONMessage{}: {"\n", "\n"},
  65. // Status
  66. JSONMessage{
  67. Status: "status",
  68. }: {
  69. "status\n",
  70. "status\n",
  71. },
  72. // General
  73. JSONMessage{
  74. Time: now.Unix(),
  75. ID: "ID",
  76. From: "From",
  77. Status: "status",
  78. }: {
  79. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)),
  80. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)),
  81. },
  82. // General, with nano precision time
  83. JSONMessage{
  84. TimeNano: now.UnixNano(),
  85. ID: "ID",
  86. From: "From",
  87. Status: "status",
  88. }: {
  89. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
  90. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
  91. },
  92. // General, with both times Nano is preferred
  93. JSONMessage{
  94. Time: now.Unix(),
  95. TimeNano: now.UnixNano(),
  96. ID: "ID",
  97. From: "From",
  98. Status: "status",
  99. }: {
  100. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
  101. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
  102. },
  103. // Stream over status
  104. JSONMessage{
  105. Status: "status",
  106. Stream: "stream",
  107. }: {
  108. "stream",
  109. "stream",
  110. },
  111. // With progress message
  112. JSONMessage{
  113. Status: "status",
  114. ProgressMessage: "progressMessage",
  115. }: {
  116. "status progressMessage",
  117. "status progressMessage",
  118. },
  119. // With progress, stream empty
  120. JSONMessage{
  121. Status: "status",
  122. Stream: "",
  123. Progress: &JSONProgress{Current: 1},
  124. }: {
  125. "",
  126. fmt.Sprintf("%c[2K\rstatus 1 B\r", 27),
  127. },
  128. }
  129. // The tests :)
  130. for jsonMessage, expectedMessages := range messages {
  131. // Without terminal
  132. data := bytes.NewBuffer([]byte{})
  133. if err := jsonMessage.Display(data, false); err != nil {
  134. t.Fatal(err)
  135. }
  136. if data.String() != expectedMessages[0] {
  137. t.Fatalf("Expected [%v], got [%v]", expectedMessages[0], data.String())
  138. }
  139. // With terminal
  140. data = bytes.NewBuffer([]byte{})
  141. if err := jsonMessage.Display(data, true); err != nil {
  142. t.Fatal(err)
  143. }
  144. if data.String() != expectedMessages[1] {
  145. t.Fatalf("Expected [%v], got [%v]", expectedMessages[1], data.String())
  146. }
  147. }
  148. }
  149. // Test JSONMessage with an Error. It will return an error with the text as error, not the meaning of the HTTP code.
  150. func TestJSONMessageDisplayWithJSONError(t *testing.T) {
  151. data := bytes.NewBuffer([]byte{})
  152. jsonMessage := JSONMessage{Error: &JSONError{404, "Can't find it"}}
  153. err := jsonMessage.Display(data, true)
  154. if err == nil || err.Error() != "Can't find it" {
  155. t.Fatalf("Expected a JSONError 404, got [%v]", err)
  156. }
  157. jsonMessage = JSONMessage{Error: &JSONError{401, "Anything"}}
  158. err = jsonMessage.Display(data, true)
  159. if err == nil || err.Error() != "Authentication is required." {
  160. t.Fatalf("Expected an error [Authentication is required.], got [%v]", err)
  161. }
  162. }
  163. func TestDisplayJSONMessagesStreamInvalidJSON(t *testing.T) {
  164. var (
  165. inFd uintptr
  166. )
  167. data := bytes.NewBuffer([]byte{})
  168. reader := strings.NewReader("This is not a 'valid' JSON []")
  169. inFd, _ = term.GetFdInfo(reader)
  170. if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err == nil && err.Error()[:17] != "invalid character" {
  171. t.Fatalf("Should have thrown an error (invalid character in ..), got [%v]", err)
  172. }
  173. }
  174. func TestDisplayJSONMessagesStream(t *testing.T) {
  175. var (
  176. inFd uintptr
  177. )
  178. messages := map[string][]string{
  179. // empty string
  180. "": {
  181. "",
  182. ""},
  183. // Without progress & ID
  184. "{ \"status\": \"status\" }": {
  185. "status\n",
  186. "status\n",
  187. },
  188. // Without progress, with ID
  189. "{ \"id\": \"ID\",\"status\": \"status\" }": {
  190. "ID: status\n",
  191. fmt.Sprintf("ID: status\n%c[%dB", 27, 0),
  192. },
  193. // With progress
  194. "{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": {
  195. "ID: status ProgressMessage",
  196. fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 0, 27, 0),
  197. },
  198. // With progressDetail
  199. "{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
  200. "", // progressbar is disabled in non-terminal
  201. fmt.Sprintf("\n%c[%dA%c[2K\rID: status 1 B\r%c[%dB", 27, 0, 27, 27, 0),
  202. },
  203. }
  204. for jsonMessage, expectedMessages := range messages {
  205. data := bytes.NewBuffer([]byte{})
  206. reader := strings.NewReader(jsonMessage)
  207. inFd, _ = term.GetFdInfo(reader)
  208. // Without terminal
  209. if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err != nil {
  210. t.Fatal(err)
  211. }
  212. if data.String() != expectedMessages[0] {
  213. t.Fatalf("Expected an [%v], got [%v]", expectedMessages[0], data.String())
  214. }
  215. // With terminal
  216. data = bytes.NewBuffer([]byte{})
  217. reader = strings.NewReader(jsonMessage)
  218. if err := DisplayJSONMessagesStream(reader, data, inFd, true, nil); err != nil {
  219. t.Fatal(err)
  220. }
  221. if data.String() != expectedMessages[1] {
  222. t.Fatalf("Expected an [%v], got [%v]", expectedMessages[1], data.String())
  223. }
  224. }
  225. }