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