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  }