github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/stringutil/string_util_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package stringutil
    15  
    16  import (
    17  	"testing"
    18  
    19  	. "github.com/whtcorpsinc/check"
    20  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    21  )
    22  
    23  func TestT(t *testing.T) {
    24  	CustomVerboseFlag = true
    25  	TestingT(t)
    26  }
    27  
    28  var _ = Suite(&testStringUtilSuite{})
    29  
    30  type testStringUtilSuite struct {
    31  }
    32  
    33  func (s *testStringUtilSuite) TestUnquote(c *C) {
    34  	defer testleak.AfterTest(c)()
    35  	causet := []struct {
    36  		str    string
    37  		expect string
    38  		ok     bool
    39  	}{
    40  		{``, ``, false},
    41  		{`'`, ``, false},
    42  		{`'abc"`, ``, false},
    43  		{`abcdea`, ``, false},
    44  		{`'abc'def'`, ``, false},
    45  		{`"abc\"`, ``, false},
    46  
    47  		{`"abcdef"`, `abcdef`, true},
    48  		{`"abc'def"`, `abc'def`, true},
    49  		{`"\a汉字测试"`, `a汉字测试`, true},
    50  		{`"☺"`, `☺`, true},
    51  		{`"\xFF"`, `xFF`, true},
    52  		{`"\U00010111"`, `U00010111`, true},
    53  		{`"\U0001011111"`, `U0001011111`, true},
    54  		{`"\a\b\f\n\r\t\v\\\""`, "a\bf\n\r\tv\\\"", true},
    55  		{`"\Z\%\_"`, "\032" + `\%\_`, true},
    56  		{`"abc\0"`, "abc\000", true},
    57  		{`"abc\"abc"`, `abc"abc`, true},
    58  
    59  		{`'abcdef'`, `abcdef`, true},
    60  		{`'"'`, "\"", true},
    61  		{`'\a\b\f\n\r\t\v\\\''`, "a\bf\n\r\tv\\'", true},
    62  		{`' '`, ` `, true},
    63  		{"'\\a汉字'", "a汉字", true},
    64  		{"'\\a\x90'", "a\x90", true},
    65  		{"\"\\a\x18èàø»\x05\"", "a\x18èàø»\x05", true},
    66  	}
    67  
    68  	for _, t := range causet {
    69  		x, err := Unquote(t.str)
    70  		c.Assert(x, Equals, t.expect)
    71  		comment := Commentf("source %v", t.str)
    72  		if t.ok {
    73  			c.Assert(err, IsNil, comment)
    74  		} else {
    75  			c.Assert(err, NotNil, comment)
    76  		}
    77  	}
    78  }
    79  
    80  func (s *testStringUtilSuite) TestPatternMatch(c *C) {
    81  	defer testleak.AfterTest(c)()
    82  	tbl := []struct {
    83  		pattern string
    84  		input   string
    85  		escape  byte
    86  		match   bool
    87  	}{
    88  		{``, `a`, '\\', false},
    89  		{`a`, `a`, '\\', true},
    90  		{`a`, `b`, '\\', false},
    91  		{`aA`, `aA`, '\\', true},
    92  		{`_`, `a`, '\\', true},
    93  		{`_`, `ab`, '\\', false},
    94  		{`__`, `b`, '\\', false},
    95  		{`%`, `abcd`, '\\', true},
    96  		{`%`, ``, '\\', true},
    97  		{`%b`, `AAA`, '\\', false},
    98  		{`%a%`, `BBB`, '\\', false},
    99  		{`a%`, `BBB`, '\\', false},
   100  		{`\%a`, `%a`, '\\', true},
   101  		{`\%a`, `aa`, '\\', false},
   102  		{`\_a`, `_a`, '\\', true},
   103  		{`\_a`, `aa`, '\\', false},
   104  		{`\\_a`, `\xa`, '\\', true},
   105  		{`\a\b`, `\a\b`, '\\', true},
   106  		{`%%_`, `abc`, '\\', true},
   107  		{`%_%_aA`, "aaaA", '\\', true},
   108  		{`+_a`, `_a`, '+', true},
   109  		{`+%a`, `%a`, '+', true},
   110  		{`\%a`, `%a`, '+', false},
   111  		{`++a`, `+a`, '+', true},
   112  		{`++_a`, `+xa`, '+', true},
   113  		// We may reopen these test when like function go back to case insensitive.
   114  		/*
   115  			{"_ab", "AAB", '\\', true},
   116  			{"%a%", "BAB", '\\', true},
   117  			{"%a", "AAA", '\\', true},
   118  			{"b%", "BBB", '\\', true},
   119  		*/
   120  	}
   121  	for _, v := range tbl {
   122  		patChars, patTypes := CompilePattern(v.pattern, v.escape)
   123  		match := DoMatch(v.input, patChars, patTypes)
   124  		c.Assert(match, Equals, v.match, Commentf("%v", v))
   125  	}
   126  }
   127  
   128  func (s *testStringUtilSuite) TestCompileLike2Regexp(c *C) {
   129  	defer testleak.AfterTest(c)()
   130  	tbl := []struct {
   131  		pattern string
   132  		regexp  string
   133  	}{
   134  		{``, ``},
   135  		{`a`, `a`},
   136  		{`aA`, `aA`},
   137  		{`_`, `.`},
   138  		{`__`, `..`},
   139  		{`%`, `.*`},
   140  		{`%b`, `.*b`},
   141  		{`%a%`, `.*a.*`},
   142  		{`a%`, `a.*`},
   143  		{`\%a`, `%a`},
   144  		{`\_a`, `_a`},
   145  		{`\\_a`, `\.a`},
   146  		{`\a\b`, `\a\b`},
   147  		{`%%_`, `..*`},
   148  		{`%_%_aA`, "...*aA"},
   149  	}
   150  	for _, v := range tbl {
   151  		result := CompileLike2Regexp(v.pattern)
   152  		c.Assert(result, Equals, v.regexp, Commentf("%v", v))
   153  	}
   154  }
   155  
   156  func (s *testStringUtilSuite) TestIsExactMatch(c *C) {
   157  	defer testleak.AfterTest(c)()
   158  	tbl := []struct {
   159  		pattern    string
   160  		escape     byte
   161  		exactMatch bool
   162  	}{
   163  		{``, '\\', true},
   164  		{`_`, '\\', false},
   165  		{`%`, '\\', false},
   166  		{`a`, '\\', true},
   167  		{`a_`, '\\', false},
   168  		{`a%`, '\\', false},
   169  		{`a\_`, '\\', true},
   170  		{`a\%`, '\\', true},
   171  		{`a\\`, '\\', true},
   172  		{`a\\_`, '\\', false},
   173  		{`a+%`, '+', true},
   174  		{`a\%`, '+', false},
   175  		{`a++`, '+', true},
   176  		{`a++_`, '+', false},
   177  	}
   178  	for _, v := range tbl {
   179  		_, patTypes := CompilePattern(v.pattern, v.escape)
   180  		c.Assert(IsExactMatch(patTypes), Equals, v.exactMatch, Commentf("%v", v))
   181  	}
   182  }
   183  
   184  func (s *testStringUtilSuite) TestBuildStringFromLabels(c *C) {
   185  	defer testleak.AfterTest(c)()
   186  	testcases := []struct {
   187  		name     string
   188  		labels   map[string]string
   189  		expected string
   190  	}{
   191  		{
   192  			name:     "nil map",
   193  			labels:   nil,
   194  			expected: "",
   195  		},
   196  		{
   197  			name: "one label",
   198  			labels: map[string]string{
   199  				"aaa": "bbb",
   200  			},
   201  			expected: "aaa=bbb",
   202  		},
   203  		{
   204  			name: "two labels",
   205  			labels: map[string]string{
   206  				"aaa": "bbb",
   207  				"ccc": "ddd",
   208  			},
   209  			expected: "aaa=bbb,ccc=ddd",
   210  		},
   211  	}
   212  	for _, testcase := range testcases {
   213  		c.Log(testcase.name)
   214  		c.Assert(BuildStringFromLabels(testcase.labels), Equals, testcase.expected)
   215  	}
   216  }
   217  
   218  func BenchmarkDoMatch(b *testing.B) {
   219  	escape := byte('\\')
   220  	tbl := []struct {
   221  		pattern string
   222  		target  string
   223  	}{
   224  		{`a%_%_%_%_b`, `aababab`},
   225  		{`%_%_a%_%_b`, `bbbaaabb`},
   226  		{`a%_%_a%_%_b`, `aaaabbbbbbaaaaaaaaabbbbb`},
   227  	}
   228  
   229  	for _, v := range tbl {
   230  		b.Run(v.pattern, func(b *testing.B) {
   231  			patChars, patTypes := CompilePattern(v.pattern, escape)
   232  			b.ResetTimer()
   233  			for i := 0; i < b.N; i++ {
   234  				match := DoMatch(v.target, patChars, patTypes)
   235  				if !match {
   236  					b.Fatal("Match expected.")
   237  				}
   238  			}
   239  		})
   240  	}
   241  }
   242  
   243  func BenchmarkDoMatchNegative(b *testing.B) {
   244  	escape := byte('\\')
   245  	tbl := []struct {
   246  		pattern string
   247  		target  string
   248  	}{
   249  		{`a%a%a%a%a%a%a%a%b`, `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`},
   250  	}
   251  
   252  	for _, v := range tbl {
   253  		b.Run(v.pattern, func(b *testing.B) {
   254  			patChars, patTypes := CompilePattern(v.pattern, escape)
   255  			b.ResetTimer()
   256  			for i := 0; i < b.N; i++ {
   257  				match := DoMatch(v.target, patChars, patTypes)
   258  				if match {
   259  					b.Fatal("Unmatch expected.")
   260  				}
   261  			}
   262  		})
   263  	}
   264  }
   265  
   266  func BenchmarkBuildStringFromLabels(b *testing.B) {
   267  	cases := []struct {
   268  		name   string
   269  		labels map[string]string
   270  	}{
   271  		{
   272  			name: "normal case",
   273  			labels: map[string]string{
   274  				"aaa": "bbb",
   275  				"foo": "bar",
   276  			},
   277  		},
   278  	}
   279  
   280  	for _, testcase := range cases {
   281  		b.Run(testcase.name, func(b *testing.B) {
   282  			b.ResetTimer()
   283  			BuildStringFromLabels(testcase.labels)
   284  		})
   285  	}
   286  }