github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/stdlibs/regexp/onepass_test.gno (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package regexp
     6  
     7  import (
     8  	"regexp/syntax"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  var runeMergeTests = []struct {
    14  	left, right, merged []rune
    15  	next                []uint32
    16  	leftPC, rightPC     uint32
    17  }{
    18  	{
    19  		// empty rhs
    20  		[]rune{69, 69},
    21  		[]rune{},
    22  		[]rune{69, 69},
    23  		[]uint32{1},
    24  		1, 2,
    25  	},
    26  	{
    27  		// identical runes, identical targets
    28  		[]rune{69, 69},
    29  		[]rune{69, 69},
    30  		[]rune{},
    31  		[]uint32{mergeFailed},
    32  		1, 1,
    33  	},
    34  	{
    35  		// identical runes, different targets
    36  		[]rune{69, 69},
    37  		[]rune{69, 69},
    38  		[]rune{},
    39  		[]uint32{mergeFailed},
    40  		1, 2,
    41  	},
    42  	{
    43  		// append right-first
    44  		[]rune{69, 69},
    45  		[]rune{71, 71},
    46  		[]rune{69, 69, 71, 71},
    47  		[]uint32{1, 2},
    48  		1, 2,
    49  	},
    50  	{
    51  		// append, left-first
    52  		[]rune{71, 71},
    53  		[]rune{69, 69},
    54  		[]rune{69, 69, 71, 71},
    55  		[]uint32{2, 1},
    56  		1, 2,
    57  	},
    58  	{
    59  		// successful interleave
    60  		[]rune{60, 60, 71, 71, 101, 101},
    61  		[]rune{69, 69, 88, 88},
    62  		[]rune{60, 60, 69, 69, 71, 71, 88, 88, 101, 101},
    63  		[]uint32{1, 2, 1, 2, 1},
    64  		1, 2,
    65  	},
    66  	{
    67  		// left surrounds right
    68  		[]rune{69, 74},
    69  		[]rune{71, 71},
    70  		[]rune{},
    71  		[]uint32{mergeFailed},
    72  		1, 2,
    73  	},
    74  	{
    75  		// right surrounds left
    76  		[]rune{69, 74},
    77  		[]rune{68, 75},
    78  		[]rune{},
    79  		[]uint32{mergeFailed},
    80  		1, 2,
    81  	},
    82  	{
    83  		// overlap at interval begin
    84  		[]rune{69, 74},
    85  		[]rune{74, 75},
    86  		[]rune{},
    87  		[]uint32{mergeFailed},
    88  		1, 2,
    89  	},
    90  	{
    91  		// overlap ar interval end
    92  		[]rune{69, 74},
    93  		[]rune{65, 69},
    94  		[]rune{},
    95  		[]uint32{mergeFailed},
    96  		1, 2,
    97  	},
    98  	{
    99  		// overlap from above
   100  		[]rune{69, 74},
   101  		[]rune{71, 74},
   102  		[]rune{},
   103  		[]uint32{mergeFailed},
   104  		1, 2,
   105  	},
   106  	{
   107  		// overlap from below
   108  		[]rune{69, 74},
   109  		[]rune{65, 71},
   110  		[]rune{},
   111  		[]uint32{mergeFailed},
   112  		1, 2,
   113  	},
   114  	{
   115  		// out of order []rune
   116  		[]rune{69, 74, 60, 65},
   117  		[]rune{66, 67},
   118  		[]rune{},
   119  		[]uint32{mergeFailed},
   120  		1, 2,
   121  	},
   122  }
   123  
   124  func TestMergeRuneSet(t *testing.T) {
   125  	for ix, test := range runeMergeTests {
   126  		merged, next := mergeRuneSets(&test.left, &test.right, test.leftPC, test.rightPC)
   127  		// XXX reflect not supported
   128  		// if !reflect.DeepEqual(merged, test.merged) {
   129  		if string(merged) != string(test.merged) {
   130  			t.Errorf("mergeRuneSet :%d (%v, %v) merged\n have\n%v\nwant\n%v", ix, test.left, test.right, merged, test.merged)
   131  		}
   132  		/* XXX reflect not supported
   133  		if !reflect.DeepEqual(next, test.next) {
   134  			t.Errorf("mergeRuneSet :%d(%v, %v) next\n have\n%v\nwant\n%v", ix, test.left, test.right, next, test.next)
   135  		}
   136  		*/
   137  		if len(next) != len(test.next) {
   138  			t.Errorf("mergeRuneSet :%d(%v, %v) next\n have\n%v\nwant\n%v", ix, test.left, test.right, next, test.next)
   139  		}
   140  		for i, u32a := range next {
   141  			u32b := test.next[i]
   142  			if u32a != u32b {
   143  				t.Errorf("mergeRuneSet :%d(%v, %v) next\n have\n%v\nwant\n%v", ix, test.left, test.right, next, test.next)
   144  			}
   145  		}
   146  	}
   147  }
   148  
   149  var onePassTests = []struct {
   150  	re        string
   151  	isOnePass bool
   152  }{
   153  	{`^(?:a|(?:a*))$`, false},
   154  	{`^(?:(a)|(?:a*))$`, false},
   155  	{`^(?:(?:(?:.(?:$))?))$`, true},
   156  	{`^abcd$`, true},
   157  	{`^(?:(?:a{0,})*?)$`, false},
   158  	{`^(?:(?:a+)*)$`, true},
   159  	{`^(?:(?:a|(?:aa)))$`, true},
   160  	{`^(?:[^\s\S])$`, true},
   161  	{`^(?:(?:a{3,4}){0,})$`, false},
   162  	{`^(?:(?:(?:a*)+))$`, true},
   163  	{`^[a-c]+$`, true},
   164  	{`^[a-c]*$`, true},
   165  	{`^(?:a*)$`, true},
   166  	{`^(?:(?:aa)|a)$`, true},
   167  	{`^[a-c]*`, false},
   168  	{`^...$`, true},
   169  	{`^(?:a|(?:aa))$`, true},
   170  	{`^a((b))c$`, true},
   171  	{`^a.[l-nA-Cg-j]?e$`, true},
   172  	{`^a((b))$`, true},
   173  	{`^a(?:(b)|(c))c$`, true},
   174  	{`^a(?:(b*)|(c))c$`, false},
   175  	{`^a(?:b|c)$`, true},
   176  	{`^a(?:b?|c)$`, true},
   177  	{`^a(?:b?|c?)$`, false},
   178  	{`^a(?:b?|c+)$`, true},
   179  	{`^a(?:b+|(bc))d$`, false},
   180  	{`^a(?:bc)+$`, true},
   181  	{`^a(?:[bcd])+$`, true},
   182  	{`^a((?:[bcd])+)$`, true},
   183  	{`^a(:?b|c)*d$`, true},
   184  	{`^.bc(d|e)*$`, true},
   185  	{`^(?:(?:aa)|.)$`, false},
   186  	{`^(?:(?:a{1,2}){1,2})$`, false},
   187  	{`^l` + strings.Repeat("o", 2<<8) + `ng$`, true},
   188  }
   189  
   190  func TestCompileOnePass(t *testing.T) {
   191  	var (
   192  		p   *syntax.Prog
   193  		re  *syntax.Regexp
   194  		err error
   195  	)
   196  	for _, test := range onePassTests {
   197  		if re, err = syntax.Parse(test.re, syntax.Perl); err != nil {
   198  			t.Errorf("Parse(%q) got err:%s, want success", test.re, err)
   199  			continue
   200  		}
   201  		// needs to be done before compile...
   202  		re = re.Simplify()
   203  		if p, err = syntax.Compile(re); err != nil {
   204  			t.Errorf("Compile(%q) got err:%s, want success", test.re, err)
   205  			continue
   206  		}
   207  		isOnePass := compileOnePass(p) != nil
   208  		if isOnePass != test.isOnePass {
   209  			t.Errorf("CompileOnePass(%q) got isOnePass=%v, expected %v", test.re, isOnePass, test.isOnePass)
   210  		}
   211  	}
   212  }
   213  
   214  // TODO(cespare): Unify with onePassTests and rationalize one-pass test cases.
   215  var onePassTests1 = []struct {
   216  	re    string
   217  	match string
   218  }{
   219  	{`^a(/b+(#c+)*)*$`, "a/b#c"}, // golang.org/issue/11905
   220  }
   221  
   222  func TestRunOnePass(t *testing.T) {
   223  	for _, test := range onePassTests1 {
   224  		re, err := Compile(test.re)
   225  		if err != nil {
   226  			t.Errorf("Compile(%q): got err: %s", test.re, err)
   227  			continue
   228  		}
   229  		if re.onepass == nil {
   230  			t.Errorf("Compile(%q): got nil, want one-pass", test.re)
   231  			continue
   232  		}
   233  		if !re.MatchString(test.match) {
   234  			t.Errorf("onepass %q did not match %q", test.re, test.match)
   235  		}
   236  	}
   237  }