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 }