1 /* $NetBSD: t_basedirname.c,v 1.2 2011/07/07 09:49:59 jruoho Exp $ */
2
3 /*
4 * Regression test for basename(3).
5 *
6 * Written by Jason R. Thorpe <thorpej@NetBSD.org>, Oct. 2002.
7 * Public domain.
8 */
9
10 #include <atf-c.h>
11
12 #include <assert.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <libgen.h>
17
18 struct {
19 const char *input;
20 const char *output;
21 } test_basename_table[] = {
22 /*
23 * The following are taken from the "Sample Input and Output Strings
24 * for basename()" table in IEEE Std 1003.1-2001.
25 */
26 { "/usr/lib", "lib" },
27 { "/usr/", "usr" },
28 { "/", "/" },
29 { "///", "/" },
30 { "//usr//lib//", "lib" },
31 /*
32 * IEEE Std 1003.1-2001:
33 *
34 * If path is a null pointer or points to an empty string,
35 * basename() shall return a pointer to the string "." .
36 */
37 { "", "." },
38 { NULL, "." },
39 /*
40 * IEEE Std 1003.1-2001:
41 *
42 * If the string is exactly "//", it is implementation-defined
43 * whether "/" or "//" is returned.
44 *
45 * The NetBSD implementation returns "/".
46 */
47 { "//", "/" },
48
49 { NULL, NULL }
50 };
51
52 struct {
53 const char *input;
54 const char *output;
55 } test_dirname_table[] = {
56 /*
57 * The following are taken from the "Sample Input and Output Strings
58 * for dirname()" table in IEEE Std 1003.1-2001.
59 */
60 { "/usr/lib", "/usr" },
61 { "/usr/", "/" },
62 { "usr", "." },
63 { "/", "/" },
64 { ".", "." },
65 { "..", "." },
66 /*
67 * IEEE Std 1003.1-2001:
68 *
69 * If path is a null pointer or points to an empty string,
70 * dirname() shall return a pointer to the string "." .
71 */
72 { "", "." },
73 { NULL, "." },
74 /*
75 * IEEE Std 1003.1-2001:
76 *
77 * Since the meaning of the leading "//" is implementation-defined,
78 * dirname("//foo") may return either "//" or "/" (but nothing else).
79 *
80 * The NetBSD implementation returns "/".
81 */
82 { "//foo", "/" },
83 /*
84 * Make sure the trailing slashes after the directory name component
85 * get trimmed. The Std does not talk about this, but this is what
86 * Solaris 8's dirname(3) does.
87 */
88 { "/usr///lib", "/usr" },
89
90 { NULL, NULL }
91 };
92
93 ATF_TC(basename_posix);
ATF_TC_HEAD(basename_posix,tc)94 ATF_TC_HEAD(basename_posix, tc)
95 {
96 atf_tc_set_md_var(tc, "descr", "Test basename(3) with POSIX examples");
97 }
98
ATF_TC_BODY(basename_posix,tc)99 ATF_TC_BODY(basename_posix, tc)
100 {
101 char testbuf[32], *base;
102 int i;
103
104 for (i = 0; test_basename_table[i].output != NULL; i++) {
105 if (test_basename_table[i].input != NULL) {
106 if (strlen(test_basename_table[i].input) >=
107 sizeof(testbuf))
108 atf_tc_skip("Testbuf too small!");
109 strcpy(testbuf, test_basename_table[i].input);
110 base = basename(testbuf);
111 } else
112 base = basename(NULL);
113
114 #ifdef __NetBSD__
115 /*
116 * basename(3) is allowed to modify the input buffer.
117 * However, that is considered hostile by some programs,
118 * and so we elect to consider this an error.
119 *
120 * This is not a problem, as basename(3) is also allowed
121 * to return a pointer to a statically-allocated buffer
122 * (it is explicitly not required to be reentrant).
123 */
124 if (test_basename_table[i].input != NULL &&
125 strcmp(test_basename_table[i].input, testbuf) != 0) {
126 fprintf(stderr,
127 "Input buffer for \"%s\" was modified\n",
128 test_basename_table[i].input);
129 atf_tc_fail("Input buffer was modified.");
130 }
131 #endif
132
133 /* Make sure the result is correct. */
134 if (strcmp(test_basename_table[i].output, base) != 0) {
135 fprintf(stderr,
136 "Input \"%s\", output \"%s\", expected \"%s\"\n",
137 test_basename_table[i].input ==
138 NULL ? "(null)" : test_basename_table[i].input,
139 base, test_basename_table[i].output);
140 atf_tc_fail("Output does not match expected value.");
141 }
142 }
143 }
144
145
146 ATF_TC(dirname_posix);
ATF_TC_HEAD(dirname_posix,tc)147 ATF_TC_HEAD(dirname_posix, tc)
148 {
149 atf_tc_set_md_var(tc, "descr", "Test dirname(3) with POSIX examples");
150 }
151
ATF_TC_BODY(dirname_posix,tc)152 ATF_TC_BODY(dirname_posix, tc)
153 {
154 char testbuf[32], *base;
155 int i;
156
157 for (i = 0; test_dirname_table[i].output != NULL; i++) {
158 if (test_dirname_table[i].input != NULL) {
159 if (strlen(test_dirname_table[i].input) >=
160 sizeof(testbuf))
161 atf_tc_skip("Testbuf too small!");
162 strcpy(testbuf, test_dirname_table[i].input);
163 base = dirname(testbuf);
164 } else
165 base = dirname(NULL);
166
167 #ifdef __NetBSD__
168 /*
169 * dirname(3) is allowed to modify the input buffer.
170 * However, that is considered hostile by some programs,
171 * and so we elect to consider this an error.
172 *
173 * This is not a problem, as dirname(3) is also allowed
174 * to return a pointer to a statically-allocated buffer
175 * (it is explicitly not required to be reentrant).
176 */
177 if (test_dirname_table[i].input != NULL &&
178 strcmp(test_dirname_table[i].input, testbuf) != 0) {
179 fprintf(stderr,
180 "Input buffer for \"%s\" was modified\n",
181 test_dirname_table[i].input);
182 atf_tc_fail("Input buffer was modified.");
183 }
184 #endif
185
186 /* Make sure the result is correct. */
187 if (strcmp(test_dirname_table[i].output, base) != 0) {
188 fprintf(stderr,
189 "Input \"%s\", output \"%s\", expected \"%s\"\n",
190 test_dirname_table[i].input ==
191 NULL ? "(null)" : test_dirname_table[i].input,
192 base, test_dirname_table[i].output);
193 atf_tc_fail("Output does not match expected value.");
194 }
195 }
196 }
197
ATF_TP_ADD_TCS(tp)198 ATF_TP_ADD_TCS(tp)
199 {
200 ATF_TP_ADD_TC(tp, basename_posix);
201 ATF_TP_ADD_TC(tp, dirname_posix);
202
203 return atf_no_error();
204 }
205