old_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. // Old tests ported to Go1. This is a mess. Want to drop it one day.
  2. // Copyright 2011 Gorilla Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package mux
  6. import (
  7. "bytes"
  8. "net/http"
  9. "testing"
  10. )
  11. // ----------------------------------------------------------------------------
  12. // ResponseRecorder
  13. // ----------------------------------------------------------------------------
  14. // Copyright 2009 The Go Authors. All rights reserved.
  15. // Use of this source code is governed by a BSD-style
  16. // license that can be found in the LICENSE file.
  17. // ResponseRecorder is an implementation of http.ResponseWriter that
  18. // records its mutations for later inspection in tests.
  19. type ResponseRecorder struct {
  20. Code int // the HTTP response code from WriteHeader
  21. HeaderMap http.Header // the HTTP response headers
  22. Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
  23. Flushed bool
  24. }
  25. // NewRecorder returns an initialized ResponseRecorder.
  26. func NewRecorder() *ResponseRecorder {
  27. return &ResponseRecorder{
  28. HeaderMap: make(http.Header),
  29. Body: new(bytes.Buffer),
  30. }
  31. }
  32. // DefaultRemoteAddr is the default remote address to return in RemoteAddr if
  33. // an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
  34. const DefaultRemoteAddr = "1.2.3.4"
  35. // Header returns the response headers.
  36. func (rw *ResponseRecorder) Header() http.Header {
  37. return rw.HeaderMap
  38. }
  39. // Write always succeeds and writes to rw.Body, if not nil.
  40. func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
  41. if rw.Body != nil {
  42. rw.Body.Write(buf)
  43. }
  44. if rw.Code == 0 {
  45. rw.Code = http.StatusOK
  46. }
  47. return len(buf), nil
  48. }
  49. // WriteHeader sets rw.Code.
  50. func (rw *ResponseRecorder) WriteHeader(code int) {
  51. rw.Code = code
  52. }
  53. // Flush sets rw.Flushed to true.
  54. func (rw *ResponseRecorder) Flush() {
  55. rw.Flushed = true
  56. }
  57. // ----------------------------------------------------------------------------
  58. func TestRouteMatchers(t *testing.T) {
  59. var scheme, host, path, query, method string
  60. var headers map[string]string
  61. var resultVars map[bool]map[string]string
  62. router := NewRouter()
  63. router.NewRoute().Host("{var1}.google.com").
  64. Path("/{var2:[a-z]+}/{var3:[0-9]+}").
  65. Queries("foo", "bar").
  66. Methods("GET").
  67. Schemes("https").
  68. Headers("x-requested-with", "XMLHttpRequest")
  69. router.NewRoute().Host("www.{var4}.com").
  70. PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}").
  71. Queries("baz", "ding").
  72. Methods("POST").
  73. Schemes("http").
  74. Headers("Content-Type", "application/json")
  75. reset := func() {
  76. // Everything match.
  77. scheme = "https"
  78. host = "www.google.com"
  79. path = "/product/42"
  80. query = "?foo=bar"
  81. method = "GET"
  82. headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
  83. resultVars = map[bool]map[string]string{
  84. true: {"var1": "www", "var2": "product", "var3": "42"},
  85. false: {},
  86. }
  87. }
  88. reset2 := func() {
  89. // Everything match.
  90. scheme = "http"
  91. host = "www.google.com"
  92. path = "/foo/product/42/path/that/is/ignored"
  93. query = "?baz=ding"
  94. method = "POST"
  95. headers = map[string]string{"Content-Type": "application/json"}
  96. resultVars = map[bool]map[string]string{
  97. true: {"var4": "google", "var5": "product", "var6": "42"},
  98. false: {},
  99. }
  100. }
  101. match := func(shouldMatch bool) {
  102. url := scheme + "://" + host + path + query
  103. request, _ := http.NewRequest(method, url, nil)
  104. for key, value := range headers {
  105. request.Header.Add(key, value)
  106. }
  107. var routeMatch RouteMatch
  108. matched := router.Match(request, &routeMatch)
  109. if matched != shouldMatch {
  110. // Need better messages. :)
  111. if matched {
  112. t.Errorf("Should match.")
  113. } else {
  114. t.Errorf("Should not match.")
  115. }
  116. }
  117. if matched {
  118. currentRoute := routeMatch.Route
  119. if currentRoute == nil {
  120. t.Errorf("Expected a current route.")
  121. }
  122. vars := routeMatch.Vars
  123. expectedVars := resultVars[shouldMatch]
  124. if len(vars) != len(expectedVars) {
  125. t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
  126. }
  127. for name, value := range vars {
  128. if expectedVars[name] != value {
  129. t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
  130. }
  131. }
  132. }
  133. }
  134. // 1st route --------------------------------------------------------------
  135. // Everything match.
  136. reset()
  137. match(true)
  138. // Scheme doesn't match.
  139. reset()
  140. scheme = "http"
  141. match(false)
  142. // Host doesn't match.
  143. reset()
  144. host = "www.mygoogle.com"
  145. match(false)
  146. // Path doesn't match.
  147. reset()
  148. path = "/product/notdigits"
  149. match(false)
  150. // Query doesn't match.
  151. reset()
  152. query = "?foo=baz"
  153. match(false)
  154. // Method doesn't match.
  155. reset()
  156. method = "POST"
  157. match(false)
  158. // Header doesn't match.
  159. reset()
  160. headers = map[string]string{}
  161. match(false)
  162. // Everything match, again.
  163. reset()
  164. match(true)
  165. // 2nd route --------------------------------------------------------------
  166. // Everything match.
  167. reset2()
  168. match(true)
  169. // Scheme doesn't match.
  170. reset2()
  171. scheme = "https"
  172. match(false)
  173. // Host doesn't match.
  174. reset2()
  175. host = "sub.google.com"
  176. match(false)
  177. // Path doesn't match.
  178. reset2()
  179. path = "/bar/product/42"
  180. match(false)
  181. // Query doesn't match.
  182. reset2()
  183. query = "?foo=baz"
  184. match(false)
  185. // Method doesn't match.
  186. reset2()
  187. method = "GET"
  188. match(false)
  189. // Header doesn't match.
  190. reset2()
  191. headers = map[string]string{}
  192. match(false)
  193. // Everything match, again.
  194. reset2()
  195. match(true)
  196. }
  197. type headerMatcherTest struct {
  198. matcher headerMatcher
  199. headers map[string]string
  200. result bool
  201. }
  202. var headerMatcherTests = []headerMatcherTest{
  203. {
  204. matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
  205. headers: map[string]string{"X-Requested-With": "XMLHttpRequest"},
  206. result: true,
  207. },
  208. {
  209. matcher: headerMatcher(map[string]string{"x-requested-with": ""}),
  210. headers: map[string]string{"X-Requested-With": "anything"},
  211. result: true,
  212. },
  213. {
  214. matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
  215. headers: map[string]string{},
  216. result: false,
  217. },
  218. }
  219. type hostMatcherTest struct {
  220. matcher *Route
  221. url string
  222. vars map[string]string
  223. result bool
  224. }
  225. var hostMatcherTests = []hostMatcherTest{
  226. {
  227. matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
  228. url: "http://abc.def.ghi/",
  229. vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
  230. result: true,
  231. },
  232. {
  233. matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
  234. url: "http://a.b.c/",
  235. vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
  236. result: false,
  237. },
  238. }
  239. type methodMatcherTest struct {
  240. matcher methodMatcher
  241. method string
  242. result bool
  243. }
  244. var methodMatcherTests = []methodMatcherTest{
  245. {
  246. matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
  247. method: "GET",
  248. result: true,
  249. },
  250. {
  251. matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
  252. method: "POST",
  253. result: true,
  254. },
  255. {
  256. matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
  257. method: "PUT",
  258. result: true,
  259. },
  260. {
  261. matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
  262. method: "DELETE",
  263. result: false,
  264. },
  265. }
  266. type pathMatcherTest struct {
  267. matcher *Route
  268. url string
  269. vars map[string]string
  270. result bool
  271. }
  272. var pathMatcherTests = []pathMatcherTest{
  273. {
  274. matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
  275. url: "http://localhost:8080/123/456/789",
  276. vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
  277. result: true,
  278. },
  279. {
  280. matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
  281. url: "http://localhost:8080/1/2/3",
  282. vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
  283. result: false,
  284. },
  285. }
  286. type schemeMatcherTest struct {
  287. matcher schemeMatcher
  288. url string
  289. result bool
  290. }
  291. var schemeMatcherTests = []schemeMatcherTest{
  292. {
  293. matcher: schemeMatcher([]string{"http", "https"}),
  294. url: "http://localhost:8080/",
  295. result: true,
  296. },
  297. {
  298. matcher: schemeMatcher([]string{"http", "https"}),
  299. url: "https://localhost:8080/",
  300. result: true,
  301. },
  302. {
  303. matcher: schemeMatcher([]string{"https"}),
  304. url: "http://localhost:8080/",
  305. result: false,
  306. },
  307. {
  308. matcher: schemeMatcher([]string{"http"}),
  309. url: "https://localhost:8080/",
  310. result: false,
  311. },
  312. }
  313. type urlBuildingTest struct {
  314. route *Route
  315. vars []string
  316. url string
  317. }
  318. var urlBuildingTests = []urlBuildingTest{
  319. {
  320. route: new(Route).Host("foo.domain.com"),
  321. vars: []string{},
  322. url: "http://foo.domain.com",
  323. },
  324. {
  325. route: new(Route).Host("{subdomain}.domain.com"),
  326. vars: []string{"subdomain", "bar"},
  327. url: "http://bar.domain.com",
  328. },
  329. {
  330. route: new(Route).Host("foo.domain.com").Path("/articles"),
  331. vars: []string{},
  332. url: "http://foo.domain.com/articles",
  333. },
  334. {
  335. route: new(Route).Path("/articles"),
  336. vars: []string{},
  337. url: "/articles",
  338. },
  339. {
  340. route: new(Route).Path("/articles/{category}/{id:[0-9]+}"),
  341. vars: []string{"category", "technology", "id", "42"},
  342. url: "/articles/technology/42",
  343. },
  344. {
  345. route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"),
  346. vars: []string{"subdomain", "foo", "category", "technology", "id", "42"},
  347. url: "http://foo.domain.com/articles/technology/42",
  348. },
  349. }
  350. func TestHeaderMatcher(t *testing.T) {
  351. for _, v := range headerMatcherTests {
  352. request, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
  353. for key, value := range v.headers {
  354. request.Header.Add(key, value)
  355. }
  356. var routeMatch RouteMatch
  357. result := v.matcher.Match(request, &routeMatch)
  358. if result != v.result {
  359. if v.result {
  360. t.Errorf("%#v: should match %v.", v.matcher, request.Header)
  361. } else {
  362. t.Errorf("%#v: should not match %v.", v.matcher, request.Header)
  363. }
  364. }
  365. }
  366. }
  367. func TestHostMatcher(t *testing.T) {
  368. for _, v := range hostMatcherTests {
  369. request, _ := http.NewRequest("GET", v.url, nil)
  370. var routeMatch RouteMatch
  371. result := v.matcher.Match(request, &routeMatch)
  372. vars := routeMatch.Vars
  373. if result != v.result {
  374. if v.result {
  375. t.Errorf("%#v: should match %v.", v.matcher, v.url)
  376. } else {
  377. t.Errorf("%#v: should not match %v.", v.matcher, v.url)
  378. }
  379. }
  380. if result {
  381. if len(vars) != len(v.vars) {
  382. t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
  383. }
  384. for name, value := range vars {
  385. if v.vars[name] != value {
  386. t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
  387. }
  388. }
  389. } else {
  390. if len(vars) != 0 {
  391. t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
  392. }
  393. }
  394. }
  395. }
  396. func TestMethodMatcher(t *testing.T) {
  397. for _, v := range methodMatcherTests {
  398. request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil)
  399. var routeMatch RouteMatch
  400. result := v.matcher.Match(request, &routeMatch)
  401. if result != v.result {
  402. if v.result {
  403. t.Errorf("%#v: should match %v.", v.matcher, v.method)
  404. } else {
  405. t.Errorf("%#v: should not match %v.", v.matcher, v.method)
  406. }
  407. }
  408. }
  409. }
  410. func TestPathMatcher(t *testing.T) {
  411. for _, v := range pathMatcherTests {
  412. request, _ := http.NewRequest("GET", v.url, nil)
  413. var routeMatch RouteMatch
  414. result := v.matcher.Match(request, &routeMatch)
  415. vars := routeMatch.Vars
  416. if result != v.result {
  417. if v.result {
  418. t.Errorf("%#v: should match %v.", v.matcher, v.url)
  419. } else {
  420. t.Errorf("%#v: should not match %v.", v.matcher, v.url)
  421. }
  422. }
  423. if result {
  424. if len(vars) != len(v.vars) {
  425. t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
  426. }
  427. for name, value := range vars {
  428. if v.vars[name] != value {
  429. t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
  430. }
  431. }
  432. } else {
  433. if len(vars) != 0 {
  434. t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
  435. }
  436. }
  437. }
  438. }
  439. func TestSchemeMatcher(t *testing.T) {
  440. for _, v := range schemeMatcherTests {
  441. request, _ := http.NewRequest("GET", v.url, nil)
  442. var routeMatch RouteMatch
  443. result := v.matcher.Match(request, &routeMatch)
  444. if result != v.result {
  445. if v.result {
  446. t.Errorf("%#v: should match %v.", v.matcher, v.url)
  447. } else {
  448. t.Errorf("%#v: should not match %v.", v.matcher, v.url)
  449. }
  450. }
  451. }
  452. }
  453. func TestUrlBuilding(t *testing.T) {
  454. for _, v := range urlBuildingTests {
  455. u, _ := v.route.URL(v.vars...)
  456. url := u.String()
  457. if url != v.url {
  458. t.Errorf("expected %v, got %v", v.url, url)
  459. /*
  460. reversePath := ""
  461. reverseHost := ""
  462. if v.route.pathTemplate != nil {
  463. reversePath = v.route.pathTemplate.Reverse
  464. }
  465. if v.route.hostTemplate != nil {
  466. reverseHost = v.route.hostTemplate.Reverse
  467. }
  468. t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost)
  469. */
  470. }
  471. }
  472. ArticleHandler := func(w http.ResponseWriter, r *http.Request) {
  473. }
  474. router := NewRouter()
  475. router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")
  476. url, _ := router.Get("article").URL("category", "technology", "id", "42")
  477. expected := "/articles/technology/42"
  478. if url.String() != expected {
  479. t.Errorf("Expected %v, got %v", expected, url.String())
  480. }
  481. }
  482. func TestMatchedRouteName(t *testing.T) {
  483. routeName := "stock"
  484. router := NewRouter()
  485. route := router.NewRoute().Path("/products/").Name(routeName)
  486. url := "http://www.domain.com/products/"
  487. request, _ := http.NewRequest("GET", url, nil)
  488. var rv RouteMatch
  489. ok := router.Match(request, &rv)
  490. if !ok || rv.Route != route {
  491. t.Errorf("Expected same route, got %+v.", rv.Route)
  492. }
  493. retName := rv.Route.GetName()
  494. if retName != routeName {
  495. t.Errorf("Expected %q, got %q.", routeName, retName)
  496. }
  497. }
  498. func TestSubRouting(t *testing.T) {
  499. // Example from docs.
  500. router := NewRouter()
  501. subrouter := router.NewRoute().Host("www.domain.com").Subrouter()
  502. route := subrouter.NewRoute().Path("/products/").Name("products")
  503. url := "http://www.domain.com/products/"
  504. request, _ := http.NewRequest("GET", url, nil)
  505. var rv RouteMatch
  506. ok := router.Match(request, &rv)
  507. if !ok || rv.Route != route {
  508. t.Errorf("Expected same route, got %+v.", rv.Route)
  509. }
  510. u, _ := router.Get("products").URL()
  511. builtUrl := u.String()
  512. // Yay, subroute aware of the domain when building!
  513. if builtUrl != url {
  514. t.Errorf("Expected %q, got %q.", url, builtUrl)
  515. }
  516. }
  517. func TestVariableNames(t *testing.T) {
  518. route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}")
  519. if route.err == nil {
  520. t.Errorf("Expected error for duplicated variable names")
  521. }
  522. }
  523. func TestRedirectSlash(t *testing.T) {
  524. var route *Route
  525. var routeMatch RouteMatch
  526. r := NewRouter()
  527. r.StrictSlash(false)
  528. route = r.NewRoute()
  529. if route.strictSlash != false {
  530. t.Errorf("Expected false redirectSlash.")
  531. }
  532. r.StrictSlash(true)
  533. route = r.NewRoute()
  534. if route.strictSlash != true {
  535. t.Errorf("Expected true redirectSlash.")
  536. }
  537. route = new(Route)
  538. route.strictSlash = true
  539. route.Path("/{arg1}/{arg2:[0-9]+}/")
  540. request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil)
  541. routeMatch = RouteMatch{}
  542. _ = route.Match(request, &routeMatch)
  543. vars := routeMatch.Vars
  544. if vars["arg1"] != "foo" {
  545. t.Errorf("Expected foo.")
  546. }
  547. if vars["arg2"] != "123" {
  548. t.Errorf("Expected 123.")
  549. }
  550. rsp := NewRecorder()
  551. routeMatch.Handler.ServeHTTP(rsp, request)
  552. if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" {
  553. t.Errorf("Expected redirect header.")
  554. }
  555. route = new(Route)
  556. route.strictSlash = true
  557. route.Path("/{arg1}/{arg2:[0-9]+}")
  558. request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil)
  559. routeMatch = RouteMatch{}
  560. _ = route.Match(request, &routeMatch)
  561. vars = routeMatch.Vars
  562. if vars["arg1"] != "foo" {
  563. t.Errorf("Expected foo.")
  564. }
  565. if vars["arg2"] != "123" {
  566. t.Errorf("Expected 123.")
  567. }
  568. rsp = NewRecorder()
  569. routeMatch.Handler.ServeHTTP(rsp, request)
  570. if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" {
  571. t.Errorf("Expected redirect header.")
  572. }
  573. }
  574. // Test for the new regexp library, still not available in stable Go.
  575. func TestNewRegexp(t *testing.T) {
  576. var p *routeRegexp
  577. var matches []string
  578. tests := map[string]map[string][]string{
  579. "/{foo:a{2}}": {
  580. "/a": nil,
  581. "/aa": {"aa"},
  582. "/aaa": nil,
  583. "/aaaa": nil,
  584. },
  585. "/{foo:a{2,}}": {
  586. "/a": nil,
  587. "/aa": {"aa"},
  588. "/aaa": {"aaa"},
  589. "/aaaa": {"aaaa"},
  590. },
  591. "/{foo:a{2,3}}": {
  592. "/a": nil,
  593. "/aa": {"aa"},
  594. "/aaa": {"aaa"},
  595. "/aaaa": nil,
  596. },
  597. "/{foo:[a-z]{3}}/{bar:[a-z]{2}}": {
  598. "/a": nil,
  599. "/ab": nil,
  600. "/abc": nil,
  601. "/abcd": nil,
  602. "/abc/ab": {"abc", "ab"},
  603. "/abc/abc": nil,
  604. "/abcd/ab": nil,
  605. },
  606. `/{foo:\w{3,}}/{bar:\d{2,}}`: {
  607. "/a": nil,
  608. "/ab": nil,
  609. "/abc": nil,
  610. "/abc/1": nil,
  611. "/abc/12": {"abc", "12"},
  612. "/abcd/12": {"abcd", "12"},
  613. "/abcd/123": {"abcd", "123"},
  614. },
  615. }
  616. for pattern, paths := range tests {
  617. p, _ = newRouteRegexp(pattern, false, false, false, false)
  618. for path, result := range paths {
  619. matches = p.regexp.FindStringSubmatch(path)
  620. if result == nil {
  621. if matches != nil {
  622. t.Errorf("%v should not match %v.", pattern, path)
  623. }
  624. } else {
  625. if len(matches) != len(result)+1 {
  626. t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches))
  627. } else {
  628. for k, v := range result {
  629. if matches[k+1] != v {
  630. t.Errorf("Expected %v, got %v.", v, matches[k+1])
  631. }
  632. }
  633. }
  634. }
  635. }
  636. }
  637. }