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
31namespace shrpx {
32
33struct Pattern {
34  StringRef pattern;
35  size_t idx;
36  bool wildcard;
37};
38
39void 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
102void 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
146void 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