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