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