jsonmessage_test.go 6.5 KB

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