web_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package web
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "net/http"
  9. "os"
  10. "path/filepath"
  11. "testing"
  12. "github.com/kellegous/go/context"
  13. )
  14. type env struct {
  15. mux *http.ServeMux
  16. dir string
  17. ctx *context.Context
  18. }
  19. func (e *env) destroy() {
  20. os.RemoveAll(e.dir)
  21. }
  22. func (e *env) getAPI(m *msg, name string) error {
  23. return e.callAPI(m, "GET", name, nil)
  24. }
  25. func (e *env) postAPI(m *msg, name, url string) error {
  26. r := struct {
  27. URL string `json:"url"`
  28. }{
  29. url,
  30. }
  31. var buf bytes.Buffer
  32. if err := json.NewEncoder(&buf).Encode(&r); err != nil {
  33. return err
  34. }
  35. return e.callAPI(m, "POST", name, &buf)
  36. }
  37. func (e *env) callAPI(m *msg, method, name string, body io.Reader) error {
  38. req, err := http.NewRequest(method, fmt.Sprintf("/api/url/%s", name), body)
  39. if err != nil {
  40. return err
  41. }
  42. res := mockResponse{
  43. header: map[string][]string{},
  44. }
  45. e.mux.ServeHTTP(&res, req)
  46. if err := json.NewDecoder(&res).Decode(&m); err != nil {
  47. return err
  48. }
  49. return nil
  50. }
  51. func newEnv() (*env, error) {
  52. dir, err := ioutil.TempDir("", "")
  53. if err != nil {
  54. return nil, err
  55. }
  56. ctx, err := context.Open(filepath.Join(dir, "data"))
  57. if err != nil {
  58. os.RemoveAll(dir)
  59. return nil, err
  60. }
  61. return &env{
  62. mux: allRoutes(ctx, ""),
  63. dir: dir,
  64. ctx: ctx,
  65. }, nil
  66. }
  67. func needEnv(t *testing.T) *env {
  68. e, err := newEnv()
  69. if err != nil {
  70. t.Fatal(err)
  71. }
  72. return e
  73. }
  74. type mockResponse struct {
  75. header http.Header
  76. bytes.Buffer
  77. status int
  78. }
  79. func (r *mockResponse) Header() http.Header {
  80. return r.header
  81. }
  82. func (r *mockResponse) WriteHeader(status int) {
  83. r.status = status
  84. }
  85. func assertJustOk(t *testing.T, m *msg) {
  86. if !m.Ok {
  87. t.Fatal("expected OK message, but it's not OK")
  88. }
  89. if m.Error != "" {
  90. t.Fatalf("expected no error, but got %s", m.Error)
  91. }
  92. if m.Route != nil {
  93. t.Fatalf("expected no route, got %v", m.Route)
  94. }
  95. }
  96. func assertOkWithRoute(t *testing.T, m *msg, url string) {
  97. if !m.Ok {
  98. t.Fatal("expected OK message, but it's not OK")
  99. }
  100. if m.Error != "" {
  101. t.Fatalf("expected no error, but got %s", m.Error)
  102. }
  103. if m.Route == nil {
  104. t.Fatalf("Route is nil, expected one with url of %s", url)
  105. }
  106. if m.Route.URL != url {
  107. t.Fatalf("Expected url of %s, got %s", url, m.Route.URL)
  108. }
  109. }
  110. func assertOkWithNamedRoute(t *testing.T, m *msg, name, url string) {
  111. assertOkWithRoute(t, m, url)
  112. if m.Route.Name != name {
  113. t.Fatalf("expected name %s, got %s", name, m.Route.Name)
  114. }
  115. }
  116. func TestAPIGetNotFound(t *testing.T) {
  117. e := needEnv(t)
  118. defer e.destroy()
  119. var m msg
  120. names := []string{"", "nothing", "nothing/there"}
  121. for _, name := range names {
  122. if err := e.getAPI(&m, name); err != nil {
  123. t.Fatal(err)
  124. }
  125. assertJustOk(t, &m)
  126. }
  127. }
  128. func TestAPIPutThenGet(t *testing.T) {
  129. e := needEnv(t)
  130. defer e.destroy()
  131. var pm msg
  132. if err := e.postAPI(&pm, "xxx", "http://ex.com/"); err != nil {
  133. t.Fatal(err)
  134. }
  135. assertOkWithRoute(t, &pm, "http://ex.com/")
  136. var gm msg
  137. if err := e.getAPI(&gm, "xxx"); err != nil {
  138. t.Fatal(err)
  139. }
  140. assertOkWithNamedRoute(t, &gm, "xxx", "http://ex.com/")
  141. }
  142. func TestAPIDel(t *testing.T) {
  143. e := needEnv(t)
  144. defer e.destroy()
  145. var am msg
  146. if err := e.postAPI(&am, "yyy", ""); err != nil {
  147. t.Fatal(err)
  148. }
  149. assertJustOk(t, &am)
  150. var bm msg
  151. if err := e.postAPI(&bm, "yyy", "https://a.com/"); err != nil {
  152. t.Fatal(err)
  153. }
  154. assertOkWithNamedRoute(t, &bm, "yyy", "https://a.com/")
  155. var cm msg
  156. if err := e.postAPI(&cm, "yyy", ""); err != nil {
  157. t.Fatal(err)
  158. }
  159. assertJustOk(t, &cm)
  160. var dm msg
  161. if err := e.getAPI(&dm, "yyy"); err != nil {
  162. t.Fatal(err)
  163. }
  164. assertJustOk(t, &dm)
  165. }
  166. func TestAPIPutThenGetAuto(t *testing.T) {
  167. e := needEnv(t)
  168. defer e.destroy()
  169. var am msg
  170. if err := e.postAPI(&am, "", "http://b.com/"); err != nil {
  171. t.Fatal(err)
  172. }
  173. assertOkWithRoute(t, &am, "http://b.com/")
  174. var bm msg
  175. if err := e.getAPI(&bm, am.Route.Name); err != nil {
  176. t.Fatal(err)
  177. }
  178. assertOkWithNamedRoute(t, &bm, am.Route.Name, "http://b.com/")
  179. }