1 /*-
2 * Copyright (c) 2010 Jilles Tjoelker
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/param.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include <atf-c.h>
35
36 #include "fnmatch_testcases.h"
37
38 static const char *
flags_to_string(int flags)39 flags_to_string(int flags)
40 {
41 static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME,
42 FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 };
43 static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0";
44 static char result[sizeof(flagnames) + 3 * sizeof(int) + 2];
45 char *p;
46 size_t i, len;
47 const char *fp;
48
49 p = result;
50 fp = flagnames;
51 for (i = 0; flagvalues[i] != 0; i++) {
52 len = strlen(fp);
53 if (flags & flagvalues[i]) {
54 if (p != result)
55 *p++ = '|';
56 memcpy(p, fp, len);
57 p += len;
58 flags &= ~flagvalues[i];
59 }
60 fp += len + 1;
61 }
62 if (p == result)
63 memcpy(p, "0", 2);
64 else if (flags != 0)
65 sprintf(p, "%d", flags);
66 else
67 *p = '\0';
68 return result;
69 }
70
71 ATF_TC_WITHOUT_HEAD(fnmatch_test);
ATF_TC_BODY(fnmatch_test,tc)72 ATF_TC_BODY(fnmatch_test, tc)
73 {
74 size_t i;
75 int flags, result;
76 struct testcase *t;
77
78 for (i = 0; i < nitems(testcases); i++) {
79 t = &testcases[i];
80 flags = t->flags;
81 do {
82 result = fnmatch(t->pattern, t->string, flags);
83 if (result != t->result)
84 break;
85 if (strchr(t->pattern, '\\') == NULL &&
86 !(flags & FNM_NOESCAPE)) {
87 flags |= FNM_NOESCAPE;
88 result = fnmatch(t->pattern, t->string, flags);
89 if (result != t->result)
90 break;
91 flags = t->flags;
92 }
93 if (strchr(t->pattern, '\\') != NULL &&
94 strchr(t->string, '\\') == NULL &&
95 t->result == FNM_NOMATCH &&
96 !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) {
97 flags |= FNM_NOESCAPE;
98 result = fnmatch(t->pattern, t->string, flags);
99 if (result != t->result)
100 break;
101 flags = t->flags;
102 }
103 if ((t->string[0] != '.' || t->pattern[0] == '.' ||
104 t->result == FNM_NOMATCH) &&
105 !(flags & (FNM_PATHNAME | FNM_PERIOD))) {
106 flags |= FNM_PERIOD;
107 result = fnmatch(t->pattern, t->string, flags);
108 if (result != t->result)
109 break;
110 flags = t->flags;
111 }
112 if ((strchr(t->string, '/') == NULL ||
113 t->result == FNM_NOMATCH) &&
114 !(flags & FNM_PATHNAME)) {
115 flags |= FNM_PATHNAME;
116 result = fnmatch(t->pattern, t->string, flags);
117 if (result != t->result)
118 break;
119 flags = t->flags;
120 }
121 if ((((t->string[0] != '.' || t->pattern[0] == '.') &&
122 strstr(t->string, "/.") == NULL) ||
123 t->result == FNM_NOMATCH) &&
124 flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) {
125 flags |= FNM_PERIOD;
126 result = fnmatch(t->pattern, t->string, flags);
127 if (result != t->result)
128 break;
129 flags = t->flags;
130 }
131 if ((((t->string[0] != '.' || t->pattern[0] == '.') &&
132 strchr(t->string, '/') == NULL) ||
133 t->result == FNM_NOMATCH) &&
134 !(flags & (FNM_PATHNAME | FNM_PERIOD))) {
135 flags |= FNM_PATHNAME | FNM_PERIOD;
136 result = fnmatch(t->pattern, t->string, flags);
137 if (result != t->result)
138 break;
139 flags = t->flags;
140 }
141 if ((strchr(t->string, '/') == NULL || t->result == 0)
142 && !(flags & FNM_LEADING_DIR)) {
143 flags |= FNM_LEADING_DIR;
144 result = fnmatch(t->pattern, t->string, flags);
145 if (result != t->result)
146 break;
147 flags = t->flags;
148 }
149 if (t->result == 0 && !(flags & FNM_CASEFOLD)) {
150 flags |= FNM_CASEFOLD;
151 result = fnmatch(t->pattern, t->string, flags);
152 if (result != t->result)
153 break;
154 flags = t->flags;
155 }
156 if (strchr(t->pattern, '\\') == NULL &&
157 t->result == 0 &&
158 !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) {
159 flags |= FNM_NOESCAPE | FNM_CASEFOLD;
160 result = fnmatch(t->pattern, t->string, flags);
161 if (result != t->result)
162 break;
163 flags = t->flags;
164 }
165 } while (0);
166
167 ATF_CHECK(result == t->result);
168 if (result == t->result)
169 printf("fnmatch(\"%s\", \"%s\", %s) == %d\n",
170 t->pattern, t->string, flags_to_string(flags), result);
171 else
172 printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n",
173 t->pattern, t->string, flags_to_string(flags),
174 t->result, result);
175 }
176
177 }
178
ATF_TP_ADD_TCS(tp)179 ATF_TP_ADD_TCS(tp)
180 {
181
182 ATF_TP_ADD_TC(tp, fnmatch_test);
183
184 return (atf_no_error());
185 }
186