github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/branch_control/expr_parser_test.go (about) 1 // Copyright 2022 Dolthub, 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 // 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 branch_control 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/dolthub/go-mysql-server/sql" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func TestSingleMatch(t *testing.T) { 26 tests := []struct { 27 expression string 28 testStr string 29 matches bool 30 collation sql.CollationID 31 }{ 32 {"a__", "abc", true, sql.Collation_utf8mb4_0900_bin}, 33 {"a__", "abcd", false, sql.Collation_utf8mb4_0900_bin}, 34 {"a%b", "acb", true, sql.Collation_utf8mb4_0900_bin}, 35 {"a%b", "acdkeflskjfdklb", true, sql.Collation_utf8mb4_0900_bin}, 36 {"a%b", "ab", true, sql.Collation_utf8mb4_0900_bin}, 37 {"a%b", "a", false, sql.Collation_utf8mb4_0900_bin}, 38 {"a_b", "ab", false, sql.Collation_utf8mb4_0900_bin}, 39 {"aa:%", "aa:bb:cc:dd:ee:ff", true, sql.Collation_utf8mb4_0900_bin}, 40 {"aa:%", "AA:BB:CC:DD:EE:FF", false, sql.Collation_utf8mb4_0900_bin}, 41 {"aa:%", "AA:BB:CC:DD:EE:FF", true, sql.Collation_utf8mb4_0900_ai_ci}, 42 {"a_%_b%_%c", "AaAbCc", true, sql.Collation_utf8mb4_0900_ai_ci}, 43 {"a_%_b%_%c", "AaAbBcCbCc", true, sql.Collation_utf8mb4_0900_ai_ci}, 44 {"a_%_b%_%c", "AbbbbC", true, sql.Collation_utf8mb4_0900_ai_ci}, 45 {"a_%_n%_%z", "aBcDeFgHiJkLmNoPqRsTuVwXyZ", true, sql.Collation_utf8mb4_0900_ai_ci}, 46 {`a\%b`, "acb", false, sql.Collation_utf8mb4_0900_bin}, 47 {`a\%b`, "a%b", true, sql.Collation_utf8mb4_0900_bin}, 48 {`a\%b`, "A%B", false, sql.Collation_utf8mb4_0900_bin}, 49 {`a\%b`, "A%B", true, sql.Collation_utf8mb4_0900_ai_ci}, 50 {`a`, "a", true, sql.Collation_utf8mb4_0900_bin}, 51 {`ab`, "a", false, sql.Collation_utf8mb4_0900_bin}, 52 {`a\b`, "a", false, sql.Collation_utf8mb4_0900_bin}, 53 {`a\\b`, "a", false, sql.Collation_utf8mb4_0900_bin}, 54 {`a\\\b`, "a", false, sql.Collation_utf8mb4_0900_bin}, 55 {`a`, "a", true, sql.Collation_utf8mb4_0900_ai_ci}, 56 {`ab`, "a", false, sql.Collation_utf8mb4_0900_ai_ci}, 57 {`a\b`, "a", false, sql.Collation_utf8mb4_0900_ai_ci}, 58 {`a\\b`, "a", false, sql.Collation_utf8mb4_0900_ai_ci}, 59 {`a\\\b`, "a", false, sql.Collation_utf8mb4_0900_ai_ci}, 60 {`A%%%%`, "abc", true, sql.Collation_utf8mb4_0900_ai_ci}, 61 {`A%%%%bc`, "abc", true, sql.Collation_utf8mb4_0900_ai_ci}, 62 } 63 64 for _, test := range tests { 65 t.Run(fmt.Sprintf("%q matches %q", test.testStr, test.expression), func(t *testing.T) { 66 parsedExpression := ParseExpression(FoldExpression(test.expression), test.collation) 67 matchCount := Match([]MatchExpression{{0, parsedExpression}}, test.testStr, test.collation) 68 if test.matches { 69 require.Len(t, matchCount, 1) 70 } else { 71 require.Len(t, matchCount, 0) 72 } 73 }) 74 } 75 } 76 77 func TestMultipleMatch(t *testing.T) { 78 collation := sql.Collation_utf8mb4_0900_ai_ci 79 matchExprs := []MatchExpression{ 80 {0, ParseExpression(FoldExpression("a__"), collation)}, 81 {1, ParseExpression(FoldExpression("a%b"), collation)}, 82 {2, ParseExpression(FoldExpression("a_b"), collation)}, 83 {3, ParseExpression(FoldExpression("aa:%"), collation)}, 84 {4, ParseExpression(FoldExpression("a_%_b%_%c"), collation)}, 85 {5, ParseExpression(FoldExpression(`a\%b`), collation)}, 86 {6, ParseExpression(FoldExpression(`a`), collation)}, 87 {7, ParseExpression(FoldExpression(`ab`), collation)}, 88 {8, ParseExpression(FoldExpression(`a\\b`), collation)}, 89 {9, ParseExpression(FoldExpression(`A%%%%`), collation)}, 90 {10, ParseExpression(FoldExpression(`A%%%%bc`), collation)}, 91 {11, ParseExpression(FoldExpression("a_%_b%_%c%"), collation)}, 92 {12, ParseExpression(FoldExpression("a_%_n%_%z"), collation)}, 93 } 94 tests := []struct { 95 testStr string 96 indexes []uint32 97 }{ 98 {"a", []uint32{6, 9}}, 99 {"ab", []uint32{1, 7, 9}}, 100 {"abc", []uint32{0, 9, 10}}, 101 {"acb", []uint32{0, 1, 2, 9}}, 102 {"abcd", []uint32{9}}, 103 {"acdkeflskjfdklb", []uint32{1, 9}}, 104 {"acdkeflskjfdklbc", []uint32{9, 10}}, 105 {"aa:bb:cc:dd:ee:ff", []uint32{3, 9, 11}}, 106 {"AA:BB:CC:DD:EE:FF", []uint32{3, 9, 11}}, 107 {"AaAbCc", []uint32{4, 9, 11}}, 108 {"AaAbBcCbCc", []uint32{4, 9, 11}}, 109 {"AbbbbC", []uint32{4, 9, 10, 11}}, 110 {"aBcDeFgHiJkLmNoPqRsTuVwXyZ", []uint32{9, 12}}, 111 {"a%b", []uint32{0, 1, 2, 5, 9}}, 112 {"A%B", []uint32{0, 1, 2, 5, 9}}, 113 } 114 115 for _, test := range tests { 116 t.Run(fmt.Sprintf("%q", test.testStr), func(t *testing.T) { 117 actualMatches := Match(matchExprs, test.testStr, collation) 118 require.ElementsMatch(t, test.indexes, actualMatches) 119 }) 120 } 121 } 122 123 func BenchmarkSimpleCase(b *testing.B) { 124 collation := sql.Collation_utf8mb4_0900_ai_ci 125 matchExprs := []MatchExpression{ 126 {0, ParseExpression(FoldExpression("a__"), collation)}, 127 {1, ParseExpression(FoldExpression("a%b"), collation)}, 128 {2, ParseExpression(FoldExpression("a_b"), collation)}, 129 {3, ParseExpression(FoldExpression("aa:%"), collation)}, 130 {4, ParseExpression(FoldExpression("a_%_b%_%c"), collation)}, 131 {5, ParseExpression(FoldExpression(`a\%b`), collation)}, 132 {6, ParseExpression(FoldExpression(`a`), collation)}, 133 {7, ParseExpression(FoldExpression(`ab`), collation)}, 134 {8, ParseExpression(FoldExpression(`a\\b`), collation)}, 135 {9, ParseExpression(FoldExpression(`A%%%%`), collation)}, 136 {10, ParseExpression(FoldExpression(`A%%%%bc`), collation)}, 137 {11, ParseExpression(FoldExpression("a_%_b%_%c%"), collation)}, 138 {12, ParseExpression(FoldExpression("a_%_n%_%z"), collation)}, 139 } 140 tests := []struct { 141 testStr string 142 matches []uint32 143 }{ 144 {"a", []uint32{6, 9}}, 145 {"ab", []uint32{1, 7, 9}}, 146 {"abc", []uint32{0, 9, 10}}, 147 {"acb", []uint32{0, 1, 2, 9}}, 148 {"abcd", []uint32{9}}, 149 {"acdkeflskjfdklb", []uint32{1, 9}}, 150 {"acdkeflskjfdklbc", []uint32{9, 10}}, 151 {"aa:bb:cc:dd:ee:ff", []uint32{3, 9, 11}}, 152 {"AA:BB:CC:DD:EE:FF", []uint32{3, 9, 11}}, 153 {"AaAbCc", []uint32{4, 9, 11}}, 154 {"AaAbBcCbCc", []uint32{4, 9, 11}}, 155 {"AbbbbC", []uint32{4, 9, 10, 11}}, 156 {"aBcDeFgHiJkLmNoPqRsTuVwXyZ", []uint32{9, 12}}, 157 {"a%b", []uint32{0, 1, 2, 5, 9}}, 158 {"A%B", []uint32{0, 1, 2, 5, 9}}, 159 } 160 testLen := len(tests) 161 b.ResetTimer() 162 for i := 0; i < b.N; i++ { 163 test := tests[i%testLen] 164 indexes := Match(matchExprs, test.testStr, collation) 165 indexPool.Put(indexes) 166 } 167 b.ReportAllocs() 168 }