PageRenderTime 227ms CodeModel.GetById 81ms app.highlight 118ms RepoModel.GetById 23ms app.codeStats 0ms

/mux/mux_test.go

https://code.google.com/p/gorilla/
Go | 417 lines | 328 code | 48 blank | 41 comment | 47 complexity | 5e1018b74f927c9df2df1bba8a226e36 MD5 | raw file
  1// Copyright 2012 The Gorilla Authors. All rights reserved.
  2// Use of this source code is governed by a BSD-style
  3// license that can be found in the LICENSE file.
  4
  5package mux
  6
  7import (
  8	"fmt"
  9	"net/http"
 10	"testing"
 11)
 12
 13func TestRoute(t *testing.T) {
 14	var route *Route
 15	var request *http.Request
 16	var vars map[string]string
 17	var host, path, url string
 18
 19	// Setup an id so we can see which test failed. :)
 20	var idValue int
 21	id := func() int {
 22		idValue++
 23		return idValue
 24	}
 25
 26	// Host -------------------------------------------------------------------
 27
 28	route = new(Route).Host("aaa.bbb.ccc")
 29	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc/111/222/333", nil)
 30	vars = map[string]string{}
 31	host = "aaa.bbb.ccc"
 32	path = ""
 33	url = host + path
 34	testRoute(t, id(), true, route, request, vars, host, path, url)
 35	// Non-match for the same config.
 36	request, _ = http.NewRequest("GET", "http://aaa.222.ccc/111/222/333", nil)
 37	testRoute(t, id(), false, route, request, vars, host, path, url)
 38
 39	route = new(Route).Host("aaa.{v1:[a-z]{3}}.ccc")
 40	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc/111/222/333", nil)
 41	vars = map[string]string{"v1": "bbb"}
 42	host = "aaa.bbb.ccc"
 43	path = ""
 44	url = host + path
 45	testRoute(t, id(), true, route, request, vars, host, path, url)
 46	// Non-match for the same config.
 47	request, _ = http.NewRequest("GET", "http://aaa.222.ccc/111/222/333", nil)
 48	testRoute(t, id(), false, route, request, vars, host, path, url)
 49
 50	route = new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}")
 51	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc/111/222/333", nil)
 52	vars = map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}
 53	host = "aaa.bbb.ccc"
 54	path = ""
 55	url = host + path
 56	testRoute(t, id(), true, route, request, vars, host, path, url)
 57	// Non-match for the same config.
 58	request, _ = http.NewRequest("GET", "http://aaa.222.ccc/111/222/333", nil)
 59	testRoute(t, id(), false, route, request, vars, host, path, url)
 60
 61	// Path -------------------------------------------------------------------
 62
 63	route = new(Route).Path("/111/222/333")
 64	request, _ = http.NewRequest("GET", "http://localhost/111/222/333", nil)
 65	vars = map[string]string{}
 66	host = ""
 67	path = "/111/222/333"
 68	url = host + path
 69	testRoute(t, id(), true, route, request, vars, host, path, url)
 70	// Non-match for the same config.
 71	request, _ = http.NewRequest("GET", "http://localhost/1/2/3", nil)
 72	testRoute(t, id(), false, route, request, vars, host, path, url)
 73
 74	route = new(Route).Path("/111/{v1:[0-9]{3}}/333")
 75	request, _ = http.NewRequest("GET", "http://localhost/111/222/333", nil)
 76	vars = map[string]string{"v1": "222"}
 77	host = ""
 78	path = "/111/222/333"
 79	url = host + path
 80	testRoute(t, id(), true, route, request, vars, host, path, url)
 81	// Non-match for the same config.
 82	request, _ = http.NewRequest("GET", "http://localhost/111/aaa/333", nil)
 83	testRoute(t, id(), false, route, request, vars, host, path, url)
 84
 85	route = new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}")
 86	request, _ = http.NewRequest("GET", "http://localhost/111/222/333", nil)
 87	vars = map[string]string{"v1": "111", "v2": "222", "v3": "333"}
 88	host = ""
 89	path = "/111/222/333"
 90	url = host + path
 91	testRoute(t, id(), true, route, request, vars, host, path, url)
 92	// Non-match for the same config.
 93	request, _ = http.NewRequest("GET", "http://localhost/111/aaa/333", nil)
 94	testRoute(t, id(), false, route, request, vars, host, path, url)
 95
 96	// PathPrefix -------------------------------------------------------------
 97
 98	route = new(Route).PathPrefix("/111")
 99	request, _ = http.NewRequest("GET", "http://localhost/111/222/333", nil)
