blob: 99e6d8a06f8a4b9a5af7ea461a627815edfd8f28 [file] [log] [blame]
use matchit::{InsertError, MatchError, Router};
#[test]
fn issue_31() {
let mut router = Router::new();
router.insert("/path/foo/:arg", "foo").unwrap();
router.insert("/path/*rest", "wildcard").unwrap();
assert_eq!(
router.at("/path/foo/myarg/bar/baz").map(|m| *m.value),
Ok("wildcard")
);
}
#[test]
fn issue_22() {
let mut x = Router::new();
x.insert("/foo_bar", "Welcome!").unwrap();
x.insert("/foo/bar", "Welcome!").unwrap();
assert_eq!(x.at("/foo/").unwrap_err(), MatchError::NotFound);
let mut x = Router::new();
x.insert("/foo", "Welcome!").unwrap();
x.insert("/foo/bar", "Welcome!").unwrap();
assert_eq!(x.at("/foo/").unwrap_err(), MatchError::ExtraTrailingSlash);
}
match_tests! {
basic {
routes = [
"/hi",
"/contact",
"/co",
"/c",
"/a",
"/ab",
"/doc/",
"/doc/rust_faq.html",
"/doc/rust1.26.html",
"/ʯ",
"/β",
"/sd!here",
"/sd$here",
"/sd&here",
"/sd'here",
"/sd(here",
"/sd)here",
"/sd+here",
"/sd,here",
"/sd;here",
"/sd=here",
],
"/a" :: "/a" => {},
"" :: "/" => None,
"/hi" :: "/hi" => {},
"/contact" :: "/contact" => {},
"/co" :: "/co" => {},
"" :: "/con" => None,
"" :: "/cona" => None,
"" :: "/no" => None,
"/ab" :: "/ab" => {},
"/ʯ" :: "/ʯ" => {},
"/β" :: "/β" => {},
"/sd!here" :: "/sd!here" => {},
"/sd$here" :: "/sd$here" => {},
"/sd&here" :: "/sd&here" => {},
"/sd'here" :: "/sd'here" => {},
"/sd(here" :: "/sd(here" => {},
"/sd)here" :: "/sd)here" => {},
"/sd+here" :: "/sd+here" => {},
"/sd,here" :: "/sd,here" => {},
"/sd;here" :: "/sd;here" => {},
"/sd=here" :: "/sd=here" => {},
},
wildcard {
routes = [
"/",
"/cmd/:tool/",
"/cmd/:tool2/:sub",
"/cmd/whoami",
"/cmd/whoami/root",
"/cmd/whoami/root/",
"/src",
"/src/",
"/src/*filepath",
"/search/",
"/search/:query",
"/search/actix-web",
"/search/google",
"/user_:name",
"/user_:name/about",
"/files/:dir/*filepath",
"/doc/",
"/doc/rust_faq.html",
"/doc/rust1.26.html",
"/info/:user/public",
"/info/:user/project/:project",
"/info/:user/project/rustlang",
"/aa/*xx",
"/ab/*xx",
"/:cc",
"/c1/:dd/e",
"/c1/:dd/e1",
"/:cc/cc",
"/:cc/:dd/ee",
"/:cc/:dd/:ee/ff",
"/:cc/:dd/:ee/:ff/gg",
"/:cc/:dd/:ee/:ff/:gg/hh",
"/get/test/abc/",
"/get/:param/abc/",
"/something/:paramname/thirdthing",
"/something/secondthing/test",
"/get/abc",
"/get/:param",
"/get/abc/123abc",
"/get/abc/:param",
"/get/abc/123abc/xxx8",
"/get/abc/123abc/:param",
"/get/abc/123abc/xxx8/1234",
"/get/abc/123abc/xxx8/:param",
"/get/abc/123abc/xxx8/1234/ffas",
"/get/abc/123abc/xxx8/1234/:param",
"/get/abc/123abc/xxx8/1234/kkdd/12c",
"/get/abc/123abc/xxx8/1234/kkdd/:param",
"/get/abc/:param/test",
"/get/abc/123abd/:param",
"/get/abc/123abddd/:param",
"/get/abc/123/:param",
"/get/abc/123abg/:param",
"/get/abc/123abf/:param",
"/get/abc/123abfff/:param",
],
"/" :: "/" => {},
"/cmd/test" :: "/cmd/:tool/" => None,
"/cmd/test/" :: "/cmd/:tool/" => { "tool" => "test" },
"/cmd/test/3" :: "/cmd/:tool2/:sub" => { "tool2" => "test", "sub" => "3" },
"/cmd/who" :: "/cmd/:tool/" => None,
"/cmd/who/" :: "/cmd/:tool/" => { "tool" => "who" },
"/cmd/whoami" :: "/cmd/whoami" => {},
"/cmd/whoami/" :: "/cmd/whoami" => None,
"/cmd/whoami/r" :: "/cmd/:tool2/:sub" => { "tool2" => "whoami", "sub" => "r" },
"/cmd/whoami/r/" :: "/cmd/:tool/:sub" => None,
"/cmd/whoami/root" :: "/cmd/whoami/root" => {},
"/cmd/whoami/root/" :: "/cmd/whoami/root/" => {},
"/src" :: "/src" => {},
"/src/" :: "/src/" => {},
"/src/some/file.png" :: "/src/*filepath" => { "filepath" => "some/file.png" },
"/search/" :: "/search/" => {},
"/search/actix" :: "/search/:query" => { "query" => "actix" },
"/search/actix-web" :: "/search/actix-web" => {},
"/search/someth!ng+in+ünìcodé" :: "/search/:query" => { "query" => "someth!ng+in+ünìcodé" },
"/search/someth!ng+in+ünìcodé/" :: "" => None,
"/user_rustacean" :: "/user_:name" => { "name" => "rustacean" },
"/user_rustacean/about" :: "/user_:name/about" => { "name" => "rustacean" },
"/files/js/inc/framework.js" :: "/files/:dir/*filepath" => { "dir" => "js", "filepath" => "inc/framework.js" },
"/info/gordon/public" :: "/info/:user/public" => { "user" => "gordon" },
"/info/gordon/project/rust" :: "/info/:user/project/:project" => { "user" => "gordon", "project" => "rust" } ,
"/info/gordon/project/rustlang" :: "/info/:user/project/rustlang" => { "user" => "gordon" },
"/aa/" :: "/" => None,
"/aa/aa" :: "/aa/*xx" => { "xx" => "aa" },
"/ab/ab" :: "/ab/*xx" => { "xx" => "ab" },
"/a" :: "/:cc" => { "cc" => "a" },
"/all" :: "/:cc" => { "cc" => "all" },
"/d" :: "/:cc" => { "cc" => "d" },
"/ad" :: "/:cc" => { "cc" => "ad" },
"/dd" :: "/:cc" => { "cc" => "dd" },
"/dddaa" :: "/:cc" => { "cc" => "dddaa" },
"/aa" :: "/:cc" => { "cc" => "aa" },
"/aaa" :: "/:cc" => { "cc" => "aaa" },
"/aaa/cc" :: "/:cc/cc" => { "cc" => "aaa" },
"/ab" :: "/:cc" => { "cc" => "ab" },
"/abb" :: "/:cc" => { "cc" => "abb" },
"/abb/cc" :: "/:cc/cc" => { "cc" => "abb" },
"/allxxxx" :: "/:cc" => { "cc" => "allxxxx" },
"/alldd" :: "/:cc" => { "cc" => "alldd" },
"/all/cc" :: "/:cc/cc" => { "cc" => "all" },
"/a/cc" :: "/:cc/cc" => { "cc" => "a" },
"/c1/d/e" :: "/c1/:dd/e" => { "dd" => "d" },
"/c1/d/e1" :: "/c1/:dd/e1" => { "dd" => "d" },
"/c1/d/ee" :: "/:cc/:dd/ee" => { "cc" => "c1", "dd" => "d" },
"/cc/cc" :: "/:cc/cc" => { "cc" => "cc" },
"/ccc/cc" :: "/:cc/cc" => { "cc" => "ccc" },
"/deedwjfs/cc" :: "/:cc/cc" => { "cc" => "deedwjfs" },
"/acllcc/cc" :: "/:cc/cc" => { "cc" => "acllcc" },
"/get/test/abc/" :: "/get/test/abc/" => {},
"/get/te/abc/" :: "/get/:param/abc/" => { "param" => "te" },
"/get/testaa/abc/" :: "/get/:param/abc/" => { "param" => "testaa" },
"/get/xx/abc/" :: "/get/:param/abc/" => { "param" => "xx" },
"/get/tt/abc/" :: "/get/:param/abc/" => { "param" => "tt" },
"/get/a/abc/" :: "/get/:param/abc/" => { "param" => "a" },
"/get/t/abc/" :: "/get/:param/abc/" => { "param" => "t" },
"/get/aa/abc/" :: "/get/:param/abc/" => { "param" => "aa" },
"/get/abas/abc/" :: "/get/:param/abc/" => { "param" => "abas" },
"/something/secondthing/test" :: "/something/secondthing/test" => {},
"/something/abcdad/thirdthing" :: "/something/:paramname/thirdthing" => { "paramname" => "abcdad" },
"/something/secondthingaaaa/thirdthing" :: "/something/:paramname/thirdthing" => { "paramname" => "secondthingaaaa" },
"/something/se/thirdthing" :: "/something/:paramname/thirdthing" => { "paramname" => "se" },
"/something/s/thirdthing" :: "/something/:paramname/thirdthing" => { "paramname" => "s" },
"/c/d/ee" :: "/:cc/:dd/ee" => { "cc" => "c", "dd" => "d" },
"/c/d/e/ff" :: "/:cc/:dd/:ee/ff" => { "cc" => "c", "dd" => "d", "ee" => "e" },
"/c/d/e/f/gg" :: "/:cc/:dd/:ee/:ff/gg" => { "cc" => "c", "dd" => "d", "ee" => "e", "ff" => "f" },
"/c/d/e/f/g/hh" :: "/:cc/:dd/:ee/:ff/:gg/hh" => { "cc" => "c", "dd" => "d", "ee" => "e", "ff" => "f", "gg" => "g" },
"/cc/dd/ee/ff/gg/hh" :: "/:cc/:dd/:ee/:ff/:gg/hh" => { "cc" => "cc", "dd" => "dd", "ee" => "ee", "ff" => "ff", "gg" => "gg" },
"/get/abc" :: "/get/abc" => {},
"/get/a" :: "/get/:param" => { "param" => "a" },
"/get/abz" :: "/get/:param" => { "param" => "abz" },
"/get/12a" :: "/get/:param" => { "param" => "12a" },
"/get/abcd" :: "/get/:param" => { "param" => "abcd" },
"/get/abc/123abc" :: "/get/abc/123abc" => {},
"/get/abc/12" :: "/get/abc/:param" => { "param" => "12" },
"/get/abc/123ab" :: "/get/abc/:param" => { "param" => "123ab" },
"/get/abc/xyz" :: "/get/abc/:param" => { "param" => "xyz" },
"/get/abc/123abcddxx" :: "/get/abc/:param" => { "param" => "123abcddxx" },
"/get/abc/123abc/xxx8" :: "/get/abc/123abc/xxx8" => {},
"/get/abc/123abc/x" :: "/get/abc/123abc/:param" => { "param" => "x" },
"/get/abc/123abc/xxx" :: "/get/abc/123abc/:param" => { "param" => "xxx" },
"/get/abc/123abc/abc" :: "/get/abc/123abc/:param" => { "param" => "abc" },
"/get/abc/123abc/xxx8xxas" :: "/get/abc/123abc/:param" => { "param" => "xxx8xxas" },
"/get/abc/123abc/xxx8/1234" :: "/get/abc/123abc/xxx8/1234" => {},
"/get/abc/123abc/xxx8/1" :: "/get/abc/123abc/xxx8/:param" => { "param" => "1" },
"/get/abc/123abc/xxx8/123" :: "/get/abc/123abc/xxx8/:param" => { "param" => "123" },
"/get/abc/123abc/xxx8/78k" :: "/get/abc/123abc/xxx8/:param" => { "param" => "78k" },
"/get/abc/123abc/xxx8/1234xxxd" :: "/get/abc/123abc/xxx8/:param" => { "param" => "1234xxxd" },
"/get/abc/123abc/xxx8/1234/ffas" :: "/get/abc/123abc/xxx8/1234/ffas" => {},
"/get/abc/123abc/xxx8/1234/f" :: "/get/abc/123abc/xxx8/1234/:param" => { "param" => "f" },
"/get/abc/123abc/xxx8/1234/ffa" :: "/get/abc/123abc/xxx8/1234/:param" => { "param" => "ffa" },
"/get/abc/123abc/xxx8/1234/kka" :: "/get/abc/123abc/xxx8/1234/:param" => { "param" => "kka" },
"/get/abc/123abc/xxx8/1234/ffas321" :: "/get/abc/123abc/xxx8/1234/:param" => { "param" => "ffas321" },
"/get/abc/123abc/xxx8/1234/kkdd/12c" :: "/get/abc/123abc/xxx8/1234/kkdd/12c" => {},
"/get/abc/123abc/xxx8/1234/kkdd/1" :: "/get/abc/123abc/xxx8/1234/kkdd/:param" => { "param" => "1" },
"/get/abc/123abc/xxx8/1234/kkdd/12" :: "/get/abc/123abc/xxx8/1234/kkdd/:param" => { "param" => "12" },
"/get/abc/123abc/xxx8/1234/kkdd/12b" :: "/get/abc/123abc/xxx8/1234/kkdd/:param" => { "param" => "12b" },
"/get/abc/123abc/xxx8/1234/kkdd/34" :: "/get/abc/123abc/xxx8/1234/kkdd/:param" => { "param" => "34" },
"/get/abc/123abc/xxx8/1234/kkdd/12c2e3" :: "/get/abc/123abc/xxx8/1234/kkdd/:param" => { "param" => "12c2e3" },
"/get/abc/12/test" :: "/get/abc/:param/test" => { "param" => "12" },
"/get/abc/123abdd/test" :: "/get/abc/:param/test" => { "param" => "123abdd" },
"/get/abc/123abdddf/test" :: "/get/abc/:param/test" => { "param" => "123abdddf" },
"/get/abc/123ab/test" :: "/get/abc/:param/test" => { "param" => "123ab" },
"/get/abc/123abgg/test" :: "/get/abc/:param/test" => { "param" => "123abgg" },
"/get/abc/123abff/test" :: "/get/abc/:param/test" => { "param" => "123abff" },
"/get/abc/123abffff/test" :: "/get/abc/:param/test" => { "param" => "123abffff" },
"/get/abc/123abd/test" :: "/get/abc/123abd/:param" => { "param" => "test" },
"/get/abc/123abddd/test" :: "/get/abc/123abddd/:param" => { "param" => "test" },
"/get/abc/123/test22" :: "/get/abc/123/:param" => { "param" => "test22" },
"/get/abc/123abg/test" :: "/get/abc/123abg/:param" => { "param" => "test" },
"/get/abc/123abf/testss" :: "/get/abc/123abf/:param" => { "param" => "testss" },
"/get/abc/123abfff/te" :: "/get/abc/123abfff/:param" => { "param" => "te" },
},
normalized {
routes = [
"/x/:foo/bar",
"/x/:bar/baz",
"/:foo/:baz/bax",
"/:foo/:bar/baz",
"/:fod/:baz/:bax/foo",
"/:fod/baz/bax/foo",
"/:foo/baz/bax",
"/:bar/:bay/bay",
"/s",
"/s/s",
"/s/s/s",
"/s/s/s/s",
"/s/s/:s/x",
"/s/s/:y/d",
],
"/x/foo/bar" :: "/x/:foo/bar" => { "foo" => "foo" },
"/x/foo/baz" :: "/x/:bar/baz" => { "bar" => "foo" },
"/y/foo/baz" :: "/:foo/:bar/baz" => { "foo" => "y", "bar" => "foo" },
"/y/foo/bax" :: "/:foo/:baz/bax" => { "foo" => "y", "baz" => "foo" },
"/y/baz/baz" :: "/:foo/:bar/baz" => { "foo" => "y", "bar" => "baz" },
"/y/baz/bax/foo" :: "/:fod/baz/bax/foo" => { "fod" => "y" },
"/y/baz/b/foo" :: "/:fod/:baz/:bax/foo" => { "fod" => "y", "baz" => "baz", "bax" => "b" },
"/y/baz/bax" :: "/:foo/baz/bax" => { "foo" => "y" },
"/z/bar/bay" :: "/:bar/:bay/bay" => { "bar" => "z", "bay" => "bar" },
"/s" :: "/s" => { },
"/s/s" :: "/s/s" => { },
"/s/s/s" :: "/s/s/s" => { },
"/s/s/s/s" :: "/s/s/s/s" => { },
"/s/s/s/x" :: "/s/s/:s/x" => { "s" => "s" },
"/s/s/s/d" :: "/s/s/:y/d" => { "y" => "s" },
},
blog {
routes = [
"/:page",
"/posts/:year/:month/:post",
"/posts/:year/:month/index",
"/posts/:year/top",
"/static/*path",
"/favicon.ico",
],
"/about" :: "/:page" => { "page" => "about" },
"/posts/2021/01/rust" :: "/posts/:year/:month/:post" => { "year" => "2021", "month" => "01", "post" => "rust" },
"/posts/2021/01/index" :: "/posts/:year/:month/index" => { "year" => "2021", "month" => "01" },
"/posts/2021/top" :: "/posts/:year/top" => { "year" => "2021" },
"/static/foo.png" :: "/static/*path" => { "path" => "foo.png" },
"/favicon.ico" :: "/favicon.ico" => {},
},
double_overlap {
routes = [
"/:object/:id",
"/secret/:id/path",
"/secret/978",
"/other/:object/:id/",
"/other/an_object/:id",
"/other/static/path",
"/other/long/static/path/"
],
"/secret/978/path" :: "/secret/:id/path" => { "id" => "978" },
"/some_object/978" :: "/:object/:id" => { "object" => "some_object", "id" => "978" },
"/secret/978" :: "/secret/978" => {},
"/super_secret/978/" :: "/:object/:id" => None,
"/other/object/1/" :: "/other/:object/:id/" => { "object" => "object", "id" => "1" },
"/other/object/1/2" :: "/other/:object/:id" => None,
"/other/an_object/1" :: "/other/an_object/:id" => { "id" => "1" },
"/other/static/path" :: "/other/static/path" => {},
"/other/long/static/path/" :: "/other/long/static/path/" => {},
},
catchall_off_by_one {
routes = [
"/foo/*catchall",
"/bar",
"/bar/",
"/bar/*catchall",
],
"/foo" :: "" => None,
"/foo/" :: "" => None,
"/foo/x" :: "/foo/*catchall" => { "catchall" => "x" },
"/bar" :: "/bar" => {},
"/bar/" :: "/bar/" => {},
"/bar/x" :: "/bar/*catchall" => { "catchall" => "x" },
},
catchall_static_overlap {
routes = [
"/foo",
"/bar",
"/*bar",
"/baz",
"/baz/",
"/baz/x",
"/baz/:xxx",
"/",
"/xxx/*x",
"/xxx/",
],
"/foo" :: "/foo" => {},
"/bar" :: "/bar" => {},
"/baz" :: "/baz" => {},
"/baz/" :: "/baz/" => {},
"/baz/x" :: "/baz/x" => {},
"/???" :: "/*bar" => { "bar" => "???" },
"/" :: "/" => {},
"" :: "" => None,
"/xxx/y" :: "/xxx/*x" => { "x" => "y" },
"/xxx/" :: "/xxx/" => {},
"/xxx" :: "" => None
}
}
// https://github.com/ibraheemdev/matchit/issues/12
#[test]
fn issue_12() {
let mut matcher = Router::new();
matcher.insert("/:object/:id", "object with id").unwrap();
matcher
.insert("/secret/:id/path", "secret with id and path")
.unwrap();
let matched = matcher.at("/secret/978/path").unwrap();
assert_eq!(matched.params.get("id"), Some("978"));
let matched = matcher.at("/something/978").unwrap();
assert_eq!(matched.params.get("id"), Some("978"));
assert_eq!(matched.params.get("object"), Some("something"));
let matched = matcher.at("/secret/978").unwrap();
assert_eq!(matched.params.get("id"), Some("978"));
}
insert_tests! {
wildcard_conflict {
"/cmd/:tool/:sub" => Ok(()),
"/cmd/vet" => Ok(()),
"/foo/bar" => Ok(()),
"/foo/:name" => Ok(()),
"/foo/:names" => Err(InsertError::Conflict { with: "/foo/:name".into() }),
"/cmd/*path" => Err(InsertError::Conflict { with: "/cmd/:tool/:sub".into() }),
"/cmd/:xxx/names" => Ok(()),
"/cmd/:tool/:xxx/foo" => Ok(()),
"/src/*filepath" => Ok(()),
"/src/:file" => Err(InsertError::Conflict { with: "/src/*filepath".into() }),
"/src/static.json" => Ok(()),
"/src/$filepathx" => Ok(()),
"/src/" => Ok(()),
"/src/foo/bar" => Ok(()),
"/src1/" => Ok(()),
"/src1/*filepath" => Ok(()),
"/src2*filepath" => Err(InsertError::InvalidCatchAll),
"/src2/*filepath" => Ok(()),
"/src2/" => Ok(()),
"/src2" => Ok(()),
"/src3" => Ok(()),
"/src3/*filepath" => Ok(()),
"/search/:query" => Ok(()),
"/search/valid" => Ok(()),
"/user_:name" => Ok(()),
"/user_x" => Ok(()),
"/user_:bar" => Err(InsertError::Conflict { with: "/user_:name".into() }),
"/id:id" => Ok(()),
"/id/:id" => Ok(()),
},
invalid_catchall {
"/non-leading-*catchall" => Err(InsertError::InvalidCatchAll),
"/foo/bar*catchall" => Err(InsertError::InvalidCatchAll),
"/src/*filepath/x" => Err(InsertError::InvalidCatchAll),
"/src2/" => Ok(()),
"/src2/*filepath/x" => Err(InsertError::InvalidCatchAll),
},
invalid_catchall2 {
"*x" => Err(InsertError::InvalidCatchAll)
},
catchall_root_conflict {
"/" => Ok(()),
"/*filepath" => Ok(()),
},
child_conflict {
"/cmd/vet" => Ok(()),
"/cmd/:tool" => Ok(()),
"/cmd/:tool/:sub" => Ok(()),
"/cmd/:tool/misc" => Ok(()),
"/cmd/:tool/:bad" => Err(InsertError::Conflict { with: "/cmd/:tool/:sub".into() }),
"/src/AUTHORS" => Ok(()),
"/src/*filepath" => Ok(()),
"/user_x" => Ok(()),
"/user_:name" => Ok(()),
"/id/:id" => Ok(()),
"/id:id" => Ok(()),
"/:id" => Ok(()),
"/*filepath" => Err(InsertError::Conflict { with: "/:id".into() }),
},
duplicates {
"/" => Ok(()),
"/" => Err(InsertError::Conflict { with: "/".into() }),
"/doc/" => Ok(()),
"/doc/" => Err(InsertError::Conflict { with: "/doc/".into() }),
"/src/*filepath" => Ok(()),
"/src/*filepath" => Err(InsertError::Conflict { with: "/src/*filepath".into() }),
"/search/:query" => Ok(()),
"/search/:query" => Err(InsertError::Conflict { with: "/search/:query".into() }),
"/user_:name" => Ok(()),
"/user_:name" => Err(InsertError::Conflict { with: "/user_:name".into() }),
},
unnamed_param {
"/user:" => Err(InsertError::UnnamedParam),
"/user:/" => Err(InsertError::UnnamedParam),
"/cmd/:/" => Err(InsertError::UnnamedParam),
"/src/*" => Err(InsertError::UnnamedParam),
},
double_params {
"/:foo:bar" => Err(InsertError::TooManyParams),
"/:foo:bar/" => Err(InsertError::TooManyParams),
"/:foo*bar/" => Err(InsertError::TooManyParams),
},
normalized_conflict {
"/x/:foo/bar" => Ok(()),
"/x/:bar/bar" => Err(InsertError::Conflict { with: "/x/:foo/bar".into() }),
"/:y/bar/baz" => Ok(()),
"/:y/baz/baz" => Ok(()),
"/:z/bar/bat" => Ok(()),
"/:z/bar/baz" => Err(InsertError::Conflict { with: "/:y/bar/baz".into() }),
},
more_conflicts {
"/con:tact" => Ok(()),
"/who/are/*you" => Ok(()),
"/who/foo/hello" => Ok(()),
"/whose/:users/:name" => Ok(()),
"/who/are/foo" => Ok(()),
"/who/are/foo/bar" => Ok(()),
"/con:nection" => Err(InsertError::Conflict { with: "/con:tact".into() }),
"/whose/:users/:user" => Err(InsertError::Conflict { with: "/whose/:users/:name".into() }),
},
catchall_static_overlap1 {
"/bar" => Ok(()),
"/bar/" => Ok(()),
"/bar/*foo" => Ok(()),
},
catchall_static_overlap2 {
"/foo" => Ok(()),
"/*bar" => Ok(()),
"/bar" => Ok(()),
"/baz" => Ok(()),
"/baz/:split" => Ok(()),
"/" => Ok(()),
"/*bar" => Err(InsertError::Conflict { with: "/*bar".into() }),
"/*zzz" => Err(InsertError::Conflict { with: "/*bar".into() }),
"/:xxx" => Err(InsertError::Conflict { with: "/*bar".into() }),
},
catchall_static_overlap3 {
"/*bar" => Ok(()),
"/bar" => Ok(()),
"/bar/x" => Ok(()),
"/bar_:x" => Ok(()),
"/bar_:x" => Err(InsertError::Conflict { with: "/bar_:x".into() }),
"/bar_:x/y" => Ok(()),
"/bar/:x" => Ok(()),
},
}
tsr_tests! {
tsr {
routes = [
"/hi",
"/b/",
"/search/:query",
"/cmd/:tool/",
"/src/*filepath",
"/x",
"/x/y",
"/y/",
"/y/z",
"/0/:id",
"/0/:id/1",
"/1/:id/",
"/1/:id/2",
"/aa",
"/a/",
"/admin",
"/admin/static",
"/admin/:category",
"/admin/:category/:page",
"/doc",
"/doc/rust_faq.html",
"/doc/rust1.26.html",
"/no/a",
"/no/b",
"/no/a/b/*other",
"/api/:page/:name",
"/api/hello/:name/bar/",
"/api/bar/:name",
"/api/baz/foo",
"/api/baz/foo/bar",
"/foo/:p",
],
"/hi/" => ExtraTrailingSlash,
"/b" => MissingTrailingSlash,
"/search/rustacean/" => ExtraTrailingSlash,
"/cmd/vet" => MissingTrailingSlash,
"/src" => NotFound,
"/src/" => NotFound,
"/x/" => ExtraTrailingSlash,
"/y" => MissingTrailingSlash,
"/0/rust/" => ExtraTrailingSlash,
"/1/rust" => MissingTrailingSlash,
"/a" => MissingTrailingSlash,
"/admin/" => ExtraTrailingSlash,
"/doc/" => ExtraTrailingSlash,
"/admin/static/" => ExtraTrailingSlash,
"/admin/cfg/" => ExtraTrailingSlash,
"/admin/cfg/users/" => ExtraTrailingSlash,
"/api/hello/x/bar" => MissingTrailingSlash,
"/api/baz/foo/" => ExtraTrailingSlash,
"/api/baz/bax/" => ExtraTrailingSlash,
"/api/bar/huh/" => ExtraTrailingSlash,
"/api/baz/foo/bar/" => ExtraTrailingSlash,
"/api/world/abc/" => ExtraTrailingSlash,
"/foo/pp/" => ExtraTrailingSlash,
"/" => NotFound,
"/no" => NotFound,
"/no/" => NotFound,
"/no/a/b" => NotFound,
"/no/a/b/" => NotFound,
"/_" => NotFound,
"/_/" => NotFound,
"/api" => NotFound,
"/api/" => NotFound,
"/api/hello/x/foo" => NotFound,
"/api/baz/foo/bad" => NotFound,
"/foo/p/p" => NotFound,
},
backtracking_tsr {
routes = [
"/a/:b/:c",
"/a/b/:c/d/",
],
"/a/b/c/d" => MissingTrailingSlash,
},
same_len {
routes = ["/foo", "/bar/"],
"/baz" => NotFound,
},
root_tsr_wildcard {
routes = ["/:foo"],
"/" => NotFound,
},
root_tsr_static {
routes = ["/foo"],
"/" => NotFound,
},
root_tsr {
routes = [
"/foo",
"/bar",
"/:baz"
],
"/" => NotFound,
},
double_overlap_tsr {
routes = [
"/:object/:id",
"/secret/:id/path",
"/secret/978/",
"/other/:object/:id/",
"/other/an_object/:id",
"/other/static/path",
"/other/long/static/path/"
],
"/secret/978/path/" => ExtraTrailingSlash,
"/object/id/" => ExtraTrailingSlash,
"/object/id/path" => NotFound,
"/secret/978" => MissingTrailingSlash,
"/other/object/1" => MissingTrailingSlash,
"/other/object/1/2" => NotFound,
"/other/an_object/1/" => ExtraTrailingSlash,
"/other/static/path/" => ExtraTrailingSlash,
"/other/long/static/path" => MissingTrailingSlash,
"/other/object/static/path" => NotFound,
},
}
macro_rules! match_tests {
($($name:ident {
routes = $routes:expr,
$( $path:literal :: $route:literal =>
$( $(@$none:tt)? None )?
$( $(@$some:tt)? { $( $key:literal => $val:literal ),* $(,)? } )?
),* $(,)?
}),* $(,)?) => { $(
#[test]
fn $name() {
let mut router = Router::new();
for route in $routes {
router.insert(route, route.to_owned())
.unwrap_or_else(|e| panic!("error when inserting route '{}': {:?}", route, e));
}
$(match router.at($path) {
Err(_) => {
$($( @$some )?
panic!("Expected value for route '{}'", $path)
)?
}
Ok(result) => {
$($( @$some )?
if result.value != $route {
panic!(
"Wrong value for route '{}'. Expected '{}', found '{}')",
$path, result.value, $route
);
}
let expected_params = vec![$(($key, $val)),*];
let got_params = result.params.iter().collect::<Vec<_>>();
assert_eq!(
got_params, expected_params,
"Wrong params for route '{}'",
$path
);
router.at_mut($path).unwrap().value.push_str("CHECKED");
assert!(router.at($path).unwrap().value.contains("CHECKED"));
let val = router.at_mut($path).unwrap().value;
*val = val.replace("CHECKED", "");
)?
$($( @$none )?
panic!(
"Unexpected value for route '{}', got: {:?}",
$path,
result.params.iter().collect::<Vec<_>>()
);
)?
}
})*
if let Err((got, expected)) = router.check_priorities() {
panic!(
"priority mismatch for node: got '{}', expected '{}'",
got, expected
)
}
}
)* };
}
macro_rules! insert_tests {
($($name:ident {
$($route:literal => $res:expr),* $(,)?
}),* $(,)?) => { $(
#[test]
fn $name() {
let mut router = Router::new();
$(
let res = router.insert($route, $route.to_owned());
assert_eq!(res, $res, "unexpected result for path '{}'", $route);
)*
}
)* };
}
macro_rules! tsr_tests {
($($name:ident {
routes = $routes:expr,
$($path:literal => $tsr:ident),* $(,)?
}),* $(,)?) => { $(
#[test]
fn $name() {
let mut router = Router::new();
for route in $routes {
router.insert(route, route.to_owned())
.unwrap_or_else(|e| panic!("error when inserting route '{}': {:?}", route, e));
}
$(
match router.at($path) {
Err(MatchError::$tsr) => {},
Err(e) => panic!("wrong tsr value for '{}', expected {}, found {}", $path, MatchError::$tsr, e),
res => panic!("unexpected result for '{}': {:?}", $path, res)
}
)*
}
)* };
}
pub(self) use {insert_tests, match_tests, tsr_tests};