http_test.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. package protocol
  2. import (
  3. "errors"
  4. "log"
  5. "net/http"
  6. "net/http/httptest"
  7. "testing"
  8. "time"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestHTTPError_Error(t *testing.T) {
  12. err := HTTPError{StatusCode: 400, Body: "bad request"}
  13. assert.Equal(t, "bad request", err.Error())
  14. }
  15. func TestHTTPProtocol_BadRequest(t *testing.T) {
  16. hp := HTTPProtocol{}
  17. err := hp.BadRequest("bad req")
  18. assert.Equal(t, http.StatusBadRequest, err.StatusCode)
  19. assert.Equal(t, "bad req", err.Body)
  20. }
  21. func TestHTTPProtocol_UnprocessableEntity(t *testing.T) {
  22. hp := HTTPProtocol{}
  23. err := hp.UnprocessableEntity("")
  24. assert.Equal(t, http.StatusUnprocessableEntity, err.StatusCode)
  25. assert.Equal(t, "Unprocessable Entity", err.Body)
  26. err2 := hp.UnprocessableEntity("custom")
  27. assert.Equal(t, "custom", err2.Body)
  28. }
  29. func TestHTTPProtocol_InternalServerError(t *testing.T) {
  30. hp := HTTPProtocol{}
  31. err := hp.InternalServerError("")
  32. assert.Equal(t, http.StatusInternalServerError, err.StatusCode)
  33. assert.Equal(t, "Internal Server Error", err.Body)
  34. err2 := hp.InternalServerError("custom")
  35. assert.Equal(t, "custom", err2.Body)
  36. }
  37. func TestHTTPProtocol_NotImplemented(t *testing.T) {
  38. hp := HTTPProtocol{}
  39. err := hp.NotImplemented("")
  40. assert.Equal(t, http.StatusNotImplemented, err.StatusCode)
  41. assert.Equal(t, "Not Implemented", err.Body)
  42. err2 := hp.NotImplemented("custom")
  43. assert.Equal(t, "custom", err2.Body)
  44. }
  45. func TestHTTPProtocol_Forbidden(t *testing.T) {
  46. hp := HTTPProtocol{}
  47. err := hp.Forbidden("")
  48. assert.Equal(t, http.StatusForbidden, err.StatusCode)
  49. assert.Equal(t, "Forbidden", err.Body)
  50. err2 := hp.Forbidden("custom")
  51. assert.Equal(t, "custom", err2.Body)
  52. }
  53. func TestHTTPProtocol_NotFound(t *testing.T) {
  54. hp := HTTPProtocol{}
  55. err := hp.NotFound()
  56. assert.Equal(t, http.StatusNotFound, err.StatusCode)
  57. assert.Equal(t, "Not Found", err.Body)
  58. }
  59. func TestHTTPProtocol_ToResponse(t *testing.T) {
  60. hp := HTTPProtocol{}
  61. resp := hp.ToResponse("data", nil)
  62. assert.Equal(t, http.StatusOK, resp.Code)
  63. assert.Equal(t, "data", resp.Data)
  64. resp2 := hp.ToResponse("data", errors.New("fail"))
  65. assert.Equal(t, http.StatusInternalServerError, resp2.Code)
  66. assert.Equal(t, "fail", resp2.Message)
  67. }
  68. func TestHTTPProtocol_WriteRawOK(t *testing.T) {
  69. hp := HTTPProtocol{}
  70. rw := httptest.NewRecorder()
  71. hp.WriteRawOK(rw)
  72. assert.Equal(t, http.StatusOK, rw.Code)
  73. assert.Equal(t, "application/json", rw.Header().Get("Content-Type"))
  74. assert.Equal(t, "0", rw.Header().Get("Content-Length"))
  75. }
  76. func TestHTTPProtocol_WriteRawNoContent(t *testing.T) {
  77. hp := HTTPProtocol{}
  78. rw := httptest.NewRecorder()
  79. hp.WriteRawNoContent(rw)
  80. assert.Equal(t, http.StatusNoContent, rw.Code)
  81. assert.Equal(t, "application/json", rw.Header().Get("Content-Type"))
  82. }
  83. func TestHTTPProtocol_WriteJSONData(t *testing.T) {
  84. hp := HTTPProtocol{}
  85. rw := httptest.NewRecorder()
  86. hp.WriteJSONData(rw, map[string]string{"foo": "bar"})
  87. assert.Equal(t, http.StatusOK, rw.Code)
  88. assert.Contains(t, rw.Body.String(), "foo")
  89. }
  90. func TestHTTPProtocol_WriteRawError(t *testing.T) {
  91. hp := HTTPProtocol{}
  92. rw := httptest.NewRecorder()
  93. hp.WriteRawError(rw, http.StatusBadRequest, "bad")
  94. assert.Equal(t, http.StatusBadRequest, rw.Code)
  95. assert.Equal(t, "text/plain; charset=utf-8", rw.Header().Get("Content-Type"))
  96. assert.Contains(t, rw.Body.String(), "bad")
  97. }
  98. func TestHTTPProtocol_WriteEncodedError(t *testing.T) {
  99. hp := HTTPProtocol{}
  100. rw := httptest.NewRecorder()
  101. hp.WriteEncodedError(rw, http.StatusBadRequest, map[string]string{"err": "bad"})
  102. assert.Equal(t, http.StatusBadRequest, rw.Code)
  103. assert.Contains(t, rw.Body.String(), "bad")
  104. }
  105. func TestHTTPProtocol_WriteData(t *testing.T) {
  106. hp := HTTPProtocol{}
  107. rw := httptest.NewRecorder()
  108. hp.WriteData(rw, map[string]string{"foo": "bar"})
  109. assert.Equal(t, http.StatusOK, rw.Code)
  110. assert.Contains(t, rw.Body.String(), "foo")
  111. }
  112. func TestHTTPProtocol_WriteDataWithWarning(t *testing.T) {
  113. hp := HTTPProtocol{}
  114. rw := httptest.NewRecorder()
  115. hp.WriteDataWithWarning(rw, map[string]string{"foo": "bar"}, "warn")
  116. assert.Equal(t, http.StatusOK, rw.Code)
  117. assert.Contains(t, rw.Body.String(), "warn")
  118. }
  119. func TestHTTPProtocol_WriteDataWithMessage(t *testing.T) {
  120. hp := HTTPProtocol{}
  121. rw := httptest.NewRecorder()
  122. hp.WriteDataWithMessage(rw, map[string]string{"foo": "bar"}, "msg")
  123. assert.Equal(t, http.StatusOK, rw.Code)
  124. assert.Contains(t, rw.Body.String(), "msg")
  125. }
  126. func TestHTTPProtocol_WriteDataWithMessageAndWarning(t *testing.T) {
  127. hp := HTTPProtocol{}
  128. rw := httptest.NewRecorder()
  129. hp.WriteDataWithMessageAndWarning(rw, map[string]string{"foo": "bar"}, "msg", "warn")
  130. assert.Equal(t, http.StatusOK, rw.Code)
  131. assert.Contains(t, rw.Body.String(), "msg")
  132. assert.Contains(t, rw.Body.String(), "warn")
  133. }
  134. func TestHTTPProtocol_WriteError(t *testing.T) {
  135. hp := HTTPProtocol{}
  136. rw := httptest.NewRecorder()
  137. hp.WriteError(rw, HTTPError{StatusCode: 400, Body: "fail"})
  138. assert.Equal(t, 400, rw.Code)
  139. body := rw.Body.String()
  140. log.Println("body: " + body)
  141. assert.Contains(t, body, "fail")
  142. }
  143. func TestHTTPProtocol_WriteResponse(t *testing.T) {
  144. hp := HTTPProtocol{}
  145. rw := httptest.NewRecorder()
  146. resp := &HTTPResponse{Code: 200, Data: "foo"}
  147. hp.WriteResponse(rw, resp)
  148. assert.Equal(t, 200, rw.Code)
  149. assert.Contains(t, rw.Body.String(), "foo")
  150. }
  151. func TestHTTPProtocol_WriteData_Structure(t *testing.T) {
  152. hp := HTTPProtocol{}
  153. rw := httptest.NewRecorder()
  154. data := map[string]string{"foo": "bar"}
  155. hp.WriteData(rw, data)
  156. assert.Equal(t, http.StatusOK, rw.Code)
  157. assert.Equal(t, "application/json", rw.Header().Get("Content-Type"))
  158. // Check the structure of the JSON response
  159. body := rw.Body.String()
  160. assert.Contains(t, body, "\"code\":200")
  161. assert.Contains(t, body, "\"data\":{\"foo\":\"bar\"}")
  162. assert.NotContains(t, body, "message")
  163. assert.NotContains(t, body, "warning")
  164. }
  165. func TestHTTPProtocol_HTTPResponse(t *testing.T) {
  166. proto := HTTP()
  167. // Test data, meta, warning, message
  168. data := struct {
  169. Apples int
  170. Bananas int
  171. }{
  172. Apples: 12,
  173. Bananas: 4,
  174. }
  175. meta := map[string]interface{}{
  176. "lastUpdated": time.Date(2025, time.September, 5, 13, 27, 3, 0, time.UTC),
  177. }
  178. warning := "warning"
  179. message := "message"
  180. // Test building an HTTPResponse
  181. var r *HTTPResponse
  182. r = proto.NewResponse()
  183. if r == nil || r.Code != 200 {
  184. t.Errorf("expected code %d, received %d", 200, r.Code)
  185. }
  186. r = proto.NewResponse(302).WithMessage("Moved Temporarily")
  187. if r == nil || r.Code != 302 || r.Message != "Moved Temporarily" {
  188. t.Errorf("expected %d %s, received %d %s", 302, "Moved Temporarily", r.Code, r.Message)
  189. }
  190. r = r.WithCode(200).WithData(data).WithMeta(meta).WithMessage(message).WithWarning(warning)
  191. if r == nil {
  192. t.Errorf("unexpected nil response")
  193. }
  194. if r.Code != 200 {
  195. t.Errorf("expected code %d, received %d", 200, r.Code)
  196. }
  197. if r.Data == nil {
  198. t.Error("unexpected nil data")
  199. }
  200. if r.Meta == nil {
  201. t.Error("unexpected nil meta")
  202. }
  203. if r.Message == "" {
  204. t.Error("unexpected empty message")
  205. }
  206. if r.Warning == "" {
  207. t.Error("unexpected empty warning")
  208. }
  209. // Test assigning attribtues to nil response
  210. r = nil
  211. r = r.WithCode(413)
  212. if r == nil || r.Code != 413 {
  213. t.Errorf("expected code %d, received %d", 413, r.Code)
  214. }
  215. r = nil
  216. r = r.WithData(data)
  217. if r == nil || r.Data == nil {
  218. t.Error("expected data, received nil")
  219. }
  220. r = nil
  221. r = r.WithMeta(meta)
  222. if r == nil || r.Meta == nil {
  223. t.Error("expected meta, received nil")
  224. }
  225. r = nil
  226. r = r.WithWarning(warning)
  227. if r == nil || r.Warning == "" {
  228. t.Error("expected warning, received empty string")
  229. }
  230. r = nil
  231. r = r.WithMessage(message)
  232. if r == nil || r.Message == "" {
  233. t.Error("expected message, received empty string")
  234. }
  235. }
  236. func TestHTTPProtocol_NewError(t *testing.T) {
  237. proto := HTTP()
  238. err := errors.New("error")
  239. httpErr := proto.NewError(err)
  240. if httpErr == nil || httpErr.StatusCode != 500 || httpErr.Body != "error" {
  241. t.Errorf("expected 500 error, received %d %s", httpErr.StatusCode, httpErr.Body)
  242. }
  243. httpErr = proto.NewError(err, 400)
  244. if httpErr == nil || httpErr.StatusCode != 400 || httpErr.Body != "error" {
  245. t.Errorf("expected 400 error, received %d %s", httpErr.StatusCode, httpErr.Body)
  246. }
  247. httpErr = proto.NewError(err, 400, 404)
  248. if httpErr == nil || httpErr.StatusCode != 400 || httpErr.Body != "error" {
  249. t.Errorf("expected 400 error, received %d %s", httpErr.StatusCode, httpErr.Body)
  250. }
  251. }