curly_test.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package restful
  2. import (
  3. "io"
  4. "net/http"
  5. "testing"
  6. )
  7. var requestPaths = []struct {
  8. // url with path (1) is handled by service with root (2) and remainder has value final (3)
  9. path, root string
  10. }{
  11. {"/", "/"},
  12. {"/p", "/p"},
  13. {"/p/x", "/p/{q}"},
  14. {"/q/x", "/q"},
  15. {"/p/x/", "/p/{q}"},
  16. {"/p/x/y", "/p/{q}"},
  17. {"/q/x/y", "/q"},
  18. {"/z/q", "/{p}/q"},
  19. {"/a/b/c/q", "/"},
  20. }
  21. // go test -v -test.run TestCurlyDetectWebService ...restful
  22. func TestCurlyDetectWebService(t *testing.T) {
  23. ws1 := new(WebService).Path("/")
  24. ws2 := new(WebService).Path("/p")
  25. ws3 := new(WebService).Path("/q")
  26. ws4 := new(WebService).Path("/p/q")
  27. ws5 := new(WebService).Path("/p/{q}")
  28. ws7 := new(WebService).Path("/{p}/q")
  29. var wss = []*WebService{ws1, ws2, ws3, ws4, ws5, ws7}
  30. for _, each := range wss {
  31. t.Logf("path=%s,toks=%v\n", each.pathExpr.Source, each.pathExpr.tokens)
  32. }
  33. router := CurlyRouter{}
  34. ok := true
  35. for i, fixture := range requestPaths {
  36. requestTokens := tokenizePath(fixture.path)
  37. who := router.detectWebService(requestTokens, wss)
  38. if who != nil && who.RootPath() != fixture.root {
  39. t.Logf("[line:%v] Unexpected dispatcher, expected:%v, actual:%v", i, fixture.root, who.RootPath())
  40. ok = false
  41. }
  42. }
  43. if !ok {
  44. t.Fail()
  45. }
  46. }
  47. var serviceDetects = []struct {
  48. path string
  49. found bool
  50. root string
  51. }{
  52. {"/a/b", true, "/{p}/{q}/{r}"},
  53. {"/p/q", true, "/p/q"},
  54. {"/q/p", true, "/q"},
  55. {"/", true, "/"},
  56. {"/p/q/r", true, "/p/q"},
  57. }
  58. // go test -v -test.run Test_detectWebService ...restful
  59. func Test_detectWebService(t *testing.T) {
  60. router := CurlyRouter{}
  61. ws1 := new(WebService).Path("/")
  62. ws2 := new(WebService).Path("/p")
  63. ws3 := new(WebService).Path("/q")
  64. ws4 := new(WebService).Path("/p/q")
  65. ws5 := new(WebService).Path("/p/{q}")
  66. ws6 := new(WebService).Path("/p/{q}/")
  67. ws7 := new(WebService).Path("/{p}/q")
  68. ws8 := new(WebService).Path("/{p}/{q}/{r}")
  69. var wss = []*WebService{ws8, ws7, ws6, ws5, ws4, ws3, ws2, ws1}
  70. for _, fix := range serviceDetects {
  71. requestPath := fix.path
  72. requestTokens := tokenizePath(requestPath)
  73. for _, ws := range wss {
  74. serviceTokens := ws.pathExpr.tokens
  75. matches, score := router.computeWebserviceScore(requestTokens, serviceTokens)
  76. t.Logf("req=%s,toks:%v,ws=%s,toks:%v,score=%d,matches=%v", requestPath, requestTokens, ws.RootPath(), serviceTokens, score, matches)
  77. }
  78. best := router.detectWebService(requestTokens, wss)
  79. if best != nil {
  80. if fix.found {
  81. t.Logf("best=%s", best.RootPath())
  82. } else {
  83. t.Fatalf("should have found:%s", fix.root)
  84. }
  85. }
  86. }
  87. }
  88. var routeMatchers = []struct {
  89. route string
  90. path string
  91. matches bool
  92. paramCount int
  93. staticCount int
  94. }{
  95. // route, request-path
  96. {"/a", "/a", true, 0, 1},
  97. {"/a", "/b", false, 0, 0},
  98. {"/a", "/b", false, 0, 0},
  99. {"/a/{b}/c/", "/a/2/c", true, 1, 2},
  100. {"/{a}/{b}/{c}/", "/a/b", false, 0, 0},
  101. {"/{x:*}", "/", false, 0, 0},
  102. {"/{x:*}", "/a", true, 1, 0},
  103. {"/{x:*}", "/a/b", true, 1, 0},
  104. {"/a/{x:*}", "/a/b", true, 1, 1},
  105. {"/a/{x:[A-Z][A-Z]}", "/a/ZX", true, 1, 1},
  106. {"/basepath/{resource:*}", "/basepath/some/other/location/test.xml", true, 1, 1},
  107. }
  108. // clear && go test -v -test.run Test_matchesRouteByPathTokens ...restful
  109. func Test_matchesRouteByPathTokens(t *testing.T) {
  110. router := CurlyRouter{}
  111. for i, each := range routeMatchers {
  112. routeToks := tokenizePath(each.route)
  113. reqToks := tokenizePath(each.path)
  114. matches, pCount, sCount := router.matchesRouteByPathTokens(routeToks, reqToks)
  115. if matches != each.matches {
  116. t.Fatalf("[%d] unexpected matches outcome route:%s, path:%s, matches:%v", i, each.route, each.path, matches)
  117. }
  118. if pCount != each.paramCount {
  119. t.Fatalf("[%d] unexpected paramCount got:%d want:%d ", i, pCount, each.paramCount)
  120. }
  121. if sCount != each.staticCount {
  122. t.Fatalf("[%d] unexpected staticCount got:%d want:%d ", i, sCount, each.staticCount)
  123. }
  124. }
  125. }
  126. // clear && go test -v -test.run TestExtractParameters_Wildcard1 ...restful
  127. func TestExtractParameters_Wildcard1(t *testing.T) {
  128. params := doExtractParams("/fixed/{var:*}", 2, "/fixed/remainder", t)
  129. if params["var"] != "remainder" {
  130. t.Errorf("parameter mismatch var: %s", params["var"])
  131. }
  132. }
  133. // clear && go test -v -test.run TestExtractParameters_Wildcard2 ...restful
  134. func TestExtractParameters_Wildcard2(t *testing.T) {
  135. params := doExtractParams("/fixed/{var:*}", 2, "/fixed/remain/der", t)
  136. if params["var"] != "remain/der" {
  137. t.Errorf("parameter mismatch var: %s", params["var"])
  138. }
  139. }
  140. // clear && go test -v -test.run TestExtractParameters_Wildcard3 ...restful
  141. func TestExtractParameters_Wildcard3(t *testing.T) {
  142. params := doExtractParams("/static/{var:*}", 2, "/static/test/sub/hi.html", t)
  143. if params["var"] != "test/sub/hi.html" {
  144. t.Errorf("parameter mismatch var: %s", params["var"])
  145. }
  146. }
  147. // clear && go test -v -test.run TestCurly_ISSUE_34 ...restful
  148. func TestCurly_ISSUE_34(t *testing.T) {
  149. ws1 := new(WebService).Path("/")
  150. ws1.Route(ws1.GET("/{type}/{id}").To(curlyDummy))
  151. ws1.Route(ws1.GET("/network/{id}").To(curlyDummy))
  152. croutes := CurlyRouter{}.selectRoutes(ws1, tokenizePath("/network/12"))
  153. if len(croutes) != 2 {
  154. t.Fatal("expected 2 routes")
  155. }
  156. if got, want := croutes[0].route.Path, "/network/{id}"; got != want {
  157. t.Errorf("got %v want %v", got, want)
  158. }
  159. }
  160. // clear && go test -v -test.run TestCurly_ISSUE_34_2 ...restful
  161. func TestCurly_ISSUE_34_2(t *testing.T) {
  162. ws1 := new(WebService)
  163. ws1.Route(ws1.GET("/network/{id}").To(curlyDummy))
  164. ws1.Route(ws1.GET("/{type}/{id}").To(curlyDummy))
  165. croutes := CurlyRouter{}.selectRoutes(ws1, tokenizePath("/network/12"))
  166. if len(croutes) != 2 {
  167. t.Fatal("expected 2 routes")
  168. }
  169. if got, want := croutes[0].route.Path, "/network/{id}"; got != want {
  170. t.Errorf("got %v want %v", got, want)
  171. }
  172. }
  173. // clear && go test -v -test.run TestCurly_JsonHtml ...restful
  174. func TestCurly_JsonHtml(t *testing.T) {
  175. ws1 := new(WebService)
  176. ws1.Path("/")
  177. ws1.Route(ws1.GET("/some.html").To(curlyDummy).Consumes("*/*").Produces("text/html"))
  178. req, _ := http.NewRequest("GET", "/some.html", nil)
  179. req.Header.Set("Accept", "application/json")
  180. _, route, err := CurlyRouter{}.SelectRoute([]*WebService{ws1}, req)
  181. if err == nil {
  182. t.Error("error expected")
  183. }
  184. if route != nil {
  185. t.Error("no route expected")
  186. }
  187. }
  188. // go test -v -test.run TestCurly_ISSUE_137 ...restful
  189. func TestCurly_ISSUE_137(t *testing.T) {
  190. ws1 := new(WebService)
  191. ws1.Route(ws1.GET("/hello").To(curlyDummy))
  192. ws1.Path("/")
  193. req, _ := http.NewRequest("GET", "/", nil)
  194. _, route, _ := CurlyRouter{}.SelectRoute([]*WebService{ws1}, req)
  195. t.Log(route)
  196. if route != nil {
  197. t.Error("no route expected")
  198. }
  199. }
  200. // go test -v -test.run TestCurly_ISSUE_137_2 ...restful
  201. func TestCurly_ISSUE_137_2(t *testing.T) {
  202. ws1 := new(WebService)
  203. ws1.Route(ws1.GET("/hello").To(curlyDummy))
  204. ws1.Path("/")
  205. req, _ := http.NewRequest("GET", "/hello/bob", nil)
  206. _, route, _ := CurlyRouter{}.SelectRoute([]*WebService{ws1}, req)
  207. t.Log(route)
  208. if route != nil {
  209. t.Errorf("no route expected, got %v", route)
  210. }
  211. }
  212. func curlyDummy(req *Request, resp *Response) { io.WriteString(resp.ResponseWriter, "curlyDummy") }