diff options
Diffstat (limited to 'subprojects/rerex/test')
-rw-r--r-- | subprojects/rerex/test/test_match.c | 238 | ||||
-rw-r--r-- | subprojects/rerex/test/test_syntax.c | 99 | ||||
-rw-r--r-- | subprojects/rerex/test/test_xsd.c | 522 |
3 files changed, 859 insertions, 0 deletions
diff --git a/subprojects/rerex/test/test_match.c b/subprojects/rerex/test/test_match.c new file mode 100644 index 00000000..fa270e83 --- /dev/null +++ b/subprojects/rerex/test/test_match.c @@ -0,0 +1,238 @@ +/* + Copyright 2020 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "rerex/rerex.h" + +#include <assert.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +typedef struct { + uintptr_t match; ///< Boolean, true if text should match + const char* pattern; ///< Regular expression + const char* text; ///< Text to match against pattern +} MatchTestCase; + +static const MatchTestCase match_tests[] = { + {1, "\\(", "("}, + {1, "\\)", ")"}, + {1, "\\*", "*"}, + {1, "\\+", "+"}, + {1, "\\-", "-"}, + {1, "\\.", "."}, + {1, "\\?", "?"}, + {1, "\\[", "["}, + {1, "\\]", "]"}, + {1, "\\^", "^"}, + {1, "\\|", "|"}, + {0, ".", ""}, + {1, ".", "a"}, + {0, ".", "aa"}, + {0, "..", ""}, + {0, "..", "a"}, + {1, "..", "aa"}, + {1, ".*", ""}, + {1, ".*", "a"}, + {1, ".*", "aa"}, + {0, ".+", ""}, + {1, ".+", "a"}, + {1, ".+", "aa"}, + {1, ".?", ""}, + {1, ".?", "a"}, + {0, ".?", "aa"}, + {1, "a*", ""}, + {1, "a*", "a"}, + {1, "a*", "aa"}, + {0, "a*", "b"}, + {0, "a+", ""}, + {1, "a+", "a"}, + {1, "a+", "aa"}, + {0, "a+", "b"}, + {1, "a?", ""}, + {1, "a?", "a"}, + {0, "a?", "aa"}, + {0, "a?", "b"}, + {0, "[.]", "a"}, + {1, "[.]", "."}, + {0, "[\\]]", "a"}, + {1, "[\\]]", "]"}, + {0, "[b]", "a"}, + {1, "[b]", "b"}, + {0, "[b]", "c"}, + {0, "[bc]", "a"}, + {1, "[bc]", "b"}, + {1, "[bc]", "c"}, + {0, "[bc]", "d"}, + {0, "[bcd]", "a"}, + {1, "[bcd]", "b"}, + {1, "[bcd]", "c"}, + {1, "[bcd]", "d"}, + {0, "[bcd]", "e"}, + {0, "[b-d]", "a"}, + {1, "[b-d]", "b"}, + {1, "[b-d]", "d"}, + {0, "[b-d]", "e"}, + {1, "[^b-d]", "a"}, + {0, "[^b-d]", "b"}, + {0, "[^b-d]", "d"}, + {1, "[^b-d]", "e"}, + {0, "[^ -/]", "\t"}, + {1, "[^ -/]", "0"}, + {1, "[^{-~]", "z"}, + {0, "[^{-~]", "~"}, + {0, "[A-Za-z]", "5"}, + {1, "[A-Za-z]", "m"}, + {1, "[A-Za-z]", "M"}, + {0, "[A-Za-z]", "~"}, + {0, "[+-]", "*"}, + {1, "[+-]", "+"}, + {0, "[+-]", ","}, + {1, "[+-]", "-"}, + {0, "[+-]", "."}, + {1, "[b-d]*", ""}, + {0, "[b-d]*", "a"}, + {1, "[b-d]*", "b"}, + {1, "[b-d]*", "c"}, + {1, "[b-d]*", "cc"}, + {1, "[b-d]*", "d"}, + {0, "[b-d]*", "e"}, + {0, "[b-d]+", ""}, + {0, "[b-d]+", "a"}, + {1, "[b-d]+", "b"}, + {1, "[b-d]+", "c"}, + {1, "[b-d]+", "cc"}, + {1, "[b-d]+", "d"}, + {0, "[b-d]+", "e"}, + {1, "[b-d]?", ""}, + {0, "[b-d]?", "a"}, + {1, "[b-d]?", "b"}, + {1, "[b-d]?", "c"}, + {0, "[b-d]?", "cc"}, + {1, "[b-d]?", "d"}, + {0, "[b-d]?", "e"}, + {1, "h(e|a)llo", "hello"}, + {1, "h(e|a)llo", "hallo"}, + {1, "h(e|a)+llo", "haello"}, + {1, "h(e|a)*llo", "hllo"}, + {1, "h(e|a)?llo", "hllo"}, + {1, "h(e|a)?llo", "hello"}, + {1, "h(e|a)*llo*", "haeeeallooo"}, + {1, "(ab|a)(bc|c)", "abc"}, + {0, "(ab|a)(bc|c)", "acb"}, + {1, "(ab)c|abc", "abc"}, + {0, "(ab)c|abc", "ab"}, + {1, "(a*)(b?)(b+)", "aaabbbb"}, + {0, "(a*)(b?)(b+)", "aaaa"}, + {1, "((a|a)|a)", "a"}, + {0, "((a|a)|a)", "aa"}, + {1, "(a*)(a|aa)", "aaaa"}, + {0, "(a*)(a|aa)", "b"}, + {1, "a(b)|c(d)|a(e)f", "aef"}, + {0, "a(b)|c(d)|a(e)f", "adf"}, + {1, "(a|b)c|a(b|c)", "ac"}, + {0, "(a|b)c|a(b|c)", "acc"}, + {1, "(a|b)c|a(b|c)", "ab"}, + {0, "(a|b)c|a(b|c)", "acb"}, + {1, "(a|b)*c|(a|ab)*c", "abc"}, + {0, "(a|b)*c|(a|ab)*c", "bbbcabbbc"}, + {1, "a?(ab|ba)ab", "abab"}, + {0, "a?(ab|ba)ab", "aaabab"}, + {1, "(aa|aaa)*|(a|aaaaa)", "aa"}, + {1, "(a)(b)(c)", "abc"}, + {1, "((((((((((x))))))))))", "x"}, + {1, "((((((((((x))))))))))*", "xx"}, + {1, "a?(ab|ba)*", "ababababababababababababababababa"}, + {1, "a*a*a*a*a*b", "aaaaaaaab"}, + {1, "abc", "abc"}, + {1, "ab*c", "abc"}, + {1, "ab*bc", "abbc"}, + {1, "ab*bc", "abbbbc"}, + {1, "ab+bc", "abbc"}, + {1, "ab+bc", "abbbbc"}, + {1, "ab?bc", "abbc"}, + {1, "ab?bc", "abc"}, + {1, "ab|cd", "ab"}, + {1, "(a)b(c)", "abc"}, + {1, "a*", "aaa"}, + {1, "(a+|b)*", "ab"}, + {1, "(a+|b)+", "ab"}, + {1, "a|b|c|d|e", "e"}, + {1, "(a|b|c|d|e)f", "ef"}, + {1, "abcd*efg", "abcdefg"}, + {1, "(ab|ab*)bc", "abc"}, + {1, "(ab|a)b*c", "abc"}, + {1, "((a)(b)c)(d)", "abcd"}, + {1, "(a|ab)(c|bcd)", "abcd"}, + {1, "(a|ab)(bcd|c)", "abcd"}, + {1, "(ab|a)(c|bcd)", "abcd"}, + {1, "(ab|a)(bcd|c)", "abcd"}, + {1, "((a|ab)(c|bcd))(d*)", "abcd"}, + {1, "((a|ab)(bcd|c))(d*)", "abcd"}, + {1, "((ab|a)(c|bcd))(d*)", "abcd"}, + {1, "((ab|a)(bcd|c))(d*)", "abcd"}, + {1, "(a|ab)((c|bcd)(d*))", "abcd"}, + {1, "(a|ab)((bcd|c)(d*))", "abcd"}, + {1, "(ab|a)((c|bcd)(d*))", "abcd"}, + {1, "(ab|a)((bcd|c)(d*))", "abcd"}, + {1, "(a*)(b|abc)", "abc"}, + {1, "(a*)(abc|b)", "abc"}, + {1, "((a*)(b|abc))(c*)", "abc"}, + {1, "((a*)(abc|b))(c*)", "abc"}, + {1, "(a*)((b|abc))(c*)", "abc"}, + {1, "(a*)((abc|b)(c*))", "abc"}, + {1, "(a*)(b|abc)", "abc"}, + {1, "(a*)(abc|b)", "abc"}, + {1, "((a*)(b|abc))(c*)", "abc"}, + {1, "((a*)(abc|b))(c*)", "abc"}, + {1, "(a*)((b|abc)(c*))", "abc"}, + {1, "(a*)((abc|b)(c*))", "abc"}, + {1, "(a|ab)", "ab"}, + {1, "(ab|a)", "ab"}, + {1, "(a|ab)(b*)", "ab"}, + {1, "(ab|a)(b*)", "ab"}, + {1, "(a|b)*c|(a|ab)*c", "abc"}, +}; + +int +main(void) +{ + const size_t n_tests = sizeof(match_tests) / sizeof(*match_tests); + + for (size_t i = 0; i < n_tests; ++i) { + const char* const regexp = match_tests[i].pattern; + const char* const text = match_tests[i].text; + const bool should_match = match_tests[i].match; + + RerexPattern* pattern = NULL; + size_t end = 0; + const RerexStatus st = rerex_compile(regexp, &end, &pattern); + + assert(!st); + + RerexMatcher* const matcher = rerex_new_matcher(pattern); + const bool matches = rerex_match(matcher, text); + + assert(matches == should_match); + + rerex_free_matcher(matcher); + rerex_free_pattern(pattern); + } + + return 0; +} diff --git a/subprojects/rerex/test/test_syntax.c b/subprojects/rerex/test/test_syntax.c new file mode 100644 index 00000000..9cff8855 --- /dev/null +++ b/subprojects/rerex/test/test_syntax.c @@ -0,0 +1,99 @@ +/* + Copyright 2020 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// Tests that regex syntax errors are reported correctly + +#undef NDEBUG + +#include "rerex/rerex.h" + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +typedef struct { + RerexStatus status; + unsigned offset; + const char* pattern; +} BadSyntaxTestCase; + +static const BadSyntaxTestCase syntax_tests[] = { + {REREX_EXPECTED_CHAR, 1, "a\b"}, + {REREX_EXPECTED_CHAR, 1, "a\x7F"}, + {REREX_EXPECTED_ELEMENT, 1, "[\b]"}, + {REREX_EXPECTED_ELEMENT, 1, "[\x7F]"}, + {REREX_EXPECTED_ELEMENT, 2, "[a\b]"}, + {REREX_EXPECTED_ELEMENT, 2, "[a\x7F]"}, + {REREX_EXPECTED_ELEMENT, 3, "[a-\b]"}, + {REREX_EXPECTED_ELEMENT, 3, "[a-\x7F]"}, + {REREX_EXPECTED_RBRACKET, 2, "[\\n]"}, + {REREX_EXPECTED_RPAREN, 2, "(a"}, + {REREX_EXPECTED_SPECIAL, 1, "\\n"}, + {REREX_UNEXPECTED_END, 1, "("}, + {REREX_UNEXPECTED_END, 1, "["}, + {REREX_UNEXPECTED_END, 2, "[a"}, + {REREX_UNEXPECTED_END, 3, "(a|"}, + {REREX_UNEXPECTED_END, 3, "[a-"}, + {REREX_UNEXPECTED_END, 4, "[a-z"}, + {REREX_UNEXPECTED_END, 4, "[a-z"}, + {REREX_UNEXPECTED_SPECIAL, 0, "{"}, + {REREX_UNEXPECTED_SPECIAL, 0, "}"}, + {REREX_UNEXPECTED_SPECIAL, 0, "?"}, + {REREX_UNEXPECTED_SPECIAL, 1, "[]]"}, + {REREX_UNEXPECTED_SPECIAL, 2, "a|?"}, + {REREX_UNEXPECTED_SPECIAL, 3, "(a|?)"}, + {REREX_UNEXPECTED_SPECIAL, 3, "[[]]"}, + {REREX_UNEXPECTED_SPECIAL, 3, "[a]]"}, + {REREX_UNEXPECTED_SPECIAL, 4, "[A-]]"}, + {REREX_UNEXPECTED_SPECIAL, 4, "[a[]]"}, + {REREX_UNEXPECTED_SPECIAL, 5, "[A-[]]"}, + {REREX_UNORDERED_RANGE, 4, "[z-a]"}, +}; + +static void +test_status(void) +{ + assert(!strcmp(rerex_strerror((RerexStatus)INT32_MAX), "Unknown error")); +} + +static void +test_syntax(void) +{ + const size_t n_tests = sizeof(syntax_tests) / sizeof(*syntax_tests); + + for (size_t i = 0; i < n_tests; ++i) { + const char* const regexp = syntax_tests[i].pattern; + const size_t offset = syntax_tests[i].offset; + const RerexStatus status = syntax_tests[i].status; + + RerexPattern* pattern = NULL; + size_t end = 0; + const RerexStatus st = rerex_compile(regexp, &end, &pattern); + + assert(st == status); + assert(!pattern); + assert(strcmp(rerex_strerror(st), rerex_strerror(REREX_SUCCESS))); + assert(end == offset); + } +} + +int +main(void) +{ + test_status(); + test_syntax(); + return 0; +} diff --git a/subprojects/rerex/test/test_xsd.c b/subprojects/rerex/test/test_xsd.c new file mode 100644 index 00000000..81104a99 --- /dev/null +++ b/subprojects/rerex/test/test_xsd.c @@ -0,0 +1,522 @@ +/* + Copyright 2020 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/* + Tests more realistic patterns and using a matcher multiple times. + + The patterns here were written by myself and may have bugs. XSD datatypes + unfortunately don't have canonical patterns, though sometimes they + infuriatingly say that they are constrained by a pattern... which is not + given. XML is terrible, don't use it, but the XSD datatypes are more + generally useful. Some patterns here slightly fuzzy (for example, with + dates), so matching does not necessary mean the value itself is valid. + + These don't have much to do with Rerex itself, but it's something I needed it + for, and having some more realistic tests is nice. These also test reusing a + matcher, unlike the basic match tests. +*/ + +#undef NDEBUG + +#include "rerex/rerex.h" + +#include <assert.h> +#include <stddef.h> + +static void +test_pattern(const char* const regexp, + const char* const matching[], + const char* const nonmatching[]) +{ + RerexPattern* pattern = NULL; + size_t end = 0; + const RerexStatus st = rerex_compile(regexp, &end, &pattern); + + assert(!st); + + RerexMatcher* const matcher = rerex_new_matcher(pattern); + + for (const char* const* m = matching; *m; ++m) { + assert(rerex_match(matcher, *m)); + } + + for (const char* const* n = nonmatching; *n; ++n) { + assert(!rerex_match(matcher, *n)); + } + + rerex_free_matcher(matcher); + rerex_free_pattern(pattern); +} + +static void +test_base64Binary(void) +{ + static const char* const regexp = + "(([A-Za-z0-9+/] *[A-Za-z0-9+/] *[A-Za-z0-9+/] *[A-Za-z0-9+/] *)*" // + "(([A-Za-z0-9+/] *[A-Za-z0-9+/] *[A-Za-z0-9+/] *[A-Za-z0-9+/])|" // + "([A-Za-z0-9+/] *[A-Za-z0-9+/] *[AEIMQUYcgkosw048] *=)|" // + "([A-Za-z0-9+/] *[AQgw] *= *=)))?"; + + static const char* const good[] = { + "0FB8", + "0fb8", + "0 FB8 0F+9", + "0F+40A8=", + "0F+40A==", + "", + NULL, + }; + + static const char* const bad[] = { + " 0FB8", + "0FB8 ", + " 0FB8 ", + "FB8", + "==0F", + "0F+40A9=", + "0F+40B==", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_boolean(void) +{ + static const char* const regexp = "(true|false|0|1)"; + static const char* const good[] = {"true", "false", "0", "1", NULL}; + static const char* const bad[] = {"TRUE", "T", "", NULL}; + + test_pattern(regexp, good, bad); +} + +static void +test_date(void) +{ + static const char* const regexp = // + "-?[0-9][0-9][0-9][0-9][0-9]*" // + "-(0[1-9]|1[0-2])" // + "-(0[1-9]|[12][0-9]|3[01])" // + "(Z|[-+][0-2][0-9]:[0-5][0-9])?"; + + static const char* const good[] = { + "2004-04-12", + "-0045-01-01", + "12004-04-12", + "2004-04-12-05:00", + "2004-04-12Z", + "2001-10-26", + "2001-10-26+02:00", + "2001-10-26Z", + "2001-10-26+00:00", + "-2001-10-26", + "-20000-04-01", + NULL, + }; + + static const char* const bad[] = { + "99-04-12", + "2004-4-2", + "2004/04/02", + "04-12-2004", + // "2004-04-31", // Not quite that clever... + "2001-10", + "2001-10-32", + "2001-13-26+02:00", + "01-10-26", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_decimal(void) +{ + static const char* const regexp = + "[+-]?(([0-9]+[.]?[0-9]*)|([0-9]*[.]?[0-9]+))"; + + static const char* const good[] = { + "3.0", + "-3.0", + "+3.5", + "3", + ".3", + "3.", + "0", + "-.3", + "0003.0", + "3.0000", + "-456", + NULL, + }; + + static const char* const bad[] = {"3,5", ".", "", NULL}; + + test_pattern(regexp, good, bad); +} + +// Tests both xsd:float and xsd:double, which are lexically identical +static void +test_float(void) +{ + static const char* const regexp = "-?INF|NaN|[+-]?(([0-9]+[.]?[0-9]*)|([0-" + "9]*[.]?[0-9]+))([eE][-+]?[0-9]+)?"; + + static const char* const good[] = { + "-3E2", + "4268.22752E11", + "+24.3e-3", + "12", + "+3.5", + "INF", + "-INF", + "-0", + "NaN", + NULL, + }; + + static const char* const bad[] = { + "-3E2.4", + "12E", + "+INF", + "NAN", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_gDay(void) +{ + static const char* const regexp = + "---(0[1-9]|[12][0-9]|3[01])(Z|[-+][0-2][0-9]:[0-5][0-9])?"; + + static const char* const good[] = { + "---02", + "---01", + "---01Z", + "---01+02:00", + "---01-04:00", + "---15", + "---31", + NULL, + }; + + static const char* const bad[] = { + "02", + "---2", + "---32", + "--30-", + "---35", + "---5", + "15", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_gMonth(void) +{ + static const char* const regexp = + "--(0[1-9]|1[0-2])(Z|[-+][0-2][0-9]:[0-5][0-9])?"; + + static const char* const good[] = { + "--04", + "--04-05:00", + "--05", + "--11Z", + "--11+02:00", + "--11-04:00", + "--02", + NULL, + }; + + static const char* const bad[] = { + "2004-04", + "04", + "--4", + "--13", + "-01-", + "--13", + "--1", + "01", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_gMonthDay(void) +{ + static const char* const regexp = // + "--(0[1-9]|1[0-2])" // + "-(0[1-9]|[12][0-9]|3[01])" // + "(Z|[-+][0-2][0-9]:[0-5][0-9])?"; + + static const char* const good[] = { + "--04-12", + "--04-12Z", + "--05-01", + "--11-01Z", + "--11-01+02:00", + "--11-01-04:00", + "--11-15", + "--02-29", + NULL, + }; + + static const char* const bad[] = { + "04-12", + // "--04-31", Not quite that clever... + "--4-6", + "-01-30-", + "--01-35", + "--1-5", + "01-15", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_gYear(void) +{ + static const char* const regexp = + "-?[0-9][0-9][0-9][0-9][0-9]*(Z|[-+][0-2][0-9]:[0-5][0-9])?"; + + static const char* const good[] = { + "2004", + "2004-05:00", + "12004", + "0922", + "-0045", + "2001+02:00", + "2001Z", + "2001+00:00", + "-2001", + "-20000", + NULL, + }; + + static const char* const bad[] = { + "99", + "922", + "01", + "2001-12", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_gYearMonth(void) +{ + static const char* const regexp = // + "-?[0-9][0-9][0-9][0-9][0-9]*" // + "-(0[1-9]|1[0-2])" // + "(Z|[-+][0-2][0-9]:[0-5][0-9])?"; + + static const char* const good[] = { + "2001-10", + "2001-10+02:00", + "2001-10Z", + "2001-10+00:00", + "-2001-10", + "-20000-04", + "2004-04-05:00", + NULL, + }; + + static const char* const bad[] = { + "2001", + "2001-13", + "2001-13-26+02:00", + "01-10", + "99-04", + "2004", + "2004-4", + "2004-13", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_hexBinary(void) +{ + static const char* const regexp = "([0-9A-Fa-f][0-9A-Fa-f])*"; + static const char* const good[] = {"0FB8", "0fb8", "", NULL}; + static const char* const bad[] = {"F", "FB8", NULL}; + + test_pattern(regexp, good, bad); +} + +static void +test_integer(void) +{ + static const char* const regexp = "[-+]?[0-9]+"; + static const char* const good[] = {"122", "00122", "0", "-3", "+3", NULL}; + static const char* const bad[] = {"3.", "3.0", "A", "", NULL}; + + test_pattern(regexp, good, bad); +} + +static void +test_language(void) +{ + static const char* const regexp = // + "[a-zA-Z][a-zA-Z]?[a-zA-Z]?[a-zA-Z]?" // + "[a-zA-Z]?[a-zA-Z]?[a-zA-Z]?[a-zA-Z]?" // + "(-[a-zA-Z0-9][a-zA-Z0-9]?[a-zA-Z0-9]?[a-zA-Z0-9]?" // + "[a-zA-Z0-9]?[a-zA-Z0-9]?[a-zA-Z0-9]?[a-zA-Z0-9]?)*"; + + static const char* const good[] = { + "en", + "en-GB", + "en-US", + "fr", + "fr-FR", + "fr-CA", + "de", + "zh", + "ja", + "ko", + "i-navajo", + "x-Newspeak", + "any-value-with-short-parts", + NULL, + }; + + static const char* const bad[] = { + "longerThan8", + "even-longerThan8", + "longererThan8-first", + "last-longererThan8", + "middle-longererThan8-CA", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +static void +test_nonNegativeInteger(void) +{ + static const char* const regexp = "[+]?[0-9]+"; + static const char* const good[] = {"+3", "122", "0", "0012", "+123", NULL}; + static const char* const bad[] = {"-3", "3.0", "", NULL}; + + test_pattern(regexp, good, bad); +} + +static void +test_nonPositiveInteger(void) +{ + static const char* const regexp = "(0|-[0-9]+)"; + static const char* const good[] = {"-3", "-0", "-00122", NULL}; + static const char* const bad[] = {"122", "+3", "3.", "3.0", "", NULL}; + + test_pattern(regexp, good, bad); +} + +static void +test_positiveInteger(void) +{ + static const char* const regexp = "[+]?[0-9]*[1-9]+[0-9]*"; + static const char* const good[] = {"122", "+3", "00122", NULL}; + static const char* const bad[] = {"0", "-3", "3.0", "", NULL}; + + test_pattern(regexp, good, bad); +} + +static void +test_time(void) +{ + static const char* const regexp = + "(([0-1][0-9])|(2[0-4])):[0-5][0-9]:[0-5][0-9](.[0-9]+)?(Z|[-+][0-2][0-" + "9]:[0-5][0-9])?"; + + static const char* const good[] = { + "13:20:00", + "13:20:30.5555", + "13:20:00-05:00", + "13:20:00Z", + "00:00:00", + "24:00:00", + "21:32:52", + "21:32:52+02:00", + "19:32:52Z", + "19:32:52+00:00", + "21:32:52.12679", + NULL, + }; + + static const char* const bad[] = { + "5:20:00", + "13:20", + "13:20.5:00", + "13:65:00", + "21:32", + "25:25:10", + "-10:00:00", + "1:20:10", + "", + NULL, + }; + + test_pattern(regexp, good, bad); +} + +int +main(void) +{ + test_base64Binary(); + test_boolean(); + test_date(); + test_decimal(); + test_float(); + test_gDay(); + test_gMonth(); + test_gMonthDay(); + test_gYear(); + test_gYearMonth(); + test_hexBinary(); + test_integer(); + test_language(); + test_nonNegativeInteger(); + test_nonPositiveInteger(); + test_positiveInteger(); + test_time(); + + return 0; +} |