istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/security/authz/matcher/string_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package matcher
    16  
    17  import (
    18  	"testing"
    19  
    20  	matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
    21  	"github.com/google/go-cmp/cmp"
    22  	"google.golang.org/protobuf/testing/protocmp"
    23  )
    24  
    25  type testCase struct {
    26  	name   string
    27  	v      string
    28  	prefix string
    29  	want   *matcher.StringMatcher
    30  }
    31  
    32  func TestStringMatcherWithPrefix(t *testing.T) {
    33  	testCases := []testCase{
    34  		{
    35  			name:   "wildcardAsRequired",
    36  			v:      "*",
    37  			prefix: "abc",
    38  			want:   StringMatcherRegex(".+"),
    39  		},
    40  		{
    41  			name:   "prefix",
    42  			v:      "-prefix-*",
    43  			prefix: "abc",
    44  			want: &matcher.StringMatcher{
    45  				MatchPattern: &matcher.StringMatcher_Prefix{
    46  					Prefix: "abc-prefix-",
    47  				},
    48  			},
    49  		},
    50  		{
    51  			name:   "suffix-empty-prefix",
    52  			v:      "*-suffix",
    53  			prefix: "",
    54  			want: &matcher.StringMatcher{
    55  				MatchPattern: &matcher.StringMatcher_Suffix{
    56  					Suffix: "-suffix",
    57  				},
    58  			},
    59  		},
    60  		{
    61  			name:   "suffix",
    62  			v:      "*-suffix",
    63  			prefix: "abc",
    64  			want:   StringMatcherRegex("abc.*-suffix"),
    65  		},
    66  		{
    67  			name:   "exact",
    68  			v:      "-exact",
    69  			prefix: "abc",
    70  			want: &matcher.StringMatcher{
    71  				MatchPattern: &matcher.StringMatcher_Exact{
    72  					Exact: "abc-exact",
    73  				},
    74  			},
    75  		},
    76  	}
    77  
    78  	for _, tc := range testCases {
    79  		t.Run(tc.name, func(t *testing.T) {
    80  			actual := StringMatcherWithPrefix(tc.v, tc.prefix)
    81  			if !cmp.Equal(actual, tc.want, protocmp.Transform()) {
    82  				t.Errorf("want %s but got %s", tc.want.String(), actual.String())
    83  			}
    84  		})
    85  	}
    86  }
    87  
    88  func TestStringMatcherRegex(t *testing.T) {
    89  	testCases := []testCase{
    90  		{
    91  			name: "wildcardAsRequired",
    92  			v:    "*",
    93  			want: &matcher.StringMatcher{
    94  				MatchPattern: &matcher.StringMatcher_SafeRegex{
    95  					SafeRegex: &matcher.RegexMatcher{
    96  						Regex: "*",
    97  					},
    98  				},
    99  			},
   100  		},
   101  		{
   102  			name: "regexExpression",
   103  			v:    "+?",
   104  			want: &matcher.StringMatcher{
   105  				MatchPattern: &matcher.StringMatcher_SafeRegex{
   106  					SafeRegex: &matcher.RegexMatcher{
   107  						Regex: "+?",
   108  					},
   109  				},
   110  			},
   111  		},
   112  	}
   113  
   114  	for _, tc := range testCases {
   115  		t.Run(tc.name, func(t *testing.T) {
   116  			if actual := StringMatcherRegex(tc.v); !cmp.Equal(actual, tc.want, protocmp.Transform()) {
   117  				t.Errorf("want %s but got %s", tc.want.String(), actual.String())
   118  			}
   119  		})
   120  	}
   121  }
   122  
   123  func TestStringMatcherPrefix(t *testing.T) {
   124  	testCases := []struct {
   125  		name       string
   126  		str        string
   127  		ignoreCase bool
   128  		want       *matcher.StringMatcher
   129  	}{
   130  		{
   131  			name:       "prefix1",
   132  			str:        "foo",
   133  			ignoreCase: true,
   134  			want: &matcher.StringMatcher{
   135  				IgnoreCase: true,
   136  				MatchPattern: &matcher.StringMatcher_Prefix{
   137  					Prefix: "foo",
   138  				},
   139  			},
   140  		},
   141  		{
   142  			name:       "prefix2",
   143  			str:        "bar",
   144  			ignoreCase: false,
   145  			want: &matcher.StringMatcher{
   146  				IgnoreCase: false,
   147  				MatchPattern: &matcher.StringMatcher_Prefix{
   148  					Prefix: "bar",
   149  				},
   150  			},
   151  		},
   152  	}
   153  
   154  	for _, tc := range testCases {
   155  		t.Run(tc.name, func(t *testing.T) {
   156  			got := StringMatcherPrefix(tc.str, tc.ignoreCase)
   157  			if !cmp.Equal(got, tc.want, protocmp.Transform()) {
   158  				t.Errorf("want %v but got %v", tc.want, got)
   159  			}
   160  		})
   161  	}
   162  }
   163  
   164  func TestStringMatcherSuffix(t *testing.T) {
   165  	testCases := []struct {
   166  		name       string
   167  		str        string
   168  		ignoreCase bool
   169  		want       *matcher.StringMatcher
   170  	}{
   171  		{
   172  			name:       "suffix1",
   173  			str:        "foo",
   174  			ignoreCase: true,
   175  			want: &matcher.StringMatcher{
   176  				IgnoreCase: true,
   177  				MatchPattern: &matcher.StringMatcher_Suffix{
   178  					Suffix: "foo",
   179  				},
   180  			},
   181  		},
   182  		{
   183  			name:       "suffix2",
   184  			str:        "bar",
   185  			ignoreCase: false,
   186  			want: &matcher.StringMatcher{
   187  				IgnoreCase: false,
   188  				MatchPattern: &matcher.StringMatcher_Suffix{
   189  					Suffix: "bar",
   190  				},
   191  			},
   192  		},
   193  	}
   194  
   195  	for _, tc := range testCases {
   196  		t.Run(tc.name, func(t *testing.T) {
   197  			got := StringMatcherSuffix(tc.str, tc.ignoreCase)
   198  			if !cmp.Equal(got, tc.want, protocmp.Transform()) {
   199  				t.Errorf("want %v but got %v", tc.want, got)
   200  			}
   201  		})
   202  	}
   203  }
   204  
   205  func TestStringMatcherExact(t *testing.T) {
   206  	testCases := []struct {
   207  		name       string
   208  		str        string
   209  		ignoreCase bool
   210  		want       *matcher.StringMatcher
   211  	}{
   212  		{
   213  			name:       "exact1",
   214  			str:        "foo",
   215  			ignoreCase: true,
   216  			want: &matcher.StringMatcher{
   217  				IgnoreCase: true,
   218  				MatchPattern: &matcher.StringMatcher_Exact{
   219  					Exact: "foo",
   220  				},
   221  			},
   222  		},
   223  		{
   224  			name:       "exact2",
   225  			str:        "bar",
   226  			ignoreCase: false,
   227  			want: &matcher.StringMatcher{
   228  				IgnoreCase: false,
   229  				MatchPattern: &matcher.StringMatcher_Exact{
   230  					Exact: "bar",
   231  				},
   232  			},
   233  		},
   234  	}
   235  
   236  	for _, tc := range testCases {
   237  		t.Run(tc.name, func(t *testing.T) {
   238  			got := StringMatcherExact(tc.str, tc.ignoreCase)
   239  			if !cmp.Equal(got, tc.want, protocmp.Transform()) {
   240  				t.Errorf("want %v but got %v", tc.want, got)
   241  			}
   242  		})
   243  	}
   244  }