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); 94 ATF_TC_HEAD(basename_posix, tc) 95 { 96 atf_tc_set_md_var(tc, "descr", "Test basename(3) with POSIX examples"); 97 } 98 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); 147 ATF_TC_HEAD(dirname_posix, tc) 148 { 149 atf_tc_set_md_var(tc, "descr", "Test dirname(3) with POSIX examples"); 150 } 151 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 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