jsonmessage_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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().Unix()
  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,
  61. ID: "ID",
  62. From: "From",
  63. Status: "status",
  64. }: {
  65. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now, 0).Format(timeutils.RFC3339NanoFixed)),
  66. fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now, 0).Format(timeutils.RFC3339NanoFixed)),
  67. },
  68. // Stream over status
  69. JSONMessage{
  70. Status: "status",
  71. Stream: "stream",
  72. }: {
  73. "stream",
  74. "stream",
  75. },
  76. // With progress message
  77. JSONMessage{
  78. Status: "status",
  79. ProgressMessage: "progressMessage",
  80. }: {
  81. "status progressMessage",
  82. "status progressMessage",
  83. },
  84. // With progress, stream empty
  85. JSONMessage{
  86. Status: "status",
  87. Stream: "",
  88. Progress: &JSONProgress{Current: 1},
  89. }: {
  90. "",
  91. fmt.Sprintf("%c[2K\rstatus 1 B\r", 27),
  92. },
  93. }
  94. // The tests :)
  95. for jsonMessage, expectedMessages := range messages {
  96. // Without terminal
  97. data := bytes.NewBuffer([]byte{})
  98. if err := jsonMessage.Display(data, false); err != nil {
  99. t.Fatal(err)
  100. }
  101. if data.String() != expectedMessages[0] {
  102. t.Fatalf("Expected [%v], got [%v]", expectedMessages[0], data.String())
  103. }
  104. // With terminal
  105. data = bytes.NewBuffer([]byte{})
  106. if err := jsonMessage.Display(data, true); err != nil {
  107. t.Fatal(err)
  108. }
  109. if data.String() != expectedMessages[1] {
  110. t.Fatalf("Expected [%v], got [%v]", expectedMessages[1], data.String())
  111. }
  112. }
  113. }
  114. // Test JSONMessage with an Error. It will return an error with the text as error, not the meaning of the HTTP code.
  115. func TestJSONMessageDisplayWithJSONError(t *testing.T) {
  116. data := bytes.NewBuffer([]byte{})
  117. jsonMessage := JSONMessage{Error: &JSONError{404, "Can't find it"}}
  118. err := jsonMessage.Display(data, true)
  119. if err == nil || err.Error() != "Can't find it" {
  120. t.Fatalf("Expected a JSONError 404, got [%v]", err)
  121. }
  122. jsonMessage = JSONMessage{Error: &JSONError{401, "Anything"}}
  123. err = jsonMessage.Display(data, true)
  124. if err == nil || err.Error() != "Authentication is required." {
  125. t.Fatalf("Expected an error [Authentication is required.], got [%v]", err)
  126. }
  127. }
  128. func TestDisplayJSONMessagesStreamInvalidJSON(t *testing.T) {
  129. var (
  130. inFd uintptr
  131. )
  132. data := bytes.NewBuffer([]byte{})
  133. reader := strings.NewReader("This is not a 'valid' JSON []")
  134. inFd, _ = term.GetFdInfo(reader)
  135. if err := DisplayJSONMessagesStream(reader, data, inFd, false); err == nil && err.Error()[:17] != "invalid character" {
  136. t.Fatalf("Should have thrown an error (invalid character in ..), got [%v]", err)
  137. }
  138. }
  139. func TestDisplayJSONMessagesStream(t *testing.T) {
  140. var (
  141. inFd uintptr
  142. )
  143. messages := map[string][]string{
  144. // empty string
  145. "": {
  146. "",
  147. ""},
  148. // Without progress & ID
  149. "{ \"status\": \"status\" }": {
  150. "status\n",
  151. "status\n",
  152. },
  153. // Without progress, with ID
  154. "{ \"id\": \"ID\",\"status\": \"status\" }": {
  155. "ID: status\n",
  156. fmt.Sprintf("ID: status\n%c[%dB", 27, 0),
  157. },
  158. // With progress
  159. "{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": {
  160. "ID: status ProgressMessage",
  161. fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 0, 27, 0),
  162. },
  163. // With progressDetail
  164. "{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
  165. "", // progressbar is disabled in non-terminal
  166. fmt.Sprintf("\n%c[%dA%c[2K\rID: status 1 B\r%c[%dB", 27, 0, 27, 27, 0),
  167. },
  168. }
  169. for jsonMessage, expectedMessages := range messages {
  170. data := bytes.NewBuffer([]byte{})
  171. reader := strings.NewReader(jsonMessage)
  172. inFd, _ = term.GetFdInfo(reader)
  173. // Without terminal
  174. if err := DisplayJSONMessagesStream(reader, data, inFd, false); err != nil {
  175. t.Fatal(err)
  176. }
  177. if data.String() != expectedMessages[0] {
  178. t.Fatalf("Expected an [%v], got [%v]", expectedMessages[0], data.String())
  179. }
  180. // With terminal
  181. data = bytes.NewBuffer([]byte{})
  182. reader = strings.NewReader(jsonMessage)
  183. if err := DisplayJSONMessagesStream(reader, data, inFd, true); err != nil {
  184. t.Fatal(err)
  185. }
  186. if data.String() != expectedMessages[1] {
  187. t.Fatalf("Expected an [%v], got [%v]", expectedMessages[1], data.String())
  188. }
  189. }
  190. }