github.com/itchyny/rassemble-go@v0.1.1/rassemble_test.go (about)

     1  package rassemble
     2  
     3  import "testing"
     4  
     5  func TestJoin(t *testing.T) {
     6  	testCases := []struct {
     7  		name     string
     8  		patterns []string
     9  		expected string
    10  	}{
    11  		{
    12  			name:     "empty",
    13  			patterns: []string{},
    14  			expected: "",
    15  		},
    16  		{
    17  			name:     "empty literal",
    18  			patterns: []string{""},
    19  			expected: "(?:)",
    20  		},
    21  		{
    22  			name:     "empty literals",
    23  			patterns: []string{"", ""},
    24  			expected: "(?:)",
    25  		},
    26  		{
    27  			name:     "single literal",
    28  			patterns: []string{"abc"},
    29  			expected: "abc",
    30  		},
    31  		{
    32  			name:     "single literal with flag",
    33  			patterns: []string{"(?i:abc)"},
    34  			expected: "(?i:ABC)",
    35  		},
    36  		{
    37  			name:     "single literal with multiple flags",
    38  			patterns: []string{"(?ims:^a.b.c$)"},
    39  			expected: "(?ims:^A.B.C$)",
    40  		},
    41  		{
    42  			name:     "multiple literals",
    43  			patterns: []string{"abc", "def", "ghi"},
    44  			expected: "abc|def|ghi",
    45  		},
    46  		{
    47  			name:     "multiple literals with same flag",
    48  			patterns: []string{"(?i:abc)", "(?i:def)", "(?i:ghi)"},
    49  			expected: "(?i:ABC|DEF|GHI)",
    50  		},
    51  		{
    52  			name:     "multiple literals with different flags",
    53  			patterns: []string{"(?i:abc)", "(?m:d.$)", "(?s:^g.i)"},
    54  			expected: "(?-s:(?i:ABC)|(?m:d.$)|(?ms:^g.i))",
    55  		},
    56  		{
    57  			name:     "multiple characters with different flags",
    58  			patterns: []string{"a", "b", "(?i:c)?", "d"},
    59  			expected: "[Ca-d]?",
    60  		},
    61  		{
    62  			name:     "same literals",
    63  			patterns: []string{"abc", "def", "abc", "def"},
    64  			expected: "abc|def",
    65  		},
    66  		{
    67  			name:     "same prefixes with different length",
    68  			patterns: []string{"abc", "ab", "ad", "a"},
    69  			expected: "a(?:bc?|d)?",
    70  		},
    71  		{
    72  			name:     "same prefixes with different length",
    73  			patterns: []string{"abcd", "abcf", "abc", "abce", "abcgh", "abdc"},
    74  			expected: "ab(?:c(?:[d-f]|gh)?|dc)",
    75  		},
    76  		{
    77  			name:     "same prefixes with same length",
    78  			patterns: []string{"abcde", "abcfg", "abcgh"},
    79  			expected: "abc(?:de|fg|gh)",
    80  		},
    81  		{
    82  			name:     "same prefixes in increasing length order",
    83  			patterns: []string{"a", "ab", "abc", "abcd"},
    84  			expected: "a(?:b(?:cd?)?)?",
    85  		},
    86  		{
    87  			name:     "same prefixes in decreasing length order",
    88  			patterns: []string{"abcd", "abc", "ab", "a"},
    89  			expected: "a(?:b(?:cd?)?)?",
    90  		},
    91  		{
    92  			name:     "same prefixes with same flag",
    93  			patterns: []string{"(?i:abc)", "(?i:ab)", "(?i:ad)", "(?i:a)"},
    94  			expected: "(?i:A(?:BC?|D)?)",
    95  		},
    96  		{
    97  			name:     "same prefixes with various flags",
    98  			patterns: []string{"(?i:abc)", "(?:a.*b$)", "(?im:ad$|ae)", "(?sm:a.$)", "(?U:a.*c$)"},
    99  			expected: "(?-s:(?im:A(?:BC|D$|E))|(?m:a(?:.*b|(?s:.)|.*?c)$))",
   100  		},
   101  		{
   102  			name:     "same prefix and suffix",
   103  			patterns: []string{"abcdefg", "abcfg", "abefg", "befg", "beefg"},
   104  			expected: "(?:ab(?:c(?:de)?|e)|bee?)fg",
   105  		},
   106  		{
   107  			name:     "same prefix and suffix with double quests",
   108  			patterns: []string{"abcd", "abd", "acd", "ad"},
   109  			expected: "ab?c?d",
   110  		},
   111  		{
   112  			name:     "same prefix and suffix with triple quests",
   113  			patterns: []string{"abcde", "acde", "abde", "abce", "abe", "ace", "ade", "ae"},
   114  			expected: "ab?c?d?e",
   115  		},
   116  		{
   117  			name:     "multiple prefix groups",
   118  			patterns: []string{"abc", "ab", "abcd", "a", "bcd", "bcdef", "cdef", "cdeh"},
   119  			expected: "a(?:b(?:cd?)?)?|bcd(?:ef)?|cde[fh]",
   120  		},
   121  		{
   122  			name:     "merge literal to quest",
   123  			patterns: []string{"abc(?:def)?", "abc"},
   124  			expected: "abc(?:def)?",
   125  		},
   126  		{
   127  			name:     "merge literal to star",
   128  			patterns: []string{"abc(?:def)*", "abcdef", "abc"},
   129  			expected: "abc(?:def)*",
   130  		},
   131  		{
   132  			name:     "merge literal to plus",
   133  			patterns: []string{"abc(?:def)+", "abcdef", "abc"},
   134  			expected: "abc(?:def)*",
   135  		},
   136  		{
   137  			name:     "merge literal to alternate",
   138  			patterns: []string{"abc(?:de|f)", "abc"},
   139  			expected: "abc(?:de|f)?",
   140  		},
   141  		{
   142  			name:     "merge literal to alternate with plus",
   143  			patterns: []string{"abc(?:de|[f-h]+)", "abc", "abc"},
   144  			expected: "abc(?:de|[f-h]*)",
   145  		},
   146  		{
   147  			name:     "merge literal to concat",
   148  			patterns: []string{"abca*b*", "abc"},
   149  			expected: "abc(?:a*b*)?",
   150  		},
   151  		{
   152  			name:     "merge literal to concat",
   153  			patterns: []string{"abca*b*", "abcde"},
   154  			expected: "abc(?:a*b*|de)",
   155  		},
   156  		{
   157  			name:     "merge literal to alternate in quest",
   158  			patterns: []string{"abc(?:de|fh)?", "abcff", "abcf", "abchh"},
   159  			expected: "abc(?:de|f[fh]?|hh)?",
   160  		},
   161  		{
   162  			name:     "merge literal to quest with suffix",
   163  			patterns: []string{"abc(?:def)?ghi", "abcd"},
   164  			expected: "abc(?:(?:def)?ghi|d)",
   165  		},
   166  		{
   167  			name:     "merge literal to alternate with same prefix",
   168  			patterns: []string{"abcfd|def", "abcdef", "abcfe"},
   169  			expected: "abc(?:f[de]|def)|def",
   170  		},
   171  		{
   172  			name:     "merge literal to alternate with different prefix",
   173  			patterns: []string{"abc|def", "ghi"},
   174  			expected: "abc|def|ghi",
   175  		},
   176  		{
   177  			name:     "character class",
   178  			patterns: []string{"a", "1", "z", "2"},
   179  			expected: "[12az]",
   180  		},
   181  		{
   182  			name:     "character class with prefix",
   183  			patterns: []string{"aa", "ab"},
   184  			expected: "a[ab]",
   185  		},
   186  		{
   187  			name:     "character class in prefix",
   188  			patterns: []string{"abcde", "abc", "bbcde", "bbc", "cbcde", "cbc"},
   189  			expected: "[a-c]bc(?:de)?",
   190  		},
   191  		{
   192  			name:     "add character class to a character",
   193  			patterns: []string{"d?", "[a-c]", "e"},
   194  			expected: "[a-e]?",
   195  		},
   196  		{
   197  			name:     "add character class to a character class",
   198  			patterns: []string{"[a-c]", "[e-f]", "d"},
   199  			expected: "[a-f]",
   200  		},
   201  		{
   202  			name:     "add complex character class to a complex character class",
   203  			patterns: []string{"[i-kea-c]", "[f-hd]"},
   204  			expected: "[a-k]",
   205  		},
   206  		{
   207  			name:     "add character to character class negation",
   208  			patterns: []string{"[^0-9]", "3", "5"},
   209  			expected: "[^0-246-9]",
   210  		},
   211  		{
   212  			name:     "add quest of character to character class negation",
   213  			patterns: []string{"[^0-9]", "3?", "5"},
   214  			expected: "[^0-246-9]?",
   215  		},
   216  		{
   217  			name:     "add character to character class negation to match anything",
   218  			patterns: []string{"[^0]", "0"},
   219  			expected: "(?s:.)",
   220  		},
   221  		{
   222  			name:     "merge literal prefix rather than character class",
   223  			patterns: []string{"a", "c", "e", "ab", "cd", "ef"},
   224  			expected: "ab?|cd?|ef?",
   225  		},
   226  		{
   227  			name:     "add character class to a character class negation",
   228  			patterns: []string{"[a-d]", "[^c-g]", "f"},
   229  			expected: "[^eg]",
   230  		},
   231  		{
   232  			name:     "successive character class",
   233  			patterns: []string{"aa", "ab", "ac"},
   234  			expected: "a[a-c]",
   235  		},
   236  		{
   237  			name:     "successive character class in random order",
   238  			patterns: []string{"ac", "aa", "ae", "ab", "ad"},
   239  			expected: "a[a-e]",
   240  		},
   241  		{
   242  			name:     "add case insensitive literal to a literal",
   243  			patterns: []string{"a", "(?i:b)", "c"},
   244  			expected: "[Ba-c]",
   245  		},
   246  		{
   247  			name:     "add case insensitive literal to a character class",
   248  			patterns: []string{"(?i:a)", "[b-e]", "(?i:f)"},
   249  			expected: "[AFa-f]",
   250  		},
   251  		{
   252  			name:     "add case insensitive character class to a character class",
   253  			patterns: []string{"[a-c]", "(?i:[d-f])", "[g-i]"},
   254  			expected: "[D-Fa-i]",
   255  		},
   256  		{
   257  			name:     "add case insensitive literal to a quest of character class",
   258  			patterns: []string{"(?i:a)", "[b-e]?", "(?i:f)"},
   259  			expected: "[AFa-f]?",
   260  		},
   261  		{
   262  			name:     "numbers",
   263  			patterns: []string{"1", "9", "2", "6", "3"},
   264  			expected: "[1-369]",
   265  		},
   266  		{
   267  			name:     "numbers 0 to 5",
   268  			patterns: []string{"0", "4", "3", "5", "1", "2"},
   269  			expected: "[0-5]",
   270  		},
   271  		{
   272  			name:     "numbers 0 to 10",
   273  			patterns: []string{"1", "9", "2", "6", "3", "7", "10", "8", "0", "5", "4"},
   274  			expected: "10?|[02-9]",
   275  		},
   276  		{
   277  			name:     "numbers with prefix",
   278  			patterns: []string{"a2", "a1", "a0", "a8", "a3", "a5", "a6", "a4", "a7", "a11", "a2", "a9", "a0", "a10"},
   279  			expected: "a(?:[02-9]|1[01]?)",
   280  		},
   281  		{
   282  			name:     "add empty literal to quest",
   283  			patterns: []string{"abc", "", ""},
   284  			expected: "(?:abc)?",
   285  		},
   286  		{
   287  			name:     "add empty literal to plus and star",
   288  			patterns: []string{"(?:abc)+", "", ""},
   289  			expected: "(?:abc)*",
   290  		},
   291  		{
   292  			name:     "add empty literal to character class",
   293  			patterns: []string{"[135]", "", "7"},
   294  			expected: "[1357]?",
   295  		},
   296  		{
   297  			name:     "add empty literal to alternate with quest",
   298  			patterns: []string{"abc", "b", "", ""},
   299  			expected: "abc|b?",
   300  		},
   301  		{
   302  			name:     "add empty literal to alternate with plus and star",
   303  			patterns: []string{"abc", "b+", "", ""},
   304  			expected: "abc|b*",
   305  		},
   306  		{
   307  			name:     "add literal to empty literal",
   308  			patterns: []string{"", "abc", ""},
   309  			expected: "(?:abc)?",
   310  		},
   311  		{
   312  			name:     "add literal with a flag to empty literal",
   313  			patterns: []string{"", "(?i:abc)", ""},
   314  			expected: "(?i:(?:ABC)?)",
   315  		},
   316  		{
   317  			name:     "add quest to empty literal",
   318  			patterns: []string{"", "(?:abc)?"},
   319  			expected: "(?:abc)?",
   320  		},
   321  		{
   322  			name:     "add quest to quest",
   323  			patterns: []string{"(?:abc)?", "(?:abc)?"},
   324  			expected: "(?:abc)?",
   325  		},
   326  		{
   327  			name:     "add star to empty literal",
   328  			patterns: []string{"", "(?:abc)*"},
   329  			expected: "(?:abc)*",
   330  		},
   331  		{
   332  			name:     "add star and plus to character class",
   333  			patterns: []string{"a[a-c]c", "a[a-c]*c", "a[a-c]+c", "a[a-d]+c"},
   334  			expected: "a(?:[a-c]*|[a-d]+)c",
   335  		},
   336  		{
   337  			name:     "add quest and plus to character class",
   338  			patterns: []string{"a[a-c]c", "aac", "a[a-c]?c", "a[a-c]+c", "a[a-d]c"},
   339  			expected: "a(?:[a-c]*|[a-d])c",
   340  		},
   341  		{
   342  			name:     "add quest of character class to literal",
   343  			patterns: []string{"abc", "a[a-c]?c"},
   344  			expected: "a[a-c]?c",
   345  		},
   346  		{
   347  			name:     "add quest of character class to character class",
   348  			patterns: []string{"abc", "adc", "a[a-c]?c"},
   349  			expected: "a[a-d]?c",
   350  		},
   351  		{
   352  			name:     "add plus to empty literal",
   353  			patterns: []string{"", "(?:abc)+"},
   354  			expected: "(?:abc)*",
   355  		},
   356  		{
   357  			name:     "add plus to literal",
   358  			patterns: []string{"abc", "(?:ab)+", "(?:abc)+"},
   359  			expected: "(?:abc)+|(?:ab)+",
   360  		},
   361  		{
   362  			name:     "add plus to quest",
   363  			patterns: []string{"(?:abc)?", "(?:ab)+", "(?:abc)+"},
   364  			expected: "(?:abc)*|(?:ab)+",
   365  		},
   366  		{
   367  			name:     "add character class to empty literal",
   368  			patterns: []string{"", "[a-c]"},
   369  			expected: "[a-c]?",
   370  		},
   371  		{
   372  			name:     "add alternate",
   373  			patterns: []string{"a", "[a-c]|bb", "cc|d"},
   374  			expected: "[a-d]|bb|cc",
   375  		},
   376  		{
   377  			name:     "merge suffix",
   378  			patterns: []string{"abcde", "cde", "bde"},
   379  			expected: "(?:(?:ab)?c|b)de",
   380  		},
   381  		{
   382  			name:     "merge suffix in increasing length order",
   383  			patterns: []string{"e", "de", "cde", "bcde", "abcde"},
   384  			expected: "(?:(?:(?:a?b)?c)?d)?e",
   385  		},
   386  		{
   387  			name:     "merge suffix in decreasing length order",
   388  			patterns: []string{"abcde", "bcde", "cde", "de", "e"},
   389  			expected: "(?:(?:(?:a?b)?c)?d)?e",
   390  		},
   391  		{
   392  			name:     "regexps matching head",
   393  			patterns: []string{"a?", "a?b*c+"},
   394  			expected: "a?(?:b*c+)?",
   395  		},
   396  		{
   397  			name:     "regexps with same prefix",
   398  			patterns: []string{"a?b+cd", "a?b+c*", "a?b*c+"},
   399  			expected: "a?(?:b+(?:cd|c*)|b*c+)",
   400  		},
   401  		{
   402  			name:     "regexps with same prefixes",
   403  			patterns: []string{"a?b+c*", "a?b+c*d*", "a?b+", "a?"},
   404  			expected: "a?(?:b+(?:c*d*)?)?",
   405  		},
   406  		{
   407  			name:     "regexps with same prefixes and flags",
   408  			patterns: []string{"(?i:a*b+c*)", "(?i:a*b+(?-i:c*d*))", "(?i:a*)(?i:b+)", "a*", "A*"},
   409  			expected: "A*(?:(?i:B+)(?:(?i:C*)|c*d*))?|a*", // bug in regexp/syntax (golang/go#59007)
   410  		},
   411  		{
   412  			name:     "regexps with same prefixes and different flags",
   413  			patterns: []string{"a?(?i:b+c*)", "(?i:a?)(?i:b+c*d*)", "(?i:a?)b+", "a?"},
   414  			expected: "a?(?i:(?:B+C*)?)|(?i:A?)(?:(?i:B+C*D*)|b+)",
   415  		},
   416  		{
   417  			name:     "regexps with same literal prefix",
   418  			patterns: []string{"abcd*e*", "abcde*f*", "abefg?", "ab"},
   419  			expected: "ab(?:c(?:d*e*|de*f*)|efg?)?",
   420  		},
   421  		{
   422  			name:     "regexps with same suffix",
   423  			patterns: []string{"ab*c", "c+", "bab?c", "a+c", "cbc+", "dbc+", "ab*c", "c*d+", "d+"},
   424  			expected: "(?:ab*|bab?|a+)c|(?:[cd]b)?c+|c*d+",
   425  		},
   426  		{
   427  			name:     "regexps with same literal suffix",
   428  			patterns: []string{"ab*cde", "bcde", "a*de", "cde"},
   429  			expected: "(?:(?:ab*|b)?c|a*)de",
   430  		},
   431  	}
   432  	for _, tc := range testCases {
   433  		t.Run(tc.name, func(t *testing.T) {
   434  			got, err := Join(tc.patterns)
   435  			if err != nil {
   436  				t.Fatalf("got an error: %s", err)
   437  			}
   438  			if got != tc.expected {
   439  				t.Errorf("expected: %s, got: %s", tc.expected, got)
   440  			}
   441  		})
   442  	}
   443  	if _, err := Join([]string{"*"}); err == nil {
   444  		t.Fatalf("expected an error")
   445  	}
   446  }