100	vars = map[string]string{}
101	host = ""
102	path = "/111"
103	url = host + path
104	testRoute(t, id(), true, route, request, vars, host, path, url)
105	// Non-match for the same config.
106	request, _ = http.NewRequest("GET", "http://localhost/1/2/3", nil)
107	testRoute(t, id(), false, route, request, vars, host, path, url)
108
109	route = new(Route).PathPrefix("/111/{v1:[0-9]{3}}")
110	request, _ = http.NewRequest("GET", "http://localhost/111/222/333", nil)
111	vars = map[string]string{"v1": "222"}
112	host = ""
113	path = "/111/222"
114	url = host + path
115	testRoute(t, id(), true, route, request, vars, host, path, url)
116	// Non-match for the same config.
117	request, _ = http.NewRequest("GET", "http://localhost/111/aaa/333", nil)
118	testRoute(t, id(), false, route, request, vars, host, path, url)
119
120	route = new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}")
121	request, _ = http.NewRequest("GET", "http://localhost/111/222/333", nil)
122	vars = map[string]string{"v1": "111", "v2": "222"}
123	host = ""
124	path = "/111/222"
125	url = host + path
126	testRoute(t, id(), true, route, request, vars, host, path, url)
127	// Non-match for the same config.
128	request, _ = http.NewRequest("GET", "http://localhost/111/aaa/333", nil)
129	testRoute(t, id(), false, route, request, vars, host, path, url)
130
131	// Host + Path ------------------------------------------------------------
132
133	route = new(Route).Host("aaa.bbb.ccc").Path("/111/222/333")
134	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc/111/222/333", nil)
135	vars = map[string]string{}
136	host = ""
137	path = ""
138	url = host + path
139	testRoute(t, id(), true, route, request, vars, host, path, url)
140	// Non-match for the same config.
141	request, _ = http.NewRequest("GET", "http://aaa.222.ccc/111/222/333", nil)
142	testRoute(t, id(), false, route, request, vars, host, path, url)
143
144	route = new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333")
145	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc/111/222/333", nil)
146	vars = map[string]string{"v1": "bbb", "v2": "222"}
147	host = "aaa.bbb.ccc"
148	path = "/111/222/333"
149	url = host + path
150	testRoute(t, id(), true, route, request, vars, host, path, url)
151	// Non-match for the same config.
152	request, _ = http.NewRequest("GET", "http://aaa.222.ccc/111/222/333", nil)
153	testRoute(t, id(), false, route, request, vars, host, path, url)
154
155	route = new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}")
156	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc/111/222/333", nil)
157	vars = map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}
158	host = "aaa.bbb.ccc"
159	path = "/111/222/333"
160	url = host + path
161	testRoute(t, id(), true, route, request, vars, host, path, url)
162	// Non-match for the same config.
163	request, _ = http.NewRequest("GET", "http://aaa.222.ccc/111/222/333", nil)
164	testRoute(t, id(), false, route, request, vars, host, path, url)
165
166	// Headers ----------------------------------------------------------------
167
168	route = new(Route).Headers("foo", "bar", "baz", "ding")
169	request, _ = http.NewRequest("GET", "http://localhost", nil)
170	request.Header.Add("foo", "bar")
171	request.Header.Add("baz", "ding")
172	vars = map[string]string{}
173	host = ""
174	path = ""
175	url = host + path
176	testRoute(t, id(), true, route, request, vars, host, path, url)
177	// Non-match for the same config.
178	request, _ = http.NewRequest("GET", "http://localhost", nil)
179	request.Header.Add("foo", "bar")
180	request.Header.Add("baz", "dong")
181	testRoute(t, id(), false, route, request, vars, host, path, url)
182
183	// Methods ----------------------------------------------------------------
184
185	route = new(Route).Methods("GET", "POST")
186	request, _ = http.NewRequest("GET", "http://localhost", nil)
187	vars = map[string]string{}
188	host = ""
189	path = ""
190	url = host + path
191	testRoute(t, id(), true, route, request, vars, host, path, url)
192	request, _ = http.NewRequest("POST", "http://localhost", nil)
193	testRoute(t, id(), true, route, request, vars, host, path, url)
194	// Non-match for the same config.
195	request, _ = http.NewRequest("PUT", "http://localhost", nil)
196	testRoute(t, id(), false, route, request, vars, host, path, url)
197
198	// Queries ----------------------------------------------------------------
199
200	route = new(Route).Queries("foo", "bar", "baz", "ding")
201	request, _ = http.NewRequest("GET", "http://localhost?foo=bar&baz=ding", nil)
202	vars = map[string]string{}
203	host = ""
204	path = ""
205	url = host + path
206	testRoute(t, id(), true, route, request, vars, host, path, url)
207	// Non-match for the same config.
208	request, _ = http.NewRequest("GET", "http://localhost?foo=bar&baz=dong", nil)
209	testRoute(t, id(), false, route, request, vars, host, path, url)
210
211	// Schemes ----------------------------------------------------------------
212
213	route = new(Route).Schemes("https", "ftp")
214	request, _ = http.NewRequest("GET", "https://localhost", nil)
215	vars = map[string]string{}
216	host = ""
217	path = ""
218	url = host + path
219	testRoute(t, id(), true, route, request, vars, host, path, url)
220	request, _ = http.NewRequest("GET", "ftp://localhost", nil)
221	testRoute(t, id(), true, route, request, vars, host, path, url)
222	// Non-match for the same config.
223	request, _ = http.NewRequest("GET", "http://localhost", nil)
224	testRoute(t, id(), false, route, request, vars, host, path, url)
225
226	// Custom -----------------------------------------------------------------
227
228	m := func(r *http.Request, m *RouteMatch) bool {
229		if r.URL.Host == "aaa.bbb.ccc" {
230			return true
231		}
232		return false
233	}
234	route = new(Route).MatcherFunc(m)
235	request, _ = http.NewRequest("GET", "http://aaa.bbb.ccc", nil)
236	vars = map[string]string{}
237	host = ""
238	path = ""
239	url = host + path
240	testRoute(t, id(), true, route, request, vars, host, path, url)
241	// Non-match for the same config.
242	request, _ = http.NewRequest("GET", "http://aaa.ccc.bbb", nil)
243	testRoute(t, id(), false, route, request, vars, host, path, url)
244}
245
246func TestSubRouter(t *testing.T) {
247	var route *Route
248	var request *http.Request
249	var vars map[string]string
250	var host, path, url string
251
252	subrouter := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter()
253
254	// Setup an id so we can see which test failed. :)
255	var idValue int
256	id := func() int {
257		idValue++
258		return idValue
259	}
260
261	// ------------------------------------------------------------------------
262
263	route = subrouter.Path("/{v2:[a-z]+}")
264	request, _ = http.NewRequest("GET", "http://aaa.google.com/bbb", nil)
265	vars = map[string]string{"v1": "aaa", "v2": "bbb"}
266	host = "aaa.google.com"
267	path = "/bbb"
268	url = host + path
269	testRoute(t, id(), true, route, request, vars, host, path, url)
270	// Non-match for the same config.
271	request, _ = http.NewRequest("GET", "http://111.google.com/111", nil)
272	testRoute(t, id(), false, route, request, vars, host, path, url)
273
274	// ------------------------------------------------------------------------
275
276	subrouter = new(Route).PathPrefix("/foo/{v1}").Subrouter()
277	route = subrouter.Path("/baz/{v2}")
278	request, _ = http.NewRequest("GET", "http://localhost/foo/bar/baz/ding", nil)
279	vars = map[string]string{"v1": "bar", "v2": "ding"}
280	host = ""
281	path = "/foo/bar/baz/ding"
282	url = host + path
283	testRoute(t, id(), true, route, request, vars, host, path, url)
284	// Non-match for the same config.
285	request, _ = http.NewRequest("GET", "http://localhost/foo/bar", nil)
286	testRoute(t, id(), false, route, request, vars, host, path, url)
287}
288
289func TestNamedRoutes(t *testing.T) {
290	r1 := NewRouter()
291	r1.NewRoute().Name("a")
292	r1.NewRoute().Name("b")
293	r1.NewRoute().Name("c")
294
295	r2 := r1.NewRoute().Subrouter()
296	r2.NewRoute().Name("d")
297	r2.NewRoute().Name("e")
298	r2.NewRoute().Name("f")
299
300	r3 := r2.NewRoute().Subrouter()
301	r3.NewRoute().Name("g")
302	r3.NewRoute().Name("h")
303	r3.NewRoute().Name("i")
304
305	if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 {
306		t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes)
307	} else if r1.Get("i") == nil {
308		t.Errorf("Subroute name not registered")
309	}
310}
311
312// ----------------------------------------------------------------------------
313// Helpers
314// ----------------------------------------------------------------------------
315
316func getRouteTemplate(route *Route) string {
317	host, path := "none", "none"
318	if route.regexp != nil {
319		if route.regexp.host != nil {
320			host = route.regexp.host.template
321		}
322		if route.regexp.path != nil {
323			path = route.regexp.path.template
324		}
325	}
326	return fmt.Sprintf("Host: %v, Path: %v", host, path)
327}
328
329func testRoute(t *testing.T, id int, shouldMatch bool, route *Route,
330	request *http.Request, vars map[string]string, host, path, url string) {
331	var match RouteMatch
332	ok := route.Match(request, &match)
333	if ok != shouldMatch {
334		msg := "Should match"
335		if !shouldMatch {
336			msg = "Should not match"
337		}
338		t.Errorf("(%v) %v:\nRoute: %#v\nRequest: %#v\nVars: %v\n", id, msg, route, request, vars)
339		return
340	}
341	if shouldMatch {
342		if vars != nil && !stringMapEqual(vars, match.Vars) {
343			t.Errorf("(%v) Vars not equal: expected %v, got %v", id, vars, match.Vars)
344			return
345		}
346		if host != "" {
347			u, _ := route.URLHost(mapToPairs(match.Vars)...)
348			if host != u.Host {
349				t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", id, host, u.Host, getRouteTemplate(route))
350				return
351			}
352		}
353		if path != "" {
354			u, _ := route.URLPath(mapToPairs(match.Vars)...)
355			if path != u.Path {
356				t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", id, path, u.Path, getRouteTemplate(route))
357				return
358			}
359		}
360		if url != "" {
361			u, _ := route.URL(mapToPairs(match.Vars)...)
362			if url != u.Host+u.Path {
363				t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", id, url, u.Host+u.Path, getRouteTemplate(route))
364				return
365			}
366		}
367	}
368}
369
370func TestStrictSlash(t *testing.T) {
371	var r *Router
372	var req *http.Request
373	var route *Route
374	var match *RouteMatch
375	var matched bool
376
377	// StrictSlash should be ignored for path prefix.
378	// So we register a route ending in slash but it doesn't attempt to add
379	// the slash for a path not ending in slash.
380	r = NewRouter()
381	r.StrictSlash(true)
382	route = r.NewRoute().PathPrefix("/static/")
383	req, _ = http.NewRequest("GET", "http://localhost/static/logo.png", nil)
384	match = new(RouteMatch)
385	matched = r.Match(req, match)
386	if !matched {
387		t.Errorf("Should match request %q -- %v", req.URL.Path, getRouteTemplate(route))
388	}
389	if match.Handler != nil {
390		t.Errorf("Should not redirect")
391	}
392}
393
394func mapToPairs(m map[string]string) []string {
395	var i int
396	p := make([]string, len(m)*2)
397	for k, v := range m {
398		p[i] = k
399		p[i+1] = v
400		i += 2
401	}
402	return p
403}
404
405func stringMapEqual(m1, m2 map[string]string) bool {
406	nil1 := m1 == nil
407	nil2 := m2 == nil
408	if nil1 != nil2 || len(m1) != len(m2) {
409		return false
410	}
411	for k, v := range m1 {
412		if v != m2[k] {
413			return false
414		}
415	}
416	return true
417}