dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/utils/matcher/matcher_header_test.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * 20 * Copyright 2020 gRPC authors. 21 * 22 */ 23 24 package matcher 25 26 import ( 27 "regexp" 28 "testing" 29 ) 30 31 import ( 32 "google.golang.org/grpc/metadata" 33 ) 34 35 func TestHeaderExactMatcherMatch(t *testing.T) { 36 tests := []struct { 37 name string 38 key, exact string 39 md metadata.MD 40 want bool 41 invert bool 42 }{ 43 { 44 name: "one value one match", 45 key: "th", 46 exact: "tv", 47 md: metadata.Pairs("th", "tv"), 48 want: true, 49 }, 50 { 51 name: "two value one match", 52 key: "th", 53 exact: "tv", 54 md: metadata.Pairs("th", "abc", "th", "tv"), 55 // Doesn't match comma-concatenated string. 56 want: false, 57 }, 58 { 59 name: "two value match concatenated", 60 key: "th", 61 exact: "abc,tv", 62 md: metadata.Pairs("th", "abc", "th", "tv"), 63 want: true, 64 }, 65 { 66 name: "not match", 67 key: "th", 68 exact: "tv", 69 md: metadata.Pairs("th", "abc"), 70 want: false, 71 }, 72 { 73 name: "invert header not present", 74 key: "th", 75 exact: "tv", 76 md: metadata.Pairs(":method", "GET"), 77 want: false, 78 invert: true, 79 }, 80 { 81 name: "invert header match", 82 key: "th", 83 exact: "tv", 84 md: metadata.Pairs("th", "tv"), 85 want: false, 86 invert: true, 87 }, 88 { 89 name: "invert header not match", 90 key: "th", 91 exact: "tv", 92 md: metadata.Pairs("th", "tvv"), 93 want: true, 94 invert: true, 95 }, 96 } 97 for _, tt := range tests { 98 t.Run(tt.name, func(t *testing.T) { 99 hem := NewHeaderExactMatcher(tt.key, tt.exact, tt.invert) 100 if got := hem.Match(tt.md); got != tt.want { 101 t.Errorf("match() = %v, want %v", got, tt.want) 102 } 103 }) 104 } 105 } 106 107 func TestHeaderRegexMatcherMatch(t *testing.T) { 108 tests := []struct { 109 name string 110 key, regexStr string 111 md metadata.MD 112 want bool 113 invert bool 114 }{ 115 { 116 name: "one value one match", 117 key: "th", 118 regexStr: "^t+v*$", 119 md: metadata.Pairs("th", "tttvv"), 120 want: true, 121 }, 122 { 123 name: "two value one match", 124 key: "th", 125 regexStr: "^t+v*$", 126 md: metadata.Pairs("th", "abc", "th", "tttvv"), 127 want: false, 128 }, 129 { 130 name: "two value match concatenated", 131 key: "th", 132 regexStr: "^[abc]*,t+v*$", 133 md: metadata.Pairs("th", "abc", "th", "tttvv"), 134 want: true, 135 }, 136 { 137 name: "no match", 138 key: "th", 139 regexStr: "^t+v*$", 140 md: metadata.Pairs("th", "abc"), 141 want: false, 142 }, 143 { 144 name: "no match because only part of value matches with regex", 145 key: "header", 146 regexStr: "^a+$", 147 md: metadata.Pairs("header", "ab"), 148 want: false, 149 }, 150 { 151 name: "match because full value matches with regex", 152 key: "header", 153 regexStr: "^a+$", 154 md: metadata.Pairs("header", "aa"), 155 want: true, 156 }, 157 { 158 name: "invert header not present", 159 key: "th", 160 regexStr: "^t+v*$", 161 md: metadata.Pairs(":method", "GET"), 162 want: false, 163 invert: true, 164 }, 165 { 166 name: "invert header match", 167 key: "th", 168 regexStr: "^t+v*$", 169 md: metadata.Pairs("th", "tttvv"), 170 want: false, 171 invert: true, 172 }, 173 { 174 name: "invert header not match", 175 key: "th", 176 regexStr: "^t+v*$", 177 md: metadata.Pairs("th", "abc"), 178 want: true, 179 invert: true, 180 }, 181 } 182 for _, tt := range tests { 183 t.Run(tt.name, func(t *testing.T) { 184 hrm := NewHeaderRegexMatcher(tt.key, regexp.MustCompile(tt.regexStr), tt.invert) 185 if got := hrm.Match(tt.md); got != tt.want { 186 t.Errorf("match() = %v, want %v", got, tt.want) 187 } 188 }) 189 } 190 } 191 192 func TestHeaderRangeMatcherMatch(t *testing.T) { 193 tests := []struct { 194 name string 195 key string 196 start, end int64 197 md metadata.MD 198 want bool 199 invert bool 200 }{ 201 { 202 name: "match", 203 key: "th", 204 start: 1, end: 10, 205 md: metadata.Pairs("th", "5"), 206 want: true, 207 }, 208 { 209 name: "equal to start", 210 key: "th", 211 start: 1, end: 10, 212 md: metadata.Pairs("th", "1"), 213 want: true, 214 }, 215 { 216 name: "equal to end", 217 key: "th", 218 start: 1, end: 10, 219 md: metadata.Pairs("th", "10"), 220 want: false, 221 }, 222 { 223 name: "negative", 224 key: "th", 225 start: -10, end: 10, 226 md: metadata.Pairs("th", "-5"), 227 want: true, 228 }, 229 { 230 name: "invert header not present", 231 key: "th", 232 start: 1, end: 10, 233 md: metadata.Pairs(":method", "GET"), 234 want: false, 235 invert: true, 236 }, 237 { 238 name: "invert header match", 239 key: "th", 240 start: 1, end: 10, 241 md: metadata.Pairs("th", "5"), 242 want: false, 243 invert: true, 244 }, 245 { 246 name: "invert header not match", 247 key: "th", 248 start: 1, end: 9, 249 md: metadata.Pairs("th", "10"), 250 want: true, 251 invert: true, 252 }, 253 } 254 for _, tt := range tests { 255 t.Run(tt.name, func(t *testing.T) { 256 hrm := NewHeaderRangeMatcher(tt.key, tt.start, tt.end, tt.invert) 257 if got := hrm.Match(tt.md); got != tt.want { 258 t.Errorf("match() = %v, want %v", got, tt.want) 259 } 260 }) 261 } 262 } 263 264 func TestHeaderPresentMatcherMatch(t *testing.T) { 265 tests := []struct { 266 name string 267 key string 268 present bool 269 md metadata.MD 270 want bool 271 invert bool 272 }{ 273 { 274 name: "want present is present", 275 key: "th", 276 present: true, 277 md: metadata.Pairs("th", "tv"), 278 want: true, 279 }, 280 { 281 name: "want present not present", 282 key: "th", 283 present: true, 284 md: metadata.Pairs("abc", "tv"), 285 want: false, 286 }, 287 { 288 name: "want not present is present", 289 key: "th", 290 present: false, 291 md: metadata.Pairs("th", "tv"), 292 want: false, 293 }, 294 { 295 name: "want not present is not present", 296 key: "th", 297 present: false, 298 md: metadata.Pairs("abc", "tv"), 299 want: true, 300 }, 301 { 302 name: "invert header not present", 303 key: "th", 304 present: true, 305 md: metadata.Pairs(":method", "GET"), 306 want: true, 307 invert: true, 308 }, 309 { 310 name: "invert header match", 311 key: "th", 312 present: true, 313 md: metadata.Pairs("th", "tv"), 314 want: false, 315 invert: true, 316 }, 317 { 318 name: "invert header not match", 319 key: "th", 320 present: true, 321 md: metadata.Pairs(":method", "GET"), 322 want: true, 323 invert: true, 324 }, 325 } 326 for _, tt := range tests { 327 t.Run(tt.name, func(t *testing.T) { 328 hpm := NewHeaderPresentMatcher(tt.key, tt.present, tt.invert) 329 if got := hpm.Match(tt.md); got != tt.want { 330 t.Errorf("match() = %v, want %v", got, tt.want) 331 } 332 }) 333 } 334 } 335 336 func TestHeaderPrefixMatcherMatch(t *testing.T) { 337 tests := []struct { 338 name string 339 key, prefix string 340 md metadata.MD 341 want bool 342 invert bool 343 }{ 344 { 345 name: "one value one match", 346 key: "th", 347 prefix: "tv", 348 md: metadata.Pairs("th", "tv123"), 349 want: true, 350 }, 351 { 352 name: "two value one match", 353 key: "th", 354 prefix: "tv", 355 md: metadata.Pairs("th", "abc", "th", "tv123"), 356 want: false, 357 }, 358 { 359 name: "two value match concatenated", 360 key: "th", 361 prefix: "tv", 362 md: metadata.Pairs("th", "tv123", "th", "abc"), 363 want: true, 364 }, 365 { 366 name: "not match", 367 key: "th", 368 prefix: "tv", 369 md: metadata.Pairs("th", "abc"), 370 want: false, 371 }, 372 { 373 name: "invert header not present", 374 key: "th", 375 prefix: "tv", 376 md: metadata.Pairs(":method", "GET"), 377 want: false, 378 invert: true, 379 }, 380 { 381 name: "invert header match", 382 key: "th", 383 prefix: "tv", 384 md: metadata.Pairs("th", "tv123"), 385 want: false, 386 invert: true, 387 }, 388 { 389 name: "invert header not match", 390 key: "th", 391 prefix: "tv", 392 md: metadata.Pairs("th", "abc"), 393 want: true, 394 invert: true, 395 }, 396 } 397 for _, tt := range tests { 398 t.Run(tt.name, func(t *testing.T) { 399 hpm := NewHeaderPrefixMatcher(tt.key, tt.prefix, tt.invert) 400 if got := hpm.Match(tt.md); got != tt.want { 401 t.Errorf("match() = %v, want %v", got, tt.want) 402 } 403 }) 404 } 405 } 406 407 func TestHeaderSuffixMatcherMatch(t *testing.T) { 408 tests := []struct { 409 name string 410 key, suffix string 411 md metadata.MD 412 want bool 413 invert bool 414 }{ 415 { 416 name: "one value one match", 417 key: "th", 418 suffix: "tv", 419 md: metadata.Pairs("th", "123tv"), 420 want: true, 421 }, 422 { 423 name: "two value one match", 424 key: "th", 425 suffix: "tv", 426 md: metadata.Pairs("th", "123tv", "th", "abc"), 427 want: false, 428 }, 429 { 430 name: "two value match concatenated", 431 key: "th", 432 suffix: "tv", 433 md: metadata.Pairs("th", "abc", "th", "123tv"), 434 want: true, 435 }, 436 { 437 name: "not match", 438 key: "th", 439 suffix: "tv", 440 md: metadata.Pairs("th", "abc"), 441 want: false, 442 }, 443 { 444 name: "invert header not present", 445 key: "th", 446 suffix: "tv", 447 md: metadata.Pairs(":method", "GET"), 448 want: false, 449 invert: true, 450 }, 451 { 452 name: "invert header match", 453 key: "th", 454 suffix: "tv", 455 md: metadata.Pairs("th", "123tv"), 456 want: false, 457 invert: true, 458 }, 459 { 460 name: "invert header not match", 461 key: "th", 462 suffix: "tv", 463 md: metadata.Pairs("th", "abc"), 464 want: true, 465 invert: true, 466 }, 467 } 468 for _, tt := range tests { 469 t.Run(tt.name, func(t *testing.T) { 470 hsm := NewHeaderSuffixMatcher(tt.key, tt.suffix, tt.invert) 471 if got := hsm.Match(tt.md); got != tt.want { 472 t.Errorf("match() = %v, want %v", got, tt.want) 473 } 474 }) 475 } 476 }