|
6 | 6 |
|
7 | 7 | #include <zephyr/posix/fnmatch.h> |
8 | 8 | #include <zephyr/ztest.h> |
| 9 | +#include <ctype.h> |
| 10 | + |
| 11 | +/* |
| 12 | + * Note: the \x00 control character is specifically excluded below, since testing for it is |
| 13 | + * equivalent to reading past the end of a '\0'-terminated string (i.e. can fault). |
| 14 | + */ |
| 15 | +#define TEST_BLANK_CHARS " \t" |
| 16 | +#define TEST_CNTRL_CHARS \ |
| 17 | + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16" \ |
| 18 | + "\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f" |
| 19 | +#define TEST_DIGIT_CHARS "0123456789" |
| 20 | +#define TEST_LOWER_CHARS "abcdefghijklmnopqrstuvwxyz" |
| 21 | +#define TEST_PUNCT_CHARS "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" |
| 22 | +#define TEST_SPACE_CHARS " \f\n\r\t\v" |
| 23 | +#define TEST_UPPER_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 24 | +#define TEST_XDIGIT_CHARS TEST_DIGIT_CHARS "ABCDEFabcdef" |
9 | 25 |
|
10 | 26 | /* |
11 | 27 | * Adapted from |
@@ -78,4 +94,50 @@ ZTEST(posix_c_lib_ext, test_fnmatch) |
78 | 94 | zassert_ok(fnmatch("a?b", "a.b", FNM_PATHNAME | FNM_PERIOD)); |
79 | 95 | zassert_ok(fnmatch("a*b", "a.b", FNM_PATHNAME | FNM_PERIOD)); |
80 | 96 | zassert_ok(fnmatch("a[.]b", "a.b", FNM_PATHNAME | FNM_PERIOD)); |
| 97 | + |
| 98 | + /* Additional test cases for POSIX character classes (C-locale only) */ |
| 99 | + static const struct test_data_s { |
| 100 | + const char *pattern; |
| 101 | + const char *match; |
| 102 | + const char *nomatch; |
| 103 | + } test_data[] = { |
| 104 | + {"[[:alnum:]]", TEST_DIGIT_CHARS TEST_UPPER_CHARS TEST_LOWER_CHARS, " "}, |
| 105 | + {"[[:alpha:]]", TEST_UPPER_CHARS TEST_LOWER_CHARS, "0"}, |
| 106 | + {"[[:blank:]]", TEST_BLANK_CHARS, "x"}, |
| 107 | + {"[[:cntrl:]]", TEST_CNTRL_CHARS, "x"}, |
| 108 | + {"[[:digit:]]", TEST_DIGIT_CHARS, "a"}, |
| 109 | + {"[[:graph:]]", TEST_DIGIT_CHARS TEST_UPPER_CHARS TEST_LOWER_CHARS TEST_PUNCT_CHARS, |
| 110 | + " "}, |
| 111 | + {"[[:lower:]]", TEST_LOWER_CHARS, "X"}, |
| 112 | + {"[[:print:]]", |
| 113 | + TEST_DIGIT_CHARS TEST_UPPER_CHARS TEST_LOWER_CHARS TEST_PUNCT_CHARS " ", "\t"}, |
| 114 | + {"[[:punct:]]", TEST_PUNCT_CHARS, "x"}, |
| 115 | + {"[[:space:]]", TEST_SPACE_CHARS, "x"}, |
| 116 | + {"[[:upper:]]", TEST_UPPER_CHARS, "x"}, |
| 117 | + {"[[:xdigit:]]", TEST_XDIGIT_CHARS, "h"}, |
| 118 | + }; |
| 119 | + |
| 120 | + ARRAY_FOR_EACH_PTR(test_data, data) { |
| 121 | + /* ensure that characters in "nomatch" do not match "pattern" */ |
| 122 | + for (size_t j = 0; j < strlen(data->nomatch); j++) { |
| 123 | + char input[] = {data->nomatch[j], '\0'}; |
| 124 | + |
| 125 | + zexpect_equal(fnmatch(data->pattern, input, 0), FNM_NOMATCH, |
| 126 | + "pattern \"%s\" unexpectedly matched char 0x%02x (%c)", |
| 127 | + data->pattern, data->nomatch[j], |
| 128 | + isprint(data->nomatch[j]) ? data->nomatch[j] : '.'); |
| 129 | + } |
| 130 | + |
| 131 | + /* ensure that characters in "match" do match "pattern" */ |
| 132 | + for (size_t j = 0; j < strlen(data->match); j++) { |
| 133 | + char input[] = {data->match[j], '\0'}; |
| 134 | + |
| 135 | + zexpect_ok(fnmatch(data->pattern, input, 0), |
| 136 | + "pattern \"%s\" did not match char 0x%02x (%c)", data->pattern, |
| 137 | + data->match[j], isprint(data->match[j]) ? data->match[j] : '.'); |
| 138 | + } |
| 139 | + } |
| 140 | + |
| 141 | + /* ensure that an invalid character class generates an error */ |
| 142 | + zassert_equal(fnmatch("[[:foobarbaz:]]", "Z", 0), FNM_NOMATCH); |
81 | 143 | } |
0 commit comments