github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/eval_internal_test.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package tree 12 13 import ( 14 "fmt" 15 "testing" 16 17 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 18 ) 19 20 func TestUnescapePattern(t *testing.T) { 21 defer leaktest.AfterTest(t)() 22 testCases := []struct { 23 pattern string 24 expected string 25 escapeToken string 26 }{ 27 {``, ``, `\`}, 28 {``, ``, `\\`}, 29 {`ABC\\`, `ABC\`, `\`}, 30 {`ABC\\\\`, `ABC\\`, `\\`}, 31 {`A\\\\BC`, `A\\BC`, `\`}, 32 {`A\\\\\\\\C`, `A\\\\C`, `\\`}, 33 {`A\\B\\C`, `A\B\C`, `\`}, 34 {`A\\\\B\\\\C`, `A\\B\\C`, `\\`}, 35 {`ABC`, `ABC`, `\`}, 36 {`ABC`, `ABC`, `\\`}, 37 {`A\BC`, `ABC`, `\`}, 38 {`A\BC`, `A\BC`, `\\`}, 39 {`A\\\BC`, `A\BC`, `\`}, 40 {`A\\\\\\BC`, `A\\BC`, `\\`}, 41 {`\漢\字`, `漢字`, `\`}, 42 {`\ \\A\B`, ` \AB`, `\`}, 43 } 44 45 for _, tc := range testCases { 46 t.Run(fmt.Sprintf("%s-->%s Escape=%s", tc.pattern, tc.expected, tc.escapeToken), func(t *testing.T) { 47 actual, err := unescapePattern(tc.pattern, tc.escapeToken, true /* emitEscapeCharacterLastError */) 48 if err != nil { 49 t.Fatal(err) 50 } 51 52 if tc.expected != actual { 53 t.Errorf("expected unescaped pattern: %s, got %s\n", tc.expected, actual) 54 } 55 }) 56 } 57 } 58 59 func TestUnescapePatternError(t *testing.T) { 60 defer leaktest.AfterTest(t)() 61 testCases := []struct { 62 pattern string 63 escapeToken string 64 }{ 65 {`\`, `\`}, 66 {`\\`, `\\`}, 67 {`ABC\`, `\`}, 68 {`ABC\\`, `\\`}, 69 {`ABC\\\`, `\`}, 70 {`ABC\\\\\\`, `\\`}, 71 } 72 73 const errorMessage = "LIKE pattern must not end with escape character" 74 75 for _, tc := range testCases { 76 t.Run(fmt.Sprintf("Pattern=%s Escape=%s", tc.pattern, tc.escapeToken), func(t *testing.T) { 77 actual, err := unescapePattern(tc.pattern, tc.escapeToken, true /* emitEscapeCharacterLastError */) 78 if err == nil { 79 t.Fatalf("error not raised. expected error message: %s\ngot unescaped pattern: %s\n", errorMessage, actual) 80 } 81 82 if err.Error() != errorMessage { 83 t.Errorf("expected error message: %s\ngot error message: %s\n", errorMessage, err.Error()) 84 } 85 }) 86 } 87 } 88 89 func TestReplaceUnescaped(t *testing.T) { 90 defer leaktest.AfterTest(t)() 91 testCases := []struct { 92 pattern string 93 old string 94 new string 95 escapeToken string 96 expected string 97 }{ 98 {``, `B`, `DEF`, `\`, ``}, 99 {`ABC`, `B`, `DEF`, `\`, `ADEFC`}, 100 {`A\BC`, `B`, `DEF`, `\`, `A\BC`}, 101 {`A\\BC`, `B`, `DEF`, `\`, `A\\DEFC`}, 102 {`\\\\BC`, `B`, `DEF`, `\`, `\\\\DEFC`}, 103 {`\\\\\BC`, `B`, `DEF`, `\`, `\\\\\BC`}, 104 {`A\\BC`, `B`, `DEF`, `\\`, `A\\BC`}, 105 {`A\\\BC`, `B`, `DEF`, `\\`, `A\\\BC`}, 106 {`ACE`, `B`, `DEF`, `\`, `ACE`}, 107 {`B\\B\\\B`, `B`, `DEF`, `\`, `DEF\\DEF\\\B`}, 108 {`漢字\\漢\字\\\漢`, `漢`, `字`, `\`, `字字\\字\字\\\漢`}, 109 {`ABCABC`, `ABC`, `D`, `\`, `DD`}, 110 {`ABC\ABCABC`, `ABC`, `D`, `\`, `D\ABCD`}, 111 } 112 113 for _, tc := range testCases { 114 t.Run(fmt.Sprintf("%s-->%s Escape=%s", tc.pattern, tc.expected, tc.escapeToken), func(t *testing.T) { 115 actual := replaceUnescaped(tc.pattern, tc.old, tc.new, tc.escapeToken) 116 117 if tc.expected != actual { 118 t.Errorf("expected replaced pattern: %s, got %s\n", tc.expected, actual) 119 } 120 }) 121 } 122 } 123 124 // TestEvalContextCopy verifies that EvalContext.Copy() produces a deep copy of 125 // EvalContext. 126 func TestEvalContextCopy(t *testing.T) { 127 defer leaktest.AfterTest(t)() 128 // Note: the test relies on "parent" EvalContext having non-nil and non-empty 129 // iVarContainerStack. 130 ctx := EvalContext{iVarContainerStack: make([]IndexedVarContainer, 1)} 131 132 cpy := ctx.Copy() 133 if &ctx.iVarContainerStack[0] == &cpy.iVarContainerStack[0] { 134 t.Fatal("iVarContainerStacks are the same") 135 } 136 }