ladybird/Tests/LibRegex/RegexLibC.cpp
Linus Groh 57dc179b1f Everywhere: Rename to_{string => deprecated_string}() where applicable
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.

One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
2022-12-06 08:54:33 +01:00

1159 lines
46 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2020, Emanuel Sprung <emanuel.sprung@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <AK/StringBuilder.h>
#include <AK/Vector.h>
#include <LibC/regex.h>
#include <stdio.h>
TEST_CASE(catch_all)
{
DeprecatedString pattern = "^.*$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hello World", 0, NULL, 0), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_start)
{
DeprecatedString pattern = "^hello friends";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hello!", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Well, hello friends", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_end)
{
DeprecatedString pattern = ".*hello\\.\\.\\. there$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hallo", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "I said fyhello... there", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "ahello... therea", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello.. there", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_period)
{
DeprecatedString pattern = "hello.";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hello1", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello1", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello2", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello?", 0, NULL, 0), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_period_end)
{
DeprecatedString pattern = "hello.$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hello1", 0, NULL, REG_NOSUB), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello1hello1", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello2hell", 0, NULL, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello?", 0, NULL, REG_NOSUB), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_escaped)
{
DeprecatedString pattern = "hello\\.";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello.", 0, NULL, 0), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_period2_end)
{
DeprecatedString pattern = ".*hi... there$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hello there", 0, NULL, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "I said fyhi... there", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "....hi... ", 0, NULL, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "I said fyhihii there", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "I said fyhihi there", 0, NULL, REG_GLOBAL), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_plus)
{
DeprecatedString pattern = "a+";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB), REG_NOERR);
EXPECT_EQ(regexec(&regex, "b", 0, NULL, REG_NOSUB), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "a", 0, NULL, REG_NOSUB), REG_NOERR);
EXPECT_EQ(regexec(&regex, "aaaaaabbbbb", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "aaaaaaaaaaa", 0, NULL, REG_GLOBAL), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_questionmark)
{
DeprecatedString pattern = "da?d";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a", 0, NULL, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "daa", 0, NULL, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "ddddd", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "dd", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "dad", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "dada", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "adadaa", 0, NULL, REG_GLOBAL), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_questionmark_matchall)
{
DeprecatedString pattern = "da?d";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a", num_matches, matches, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
EXPECT_EQ(regexec(&regex, "daa", num_matches, matches, REG_GLOBAL), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
EXPECT_EQ(regexec(&regex, "ddddd", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 2);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 2);
EXPECT_EQ(matches[1].rm_so, 2);
EXPECT_EQ(matches[1].rm_eo, 4);
EXPECT_EQ(regexec(&regex, "dd", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(regexec(&regex, "dad", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(regexec(&regex, "dada", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(regexec(&regex, "adadaa", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
regfree(&regex);
}
TEST_CASE(character_class)
{
DeprecatedString pattern = "[[:alpha:]]";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
DeprecatedString haystack = "[Window]\nOpacity=255\nAudibleBeep=0\n";
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, haystack.characters(), num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
EXPECT_EQ(regexec(&regex, haystack.characters(), num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 24);
EXPECT_EQ(haystack.substring_view(matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so), "W");
EXPECT_EQ(haystack.substring_view(matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so), "i");
regfree(&regex);
}
TEST_CASE(character_class2)
{
DeprecatedString pattern = "[[:alpha:]]*=([[:digit:]]*)|\\[(.*)\\]";
regex_t regex;
static constexpr int num_matches { 9 };
regmatch_t matches[num_matches];
DeprecatedString haystack = "[Window]\nOpacity=255\nAudibleBeep=0\n";
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NEWLINE), REG_NOERR);
EXPECT_EQ(regexec(&regex, haystack.characters(), num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 3);
#if 0
for (int i = 0; i < num_matches; ++i) {
fprintf(stderr, "Matches[%i].rm_so: %li, .rm_eo: %li .rm_cnt: %li: ", i, matches[i].rm_so, matches[i].rm_eo, matches[i].rm_cnt);
fprintf(stderr, "haystack length: %lu\n", haystack.length());
if (matches[i].rm_so != -1)
fprintf(stderr, "%s\n", haystack.substring_view(matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so).to_deprecated_string().characters());
}
#endif
EXPECT_EQ(haystack.substring_view(matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so), "[Window]");
EXPECT_EQ(matches[1].rm_so, -1);
EXPECT_EQ(matches[1].rm_eo, -1);
EXPECT_EQ(matches[1].rm_cnt, 0);
EXPECT_EQ(haystack.substring_view(matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so), "Window");
EXPECT_EQ(haystack.substring_view(matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so), "Opacity=255");
EXPECT_EQ(haystack.substring_view(matches[4].rm_so, matches[4].rm_eo - matches[4].rm_so), "255");
EXPECT_EQ(matches[5].rm_so, -1);
EXPECT_EQ(matches[5].rm_eo, -1);
EXPECT_EQ(matches[5].rm_cnt, 0);
EXPECT_EQ(haystack.substring_view(matches[6].rm_so, matches[6].rm_eo - matches[6].rm_so), "AudibleBeep=0");
EXPECT_EQ(haystack.substring_view(matches[7].rm_so, matches[7].rm_eo - matches[7].rm_so), "0");
EXPECT_EQ(matches[8].rm_so, -1);
EXPECT_EQ(matches[8].rm_eo, -1);
EXPECT_EQ(matches[8].rm_cnt, 0);
regfree(&regex);
}
TEST_CASE(escaped_char_questionmark)
{
DeprecatedString pattern = "This\\.?And\\.?That";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "ThisAndThat", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "This.And.That", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "This And That", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "This..And..That", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(char_qualifier_asterisk)
{
DeprecatedString pattern = "regex*";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "#include <regex.h>", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
regfree(&regex);
}
TEST_CASE(char_utf8)
{
DeprecatedString pattern = "😀";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Привет, мир! 😀 γειά σου κόσμος 😀 こんにちは世界", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 2);
regfree(&regex);
}
TEST_CASE(parens)
{
DeprecatedString pattern = "test(hello)test";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "testhellotest", num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 13);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 9);
regfree(&regex);
}
TEST_CASE(parser_error_parens)
{
DeprecatedString pattern = "test()test";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
EXPECT_EQ(regexec(&regex, "testhellotest", num_matches, matches, 0), REG_EMPTY_EXPR);
regfree(&regex);
}
TEST_CASE(parser_error_special_characters_used_at_wrong_place)
{
DeprecatedString pattern;
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
Vector<char, 4> chars = { '*', '+', '?', '}' };
StringBuilder b;
for (auto& ch : chars) {
auto error_code_to_check = ch == '}' ? REG_EBRACE : REG_BADRPT;
// First in ere
b.clear();
b.append(ch);
pattern = b.build();
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
regfree(&regex);
// After vertical line
b.clear();
b.append("a|"sv);
b.append(ch);
pattern = b.build();
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
regfree(&regex);
// After circumflex
b.clear();
b.append('^');
b.append(ch);
pattern = b.build();
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
regfree(&regex);
// After dollar
b.clear();
b.append('$');
b.append(ch);
pattern = b.build();
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
regfree(&regex);
// After left parens
b.clear();
b.append('(');
b.append(ch);
b.append(')');
pattern = b.build();
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
regfree(&regex);
}
}
TEST_CASE(parser_error_vertical_line_used_at_wrong_place)
{
DeprecatedString pattern;
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
// First in ere
pattern = "|asdf";
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
regfree(&regex);
// Last in ere
pattern = "asdf|";
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
regfree(&regex);
// After left parens
pattern = "(|asdf)";
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
regfree(&regex);
// Proceed right parens
pattern = "(asdf)|";
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
regfree(&regex);
}
TEST_CASE(parens_qualifier_questionmark)
{
DeprecatedString pattern = "test(hello)?test";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "testtest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 8);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
match_str = "testhellotest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 13);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 9);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellotest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
regfree(&regex);
}
TEST_CASE(parens_qualifier_asterisk)
{
DeprecatedString pattern = "test(hello)*test";
regex_t regex;
static constexpr int num_matches { 6 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "testtest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 8);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
match_str = "testhellohellotest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 18);
EXPECT_EQ(matches[1].rm_so, 9);
EXPECT_EQ(matches[1].rm_eo, 14);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellohellotest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "testhellohellotest, testhellotest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 2);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 18);
EXPECT_EQ(matches[1].rm_so, 9);
EXPECT_EQ(matches[1].rm_eo, 14);
EXPECT_EQ(matches[2].rm_so, 20);
EXPECT_EQ(matches[2].rm_eo, 33);
EXPECT_EQ(matches[3].rm_so, 24);
EXPECT_EQ(matches[3].rm_eo, 29);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellohellotest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "testhellotest");
EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "hello");
regfree(&regex);
}
TEST_CASE(parens_qualifier_asterisk_2)
{
DeprecatedString pattern = "test(.*)test";
regex_t regex;
static constexpr int num_matches { 6 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "testasdftest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 12);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 8);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testasdftest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "asdf");
match_str = "testasdfasdftest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 16);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 12);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testasdfasdftest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "asdfasdf");
match_str = "testaaaatest, testbbbtest, testtest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 35);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 31);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testaaaatest, testbbbtest, testtest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "aaaatest, testbbbtest, test");
regfree(&regex);
}
TEST_CASE(mulit_parens_qualifier_too_less_result_values)
{
DeprecatedString pattern = "test(a)?(b)?(c)?test";
regex_t regex;
static constexpr int num_matches { 4 };
regmatch_t matches[num_matches];
char const* match_str;
matches[3] = { -2, -2, 100 };
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "testabtest";
EXPECT_EQ(regexec(&regex, match_str, num_matches - 1, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 10);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 5);
EXPECT_EQ(matches[2].rm_so, 5);
EXPECT_EQ(matches[2].rm_eo, 6);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabtest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
EXPECT_EQ(matches[3].rm_so, -2);
EXPECT_EQ(matches[3].rm_eo, -2);
EXPECT_EQ(matches[3].rm_cnt, 100);
match_str = "testabctest";
EXPECT_EQ(regexec(&regex, match_str, num_matches - 1, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 11);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 5);
EXPECT_EQ(matches[2].rm_so, 5);
EXPECT_EQ(matches[2].rm_eo, 6);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
EXPECT_EQ(matches[3].rm_so, -2);
EXPECT_EQ(matches[3].rm_eo, -2);
EXPECT_EQ(matches[3].rm_cnt, 100);
match_str = "testabctest, testabctest";
EXPECT_EQ(regexec(&regex, match_str, num_matches - 1, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 2);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 11);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 5);
EXPECT_EQ(matches[2].rm_so, 5);
EXPECT_EQ(matches[2].rm_eo, 6);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
EXPECT_EQ(matches[3].rm_so, -2);
EXPECT_EQ(matches[3].rm_eo, -2);
EXPECT_EQ(matches[3].rm_cnt, 100);
regfree(&regex);
}
TEST_CASE(multi_parens_qualifier_questionmark)
{
DeprecatedString pattern = "test(a)?(b)?(c)?test";
regex_t regex;
static constexpr int num_matches { 8 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "testtest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 8);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
match_str = "testabctest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 11);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 5);
EXPECT_EQ(matches[2].rm_so, 5);
EXPECT_EQ(matches[2].rm_eo, 6);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
match_str = "testabctest, testactest";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 2);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 11);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 5);
EXPECT_EQ(matches[2].rm_so, 5);
EXPECT_EQ(matches[2].rm_eo, 6);
EXPECT_EQ(matches[3].rm_so, 6);
EXPECT_EQ(matches[3].rm_eo, 7);
EXPECT_EQ(matches[4].rm_so, 13);
EXPECT_EQ(matches[4].rm_eo, 23);
EXPECT_EQ(matches[5].rm_so, 17);
EXPECT_EQ(matches[5].rm_eo, 18);
EXPECT_EQ(matches[6].rm_so, -1);
EXPECT_EQ(matches[6].rm_eo, -1);
EXPECT_EQ(matches[7].rm_so, 18);
EXPECT_EQ(matches[7].rm_eo, 19);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "c");
EXPECT_EQ(StringView(&match_str[matches[4].rm_so], matches[4].rm_eo - matches[4].rm_so), "testactest");
EXPECT_EQ(StringView(&match_str[matches[5].rm_so], matches[5].rm_eo - matches[5].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[6].rm_so], matches[6].rm_eo - matches[6].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[7].rm_so], matches[7].rm_eo - matches[7].rm_so), "c");
regfree(&regex);
}
TEST_CASE(simple_alternative)
{
DeprecatedString pattern = "test|hello|friends";
regex_t regex;
static constexpr int num_matches { 1 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 4);
EXPECT_EQ(regexec(&regex, "hello", num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 5);
EXPECT_EQ(regexec(&regex, "friends", num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 7);
regfree(&regex);
}
TEST_CASE(alternative_match_groups)
{
DeprecatedString pattern = "test(a)?(b)?|hello ?(dear|my)? friends";
regex_t regex;
static constexpr int num_matches { 8 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "test";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 4);
EXPECT_EQ(matches[1].rm_so, -1);
EXPECT_EQ(matches[1].rm_eo, -1);
EXPECT_EQ(matches[2].rm_so, -1);
EXPECT_EQ(matches[2].rm_eo, -1);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "test");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
match_str = "testa";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 5);
EXPECT_EQ(matches[1].rm_so, 4);
EXPECT_EQ(matches[1].rm_eo, 5);
EXPECT_EQ(matches[2].rm_so, -1);
EXPECT_EQ(matches[2].rm_eo, -1);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testa");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
match_str = "testb";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 5);
EXPECT_EQ(matches[1].rm_so, -1);
EXPECT_EQ(matches[1].rm_eo, -1);
EXPECT_EQ(matches[2].rm_so, 4);
EXPECT_EQ(matches[2].rm_eo, 5);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testb");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
match_str = "hello friends";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 13);
EXPECT_EQ(matches[1].rm_so, -1);
EXPECT_EQ(matches[1].rm_eo, -1);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello friends");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
match_str = "hello dear friends";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 18);
EXPECT_EQ(matches[1].rm_so, -1);
EXPECT_EQ(matches[1].rm_eo, -1);
EXPECT_EQ(matches[2].rm_so, -1);
EXPECT_EQ(matches[2].rm_eo, -1);
EXPECT_EQ(matches[3].rm_so, 6);
EXPECT_EQ(matches[3].rm_eo, 10);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello dear friends");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "dear");
match_str = "hello my friends";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 16);
EXPECT_EQ(matches[1].rm_so, -1);
EXPECT_EQ(matches[1].rm_eo, -1);
EXPECT_EQ(matches[2].rm_so, -1);
EXPECT_EQ(matches[2].rm_eo, -1);
EXPECT_EQ(matches[3].rm_so, 6);
EXPECT_EQ(matches[3].rm_eo, 8);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello my friends");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "my");
match_str = "testabc";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
EXPECT_EQ(matches[0].rm_so, -1);
EXPECT_EQ(matches[0].rm_eo, -1);
match_str = "hello test friends";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
EXPECT_EQ(matches[0].rm_so, -1);
EXPECT_EQ(matches[0].rm_eo, -1);
regfree(&regex);
}
TEST_CASE(parens_qualifier_exact)
{
DeprecatedString pattern = "(hello){3}";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "hello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
match_str = "hellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 15);
EXPECT_EQ(matches[1].rm_so, 10);
EXPECT_EQ(matches[1].rm_eo, 15);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "hellohellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 15);
EXPECT_EQ(matches[1].rm_so, 10);
EXPECT_EQ(matches[1].rm_eo, 15);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "test hellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 5);
EXPECT_EQ(matches[0].rm_eo, 20);
EXPECT_EQ(matches[1].rm_so, 15);
EXPECT_EQ(matches[1].rm_eo, 20);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
regfree(&regex);
}
TEST_CASE(parens_qualifier_minimum)
{
DeprecatedString pattern = "(hello){3,}";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "hello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
match_str = "hellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 15);
EXPECT_EQ(matches[1].rm_so, 10);
EXPECT_EQ(matches[1].rm_eo, 15);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "hellohellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_SEARCH), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 20);
EXPECT_EQ(matches[1].rm_so, 15);
EXPECT_EQ(matches[1].rm_eo, 20);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "test hellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 5);
EXPECT_EQ(matches[0].rm_eo, 20);
EXPECT_EQ(matches[1].rm_so, 15);
EXPECT_EQ(matches[1].rm_eo, 20);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "test hellohellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 5);
EXPECT_EQ(matches[0].rm_eo, 25);
EXPECT_EQ(matches[1].rm_so, 20);
EXPECT_EQ(matches[1].rm_eo, 25);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
regfree(&regex);
}
TEST_CASE(parens_qualifier_maximum)
{
DeprecatedString pattern = "(hello){2,3}";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
char const* match_str;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
match_str = "hello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(matches[0].rm_cnt, 0);
match_str = "hellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 15);
EXPECT_EQ(matches[1].rm_so, 10);
EXPECT_EQ(matches[1].rm_eo, 15);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "hellohellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 0);
EXPECT_EQ(matches[0].rm_eo, 15);
EXPECT_EQ(matches[1].rm_so, 10);
EXPECT_EQ(matches[1].rm_eo, 15);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "test hellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 5);
EXPECT_EQ(matches[0].rm_eo, 20);
EXPECT_EQ(matches[1].rm_so, 15);
EXPECT_EQ(matches[1].rm_eo, 20);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
match_str = "test hellohellohellohello";
EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(matches[0].rm_so, 5);
EXPECT_EQ(matches[0].rm_eo, 20);
EXPECT_EQ(matches[1].rm_so, 15);
EXPECT_EQ(matches[1].rm_eo, 20);
EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
regfree(&regex);
}
TEST_CASE(char_qualifier_min_max)
{
DeprecatedString pattern = "c{3,30}";
regex_t regex;
static constexpr int num_matches { 5 };
regmatch_t matches[num_matches];
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "cc", num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "ccc", num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "cccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOERR);
EXPECT_EQ(matches[0].rm_cnt, 1);
EXPECT_EQ(regexec(&regex, "ccccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "ccccccccccccccccccccccccccccccc", num_matches, matches, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "cccccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_bracket_chars)
{
DeprecatedString pattern = "[abc]";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_bracket_chars_inverse)
{
DeprecatedString pattern = "[^abc]";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOERR);
regfree(&regex);
}
TEST_CASE(simple_bracket_chars_range)
{
DeprecatedString pattern = "[a-d]";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_bracket_chars_range_inverse)
{
DeprecatedString pattern = "[^a-df-z]";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "k", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "z", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(bracket_character_class_uuid)
{
DeprecatedString pattern = "^([[:xdigit:]]{8})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{12})$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "fb9b62a2-1579-4e3a-afba-76239ccb6583", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "fb9b62a2", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_bracket_character_class_inverse)
{
DeprecatedString pattern = "[^[:digit:]]";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "1", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "2", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "3", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOERR);
regfree(&regex);
}
TEST_CASE(email_address)
{
DeprecatedString pattern = "^[A-Z0-9a-z._%+-]{1,64}@(?:[A-Za-z0-9-]{1,63}\\.){1,125}[A-Za-z]{2,63}$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
EXPECT_EQ(regexec(&regex, "emanuel.sprung@gmail.com", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "kling@serenityos.org", 0, NULL, 0), REG_NOERR);
regfree(&regex);
}
TEST_CASE(error_message)
{
DeprecatedString pattern = "^[A-Z0-9[a-z._%+-]{1,64}@[A-Za-z0-9-]{1,63}\\.{1,125}[A-Za-z]{2,63}$";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EBRACK);
EXPECT_EQ(regexec(&regex, "asdf@asdf.com", 0, NULL, 0), REG_EBRACK);
char buf[1024];
size_t buflen = 1024;
auto len = regerror(0, &regex, buf, buflen);
DeprecatedString expected = "Error during parsing of regular expression:\n ^[A-Z0-9[a-z._%+-]{1,64}@[A-Za-z0-9-]{1,63}\\.{1,125}[A-Za-z]{2,63}$\n ^---- [ ] imbalance.";
for (size_t i = 0; i < len; ++i) {
EXPECT_EQ(buf[i], expected[i]);
}
regfree(&regex);
}
TEST_CASE(simple_ignorecase)
{
DeprecatedString pattern = "^hello friends";
regex_t regex;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "Hello Friends", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello Friends", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello Friends!", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello Friends!", 0, NULL, REG_GLOBAL), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hell Friends", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hell Friends", 0, NULL, REG_GLOBAL), REG_NOMATCH);
regfree(&regex);
}
TEST_CASE(simple_notbol_noteol)
{
DeprecatedString pattern = "^hello friends$";
DeprecatedString pattern2 = "hello friends";
regex_t regex, regex2;
EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regcomp(&regex2, pattern2.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "a hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "a hello friends", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOERR);
EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
EXPECT_EQ(regexec(&regex2, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
EXPECT_EQ(regexec(&regex2, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
regfree(&regex);
regfree(&regex2);
}
TEST_CASE(bre_basic)
{
regex_t regex;
EXPECT_EQ(regcomp(&regex, "hello friends", REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, 0), REG_NOERR);
regfree(&regex);
EXPECT_EQ(regcomp(&regex, "\\(15\\)\\1", REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "1515", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "55", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
EXPECT_EQ(regcomp(&regex, "15\\{1,2\\}", REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "15", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "1515", 0, NULL, 0), REG_NOMATCH);
EXPECT_EQ(regexec(&regex, "55", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
EXPECT_EQ(regcomp(&regex, "15{1,2}", REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "15{1,2}", 0, NULL, 0), REG_NOERR);
regfree(&regex);
EXPECT_EQ(regcomp(&regex, "1[56]", REG_NOSUB | REG_ICASE), REG_NOERR);
EXPECT_EQ(regexec(&regex, "15", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "16", 0, NULL, 0), REG_NOERR);
EXPECT_EQ(regexec(&regex, "17", 0, NULL, 0), REG_NOMATCH);
regfree(&regex);
}