1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2016 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "shrpx_router_test.h"
26
27 #include <CUnit/CUnit.h>
28
29 #include "shrpx_router.h"
30
31 namespace shrpx {
32
33 struct Pattern {
34 StringRef pattern;
35 size_t idx;
36 bool wildcard;
37 };
38
test_shrpx_router_match(void)39 void test_shrpx_router_match(void) {
40 auto patterns = std::vector<Pattern>{
41 {StringRef::from_lit("nghttp2.org/"), 0},
42 {StringRef::from_lit("nghttp2.org/alpha"), 1},
43 {StringRef::from_lit("nghttp2.org/alpha/"), 2},
44 {StringRef::from_lit("nghttp2.org/alpha/bravo/"), 3},
45 {StringRef::from_lit("www.nghttp2.org/alpha/"), 4},
46 {StringRef::from_lit("/alpha"), 5},
47 {StringRef::from_lit("example.com/alpha/"), 6},
48 {StringRef::from_lit("nghttp2.org/alpha/bravo2/"), 7},
49 {StringRef::from_lit("www2.nghttp2.org/alpha/"), 8},
50 {StringRef::from_lit("www2.nghttp2.org/alpha2/"), 9},
51 };
52
53 Router router;
54
55 for (auto &p : patterns) {
56 router.add_route(p.pattern, p.idx);
57 }
58
59 ssize_t idx;
60
61 idx = router.match(StringRef::from_lit("nghttp2.org"),
62 StringRef::from_lit("/"));
63
64 CU_ASSERT(0 == idx);
65
66 idx = router.match(StringRef::from_lit("nghttp2.org"),
67 StringRef::from_lit("/alpha"));
68
69 CU_ASSERT(1 == idx);
70
71 idx = router.match(StringRef::from_lit("nghttp2.org"),
72 StringRef::from_lit("/alpha/"));
73
74 CU_ASSERT(2 == idx);
75
76 idx = router.match(StringRef::from_lit("nghttp2.org"),
77 StringRef::from_lit("/alpha/charlie"));
78
79 CU_ASSERT(2 == idx);
80
81 idx = router.match(StringRef::from_lit("nghttp2.org"),
82 StringRef::from_lit("/alpha/bravo/"));
83
84 CU_ASSERT(3 == idx);
85
86 // matches pattern when last '/' is missing in path
87 idx = router.match(StringRef::from_lit("nghttp2.org"),
88 StringRef::from_lit("/alpha/bravo"));
89
90 CU_ASSERT(3 == idx);
91
92 idx = router.match(StringRef::from_lit("www2.nghttp2.org"),
93 StringRef::from_lit("/alpha"));
94
95 CU_ASSERT(8 == idx);
96
97 idx = router.match(StringRef{}, StringRef::from_lit("/alpha"));
98
99 CU_ASSERT(5 == idx);
100 }
101
test_shrpx_router_match_wildcard(void)102 void test_shrpx_router_match_wildcard(void) {
103 constexpr auto patterns = std::array<Pattern, 6>{{
104 {StringRef::from_lit("nghttp2.org/"), 0},
105 {StringRef::from_lit("nghttp2.org/"), 1, true},
106 {StringRef::from_lit("nghttp2.org/alpha/"), 2},
107 {StringRef::from_lit("nghttp2.org/alpha/"), 3, true},
108 {StringRef::from_lit("nghttp2.org/bravo"), 4},
109 {StringRef::from_lit("nghttp2.org/bravo"), 5, true},
110 }};
111
112 Router router;
113
114 for (auto &p : patterns) {
115 router.add_route(p.pattern, p.idx, p.wildcard);
116 }
117
118 CU_ASSERT(0 == router.match(StringRef::from_lit("nghttp2.org"),
119 StringRef::from_lit("/")));
120
121 CU_ASSERT(1 == router.match(StringRef::from_lit("nghttp2.org"),
122 StringRef::from_lit("/a")));
123
124 CU_ASSERT(1 == router.match(StringRef::from_lit("nghttp2.org"),
125 StringRef::from_lit("/charlie")));
126
127 CU_ASSERT(2 == router.match(StringRef::from_lit("nghttp2.org"),
128 StringRef::from_lit("/alpha")));
129
130 CU_ASSERT(2 == router.match(StringRef::from_lit("nghttp2.org"),
131 StringRef::from_lit("/alpha/")));
132
133 CU_ASSERT(3 == router.match(StringRef::from_lit("nghttp2.org"),
134 StringRef::from_lit("/alpha/b")));
135
136 CU_ASSERT(4 == router.match(StringRef::from_lit("nghttp2.org"),
137 StringRef::from_lit("/bravo")));
138
139 CU_ASSERT(5 == router.match(StringRef::from_lit("nghttp2.org"),
140 StringRef::from_lit("/bravocharlie")));
141
142 CU_ASSERT(5 == router.match(StringRef::from_lit("nghttp2.org"),
143 StringRef::from_lit("/bravo/")));
144 }
145
test_shrpx_router_match_prefix(void)146 void test_shrpx_router_match_prefix(void) {
147 auto patterns = std::vector<Pattern>{
148 {StringRef::from_lit("gro.2ptthgn."), 0},
149 {StringRef::from_lit("gro.2ptthgn.www."), 1},
150 {StringRef::from_lit("gro.2ptthgn.gmi."), 2},
151 {StringRef::from_lit("gro.2ptthgn.gmi.ahpla."), 3},
152 };
153
154 Router router;
155
156 for (auto &p : patterns) {
157 router.add_route(p.pattern, p.idx);
158 }
159
160 ssize_t idx;
161 const RNode *node;
162 size_t nread;
163
164 node = nullptr;
165
166 idx = router.match_prefix(&nread, &node,
167 StringRef::from_lit("gro.2ptthgn.gmi.ahpla.ovarb"));
168
169 CU_ASSERT(0 == idx);
170 CU_ASSERT(12 == nread);
171
172 idx = router.match_prefix(&nread, &node,
173 StringRef::from_lit("gmi.ahpla.ovarb"));
174
175 CU_ASSERT(2 == idx);
176 CU_ASSERT(4 == nread);
177
178 idx = router.match_prefix(&nread, &node, StringRef::from_lit("ahpla.ovarb"));
179
180 CU_ASSERT(3 == idx);
181 CU_ASSERT(6 == nread);
182 }
183
184 } // namespace shrpx
185