github.com/btccom/go-micro/v2@v2.9.3/api/router/util/parse_test.go (about) 1 package util 2 3 // download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/parse_test.go 4 5 import ( 6 "flag" 7 "fmt" 8 "reflect" 9 "testing" 10 11 "github.com/btccom/go-micro/v2/logger" 12 ) 13 14 func TestTokenize(t *testing.T) { 15 for _, spec := range []struct { 16 src string 17 tokens []string 18 }{ 19 { 20 src: "", 21 tokens: []string{eof}, 22 }, 23 { 24 src: "v1", 25 tokens: []string{"v1", eof}, 26 }, 27 { 28 src: "v1/b", 29 tokens: []string{"v1", "/", "b", eof}, 30 }, 31 { 32 src: "v1/endpoint/*", 33 tokens: []string{"v1", "/", "endpoint", "/", "*", eof}, 34 }, 35 { 36 src: "v1/endpoint/**", 37 tokens: []string{"v1", "/", "endpoint", "/", "**", eof}, 38 }, 39 { 40 src: "v1/b/{bucket_name=*}", 41 tokens: []string{ 42 "v1", "/", 43 "b", "/", 44 "{", "bucket_name", "=", "*", "}", 45 eof, 46 }, 47 }, 48 { 49 src: "v1/b/{bucket_name=buckets/*}", 50 tokens: []string{ 51 "v1", "/", 52 "b", "/", 53 "{", "bucket_name", "=", "buckets", "/", "*", "}", 54 eof, 55 }, 56 }, 57 { 58 src: "v1/b/{bucket_name=buckets/*}/o", 59 tokens: []string{ 60 "v1", "/", 61 "b", "/", 62 "{", "bucket_name", "=", "buckets", "/", "*", "}", "/", 63 "o", 64 eof, 65 }, 66 }, 67 { 68 src: "v1/b/{bucket_name=buckets/*}/o/{name}", 69 tokens: []string{ 70 "v1", "/", 71 "b", "/", 72 "{", "bucket_name", "=", "buckets", "/", "*", "}", "/", 73 "o", "/", "{", "name", "}", 74 eof, 75 }, 76 }, 77 { 78 src: "v1/a=b&c=d;e=f:g/endpoint.rdf", 79 tokens: []string{ 80 "v1", "/", 81 "a=b&c=d;e=f:g", "/", 82 "endpoint.rdf", 83 eof, 84 }, 85 }, 86 } { 87 tokens, verb := tokenize(spec.src) 88 if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) { 89 t.Errorf("tokenize(%q) = %q, _; want %q, _", spec.src, got, want) 90 } 91 if got, want := verb, ""; got != want { 92 t.Errorf("tokenize(%q) = _, %q; want _, %q", spec.src, got, want) 93 } 94 95 src := fmt.Sprintf("%s:%s", spec.src, "LOCK") 96 tokens, verb = tokenize(src) 97 if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) { 98 t.Errorf("tokenize(%q) = %q, _; want %q, _", src, got, want) 99 } 100 if got, want := verb, "LOCK"; got != want { 101 t.Errorf("tokenize(%q) = _, %q; want _, %q", src, got, want) 102 } 103 } 104 } 105 106 func TestParseSegments(t *testing.T) { 107 flag.Set("v", "3") 108 for _, spec := range []struct { 109 tokens []string 110 want []segment 111 }{ 112 { 113 tokens: []string{"v1", eof}, 114 want: []segment{ 115 literal("v1"), 116 }, 117 }, 118 { 119 tokens: []string{"/", eof}, 120 want: []segment{ 121 wildcard{}, 122 }, 123 }, 124 { 125 tokens: []string{"-._~!$&'()*+,;=:@", eof}, 126 want: []segment{ 127 literal("-._~!$&'()*+,;=:@"), 128 }, 129 }, 130 { 131 tokens: []string{"%e7%ac%ac%e4%b8%80%e7%89%88", eof}, 132 want: []segment{ 133 literal("%e7%ac%ac%e4%b8%80%e7%89%88"), 134 }, 135 }, 136 { 137 tokens: []string{"v1", "/", "*", eof}, 138 want: []segment{ 139 literal("v1"), 140 wildcard{}, 141 }, 142 }, 143 { 144 tokens: []string{"v1", "/", "**", eof}, 145 want: []segment{ 146 literal("v1"), 147 deepWildcard{}, 148 }, 149 }, 150 { 151 tokens: []string{"{", "name", "}", eof}, 152 want: []segment{ 153 variable{ 154 path: "name", 155 segments: []segment{ 156 wildcard{}, 157 }, 158 }, 159 }, 160 }, 161 { 162 tokens: []string{"{", "name", "=", "*", "}", eof}, 163 want: []segment{ 164 variable{ 165 path: "name", 166 segments: []segment{ 167 wildcard{}, 168 }, 169 }, 170 }, 171 }, 172 { 173 tokens: []string{"{", "field", ".", "nested", ".", "nested2", "=", "*", "}", eof}, 174 want: []segment{ 175 variable{ 176 path: "field.nested.nested2", 177 segments: []segment{ 178 wildcard{}, 179 }, 180 }, 181 }, 182 }, 183 { 184 tokens: []string{"{", "name", "=", "a", "/", "b", "/", "*", "}", eof}, 185 want: []segment{ 186 variable{ 187 path: "name", 188 segments: []segment{ 189 literal("a"), 190 literal("b"), 191 wildcard{}, 192 }, 193 }, 194 }, 195 }, 196 { 197 tokens: []string{ 198 "v1", "/", 199 "{", 200 "name", ".", "nested", ".", "nested2", 201 "=", 202 "a", "/", "b", "/", "*", 203 "}", "/", 204 "o", "/", 205 "{", 206 "another_name", 207 "=", 208 "a", "/", "b", "/", "*", "/", "c", 209 "}", "/", 210 "**", 211 eof}, 212 want: []segment{ 213 literal("v1"), 214 variable{ 215 path: "name.nested.nested2", 216 segments: []segment{ 217 literal("a"), 218 literal("b"), 219 wildcard{}, 220 }, 221 }, 222 literal("o"), 223 variable{ 224 path: "another_name", 225 segments: []segment{ 226 literal("a"), 227 literal("b"), 228 wildcard{}, 229 literal("c"), 230 }, 231 }, 232 deepWildcard{}, 233 }, 234 }, 235 } { 236 p := parser{tokens: spec.tokens} 237 segs, err := p.topLevelSegments() 238 if err != nil { 239 t.Errorf("parser{%q}.segments() failed with %v; want success", spec.tokens, err) 240 continue 241 } 242 if got, want := segs, spec.want; !reflect.DeepEqual(got, want) { 243 t.Errorf("parser{%q}.segments() = %#v; want %#v", spec.tokens, got, want) 244 } 245 if got := p.tokens; len(got) > 0 { 246 t.Errorf("p.tokens = %q; want []; spec.tokens=%q", got, spec.tokens) 247 } 248 } 249 } 250 251 func TestParseSegmentsWithErrors(t *testing.T) { 252 flag.Set("v", "3") 253 for _, spec := range []struct { 254 tokens []string 255 }{ 256 { 257 // double slash 258 tokens: []string{"//", eof}, 259 }, 260 { 261 // invalid literal 262 tokens: []string{"a?b", eof}, 263 }, 264 { 265 // invalid percent-encoding 266 tokens: []string{"%", eof}, 267 }, 268 { 269 // invalid percent-encoding 270 tokens: []string{"%2", eof}, 271 }, 272 { 273 // invalid percent-encoding 274 tokens: []string{"a%2z", eof}, 275 }, 276 { 277 // empty segments 278 tokens: []string{eof}, 279 }, 280 { 281 // unterminated variable 282 tokens: []string{"{", "name", eof}, 283 }, 284 { 285 // unterminated variable 286 tokens: []string{"{", "name", "=", eof}, 287 }, 288 { 289 // unterminated variable 290 tokens: []string{"{", "name", "=", "*", eof}, 291 }, 292 { 293 // empty component in field path 294 tokens: []string{"{", "name", ".", "}", eof}, 295 }, 296 { 297 // empty component in field path 298 tokens: []string{"{", "name", ".", ".", "nested", "}", eof}, 299 }, 300 { 301 // invalid character in identifier 302 tokens: []string{"{", "field-name", "}", eof}, 303 }, 304 { 305 // no slash between segments 306 tokens: []string{"v1", "endpoint", eof}, 307 }, 308 { 309 // no slash between segments 310 tokens: []string{"v1", "{", "name", "}", eof}, 311 }, 312 } { 313 p := parser{tokens: spec.tokens} 314 segs, err := p.topLevelSegments() 315 if err == nil { 316 t.Errorf("parser{%q}.segments() succeeded; want InvalidTemplateError; accepted %#v", spec.tokens, segs) 317 continue 318 } 319 logger.Info(err) 320 } 321 }