github.com/waldiirawan/apm-agent-go/v2@v2.2.2/internal/wildcard/matcher_test.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // 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,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package wildcard
    19  
    20  import (
    21  	"encoding/json"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"regexp"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestWildcardSpec(t *testing.T) {
    33  	// {name -> {pattern -> {input -> match?}}}
    34  	var tests map[string]map[string]map[string]bool
    35  
    36  	data, err := ioutil.ReadFile("../testdata/json-specs/wildcard_matcher_tests.json")
    37  	require.NoError(t, err)
    38  	err = json.Unmarshal(data, &tests)
    39  	require.NoError(t, err)
    40  
    41  	for name, patterns := range tests {
    42  		t.Run(name, func(t *testing.T) {
    43  			for pattern, inputs := range patterns {
    44  				origPattern := pattern
    45  				caseSensitivity := CaseInsensitive
    46  				if strings.HasPrefix(pattern, "(?-i)") {
    47  					caseSensitivity = CaseSensitive
    48  					pattern = pattern[len("(?-i)"):]
    49  				}
    50  				matcher := NewMatcher(pattern, caseSensitivity)
    51  				for input, expectMatch := range inputs {
    52  					match := matcher.Match(input)
    53  					assert.Equal(t, expectMatch, match, "Match(%q, %q)", origPattern, input)
    54  				}
    55  			}
    56  		})
    57  	}
    58  }
    59  
    60  func TestWildcardStartsWith(t *testing.T) {
    61  	mS := NewMatcher("foo*", CaseSensitive)
    62  	mI := NewMatcher("foo*", CaseInsensitive)
    63  	for _, m := range []*Matcher{mS, mI} {
    64  		assert.True(t, m.Match("foo"))
    65  		assert.True(t, m.Match("foobar"))
    66  		assert.False(t, m.Match("bar"))
    67  		assert.False(t, m.Match("barfoo"))
    68  		assert.False(t, m.Match(""))
    69  	}
    70  	assert.True(t, mI.Match("FoO"))
    71  	assert.False(t, mS.Match("FoO"))
    72  }
    73  
    74  func TestWildcardEndsWith(t *testing.T) {
    75  	mS := NewMatcher("*foo", CaseSensitive)
    76  	mI := NewMatcher("*foo", CaseInsensitive)
    77  	for _, m := range []*Matcher{mS, mI} {
    78  		assert.True(t, m.Match("foo"))
    79  		assert.True(t, m.Match("barfoo"))
    80  		assert.True(t, m.Match("\xed\xbf\xbf\x80foo"))
    81  		assert.False(t, m.Match("foobar"))
    82  		assert.False(t, m.Match("bar"))
    83  		assert.False(t, m.Match(""))
    84  	}
    85  	assert.True(t, mI.Match("BaRFoO"))
    86  	assert.False(t, mS.Match("BaRFoO"))
    87  }
    88  
    89  func TestWildcardEqual(t *testing.T) {
    90  	mS := NewMatcher("foo", CaseSensitive)
    91  	mI := NewMatcher("foo", CaseInsensitive)
    92  	for _, m := range []*Matcher{mS, mI} {
    93  		assert.True(t, m.Match("foo"))
    94  		assert.False(t, m.Match("foobar"))
    95  		assert.False(t, m.Match("bar"))
    96  		assert.False(t, m.Match("barfoo"))
    97  		assert.False(t, m.Match(""))
    98  	}
    99  	assert.True(t, mI.Match("FoO"))
   100  	assert.False(t, mS.Match("FoO"))
   101  }
   102  
   103  func TestWildcardAll(t *testing.T) {
   104  	mS := NewMatcher("*", CaseSensitive)
   105  	mI := NewMatcher("*", CaseInsensitive)
   106  	for _, m := range []*Matcher{mS, mI} {
   107  		assert.True(t, m.Match(""))
   108  		assert.True(t, m.Match("x"))
   109  	}
   110  }
   111  
   112  func TestWildcardEmptyPattern(t *testing.T) {
   113  	mS := NewMatcher("", CaseSensitive)
   114  	mI := NewMatcher("", CaseInsensitive)
   115  	for _, m := range []*Matcher{mS, mI} {
   116  		assert.True(t, m.Match(""))
   117  		assert.False(t, m.Match("x"))
   118  	}
   119  }
   120  
   121  func TestWildcardMultiples(t *testing.T) {
   122  	mS := NewMatcher("a*b*c", CaseSensitive)
   123  	mI := NewMatcher("a*b*c", CaseInsensitive)
   124  	for _, m := range []*Matcher{mS, mI} {
   125  		assert.True(t, m.Match("abc"))
   126  		assert.True(t, m.Match("abbc"))
   127  		assert.True(t, m.Match("aabc"))
   128  		assert.True(t, m.Match("abcc"))
   129  		assert.False(t, m.Match("ab"))
   130  		assert.False(t, m.Match("bc"))
   131  		assert.False(t, m.Match("ac"))
   132  		assert.False(t, m.Match("_abc_"))
   133  		assert.False(t, m.Match(""))
   134  	}
   135  }
   136  
   137  func TestWildcardSandwich(t *testing.T) {
   138  	mS := NewMatcher("a*c", CaseSensitive)
   139  	mI := NewMatcher("a*c", CaseInsensitive)
   140  	for _, m := range []*Matcher{mS, mI} {
   141  		assert.True(t, m.Match("abc"))
   142  		assert.True(t, m.Match("abbc"))
   143  		assert.True(t, m.Match("aabc"))
   144  		assert.True(t, m.Match("abcc"))
   145  		assert.True(t, m.Match("ac"))
   146  		assert.False(t, m.Match("ab"))
   147  		assert.False(t, m.Match("bc"))
   148  		assert.False(t, m.Match("_abc_"))
   149  		assert.False(t, m.Match(""))
   150  	}
   151  }
   152  
   153  var benchmarkPatterns = []string{
   154  	"password",
   155  	"passwd",
   156  	"pwd",
   157  	"secret",
   158  	"*key",
   159  	"*token",
   160  	"*session*",
   161  	"*credit*",
   162  	"*card*",
   163  	"*principal*",
   164  }
   165  
   166  func BenchmarkWildcardMatcher(b *testing.B) {
   167  	matchers := make(Matchers, len(benchmarkPatterns))
   168  	for i, p := range benchmarkPatterns {
   169  		matchers[i] = NewMatcher(p, CaseInsensitive)
   170  	}
   171  	b.ResetTimer()
   172  	benchmarkMatch(b, matchers.MatchAny)
   173  }
   174  
   175  func BenchmarkRegexpMatcher(b *testing.B) {
   176  	patterns := make([]string, len(benchmarkPatterns))
   177  	for i, p := range benchmarkPatterns {
   178  		patterns[i] = strings.Replace(p, "*", ".*", -1)
   179  	}
   180  	re := regexp.MustCompile(fmt.Sprintf("(?i:%s)", strings.Join(patterns, "|")))
   181  	b.ResetTimer()
   182  	benchmarkMatch(b, re.MatchString)
   183  }
   184  
   185  func benchmarkMatch(b *testing.B, match func(s string) bool) {
   186  	var bytes int64
   187  	test := func(s string, expect bool) {
   188  		if match(s) != expect {
   189  			panic("nope")
   190  		}
   191  		bytes += int64(len(s))
   192  	}
   193  	for i := 0; i < b.N; i++ {
   194  		test("foo", false)
   195  		test("session", true)
   196  		test("passwork", false)
   197  		test("pwd", true)
   198  		test("credit_card", true)
   199  		test("zing", false)
   200  		test("boop", false)
   201  
   202  		b.SetBytes(bytes)
   203  		bytes = 0
   204  	}
   205  }