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  }