1 1.2 jruoho /* $NetBSD: t_basedirname.c,v 1.2 2011/07/07 09:49:59 jruoho 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.2 jruoho ATF_TC(basename_posix); 94 1.2 jruoho ATF_TC_HEAD(basename_posix, tc) 95 1.1 pgoyette { 96 1.1 pgoyette atf_tc_set_md_var(tc, "descr", "Test basename(3) with POSIX examples"); 97 1.1 pgoyette } 98 1.1 pgoyette 99 1.2 jruoho ATF_TC_BODY(basename_posix, tc) 100 1.1 pgoyette { 101 1.1 pgoyette char testbuf[32], *base; 102 1.1 pgoyette int i; 103 1.1 pgoyette 104 1.1 pgoyette for (i = 0; test_basename_table[i].output != NULL; i++) { 105 1.1 pgoyette if (test_basename_table[i].input != NULL) { 106 1.1 pgoyette if (strlen(test_basename_table[i].input) >= 107 1.1 pgoyette sizeof(testbuf)) 108 1.1 pgoyette atf_tc_skip("Testbuf too small!"); 109 1.1 pgoyette strcpy(testbuf, test_basename_table[i].input); 110 1.1 pgoyette base = basename(testbuf); 111 1.1 pgoyette } else 112 1.1 pgoyette base = basename(NULL); 113 1.1 pgoyette 114 1.1 pgoyette /* 115 1.1 pgoyette * basename(3) is allowed to modify the input buffer. 116 1.1 pgoyette * However, that is considered hostile by some programs, 117 1.1 pgoyette * and so we elect to consider this an error. 118 1.1 pgoyette * 119 1.1 pgoyette * This is not a problem, as basename(3) is also allowed 120 1.1 pgoyette * to return a pointer to a statically-allocated buffer 121 1.1 pgoyette * (it is explicitly not required to be reentrant). 122 1.1 pgoyette */ 123 1.1 pgoyette if (test_basename_table[i].input != NULL && 124 1.1 pgoyette strcmp(test_basename_table[i].input, testbuf) != 0) { 125 1.1 pgoyette fprintf(stderr, 126 1.1 pgoyette "Input buffer for \"%s\" was modified\n", 127 1.1 pgoyette test_basename_table[i].input); 128 1.1 pgoyette atf_tc_fail("Input buffer was modified."); 129 1.1 pgoyette } 130 1.1 pgoyette 131 1.1 pgoyette /* Make sure the result is correct. */ 132 1.1 pgoyette if (strcmp(test_basename_table[i].output, base) != 0) { 133 1.1 pgoyette fprintf(stderr, 134 1.1 pgoyette "Input \"%s\", output \"%s\", expected \"%s\"\n", 135 1.1 pgoyette test_basename_table[i].input == 136 1.1 pgoyette NULL ? "(null)" : test_basename_table[i].input, 137 1.1 pgoyette base, test_basename_table[i].output); 138 1.1 pgoyette atf_tc_fail("Output does not match expected value."); 139 1.1 pgoyette } 140 1.1 pgoyette } 141 1.1 pgoyette } 142 1.1 pgoyette 143 1.1 pgoyette 144 1.2 jruoho ATF_TC(dirname_posix); 145 1.2 jruoho ATF_TC_HEAD(dirname_posix, tc) 146 1.1 pgoyette { 147 1.1 pgoyette atf_tc_set_md_var(tc, "descr", "Test dirname(3) with POSIX examples"); 148 1.1 pgoyette } 149 1.1 pgoyette 150 1.2 jruoho ATF_TC_BODY(dirname_posix, tc) 151 1.1 pgoyette { 152 1.1 pgoyette char testbuf[32], *base; 153 1.1 pgoyette int i; 154 1.1 pgoyette 155 1.1 pgoyette for (i = 0; test_dirname_table[i].output != NULL; i++) { 156 1.1 pgoyette if (test_dirname_table[i].input != NULL) { 157 1.1 pgoyette if (strlen(test_dirname_table[i].input) >= 158 1.1 pgoyette sizeof(testbuf)) 159 1.1 pgoyette atf_tc_skip("Testbuf too small!"); 160 1.1 pgoyette strcpy(testbuf, test_dirname_table[i].input); 161 1.1 pgoyette base = dirname(testbuf); 162 1.1 pgoyette } else 163 1.1 pgoyette base = dirname(NULL); 164 1.1 pgoyette 165 1.1 pgoyette /* 166 1.1 pgoyette * dirname(3) is allowed to modify the input buffer. 167 1.1 pgoyette * However, that is considered hostile by some programs, 168 1.1 pgoyette * and so we elect to consider this an error. 169 1.1 pgoyette * 170 1.1 pgoyette * This is not a problem, as dirname(3) is also allowed 171 1.1 pgoyette * to return a pointer to a statically-allocated buffer 172 1.1 pgoyette * (it is explicitly not required to be reentrant). 173 1.1 pgoyette */ 174 1.1 pgoyette if (test_dirname_table[i].input != NULL && 175 1.1 pgoyette strcmp(test_dirname_table[i].input, testbuf) != 0) { 176 1.1 pgoyette fprintf(stderr, 177 1.1 pgoyette "Input buffer for \"%s\" was modified\n", 178 1.1 pgoyette test_dirname_table[i].input); 179 1.1 pgoyette atf_tc_fail("Input buffer was modified."); 180 1.1 pgoyette } 181 1.1 pgoyette 182 1.1 pgoyette /* Make sure the result is correct. */ 183 1.1 pgoyette if (strcmp(test_dirname_table[i].output, base) != 0) { 184 1.1 pgoyette fprintf(stderr, 185 1.1 pgoyette "Input \"%s\", output \"%s\", expected \"%s\"\n", 186 1.1 pgoyette test_dirname_table[i].input == 187 1.1 pgoyette NULL ? "(null)" : test_dirname_table[i].input, 188 1.1 pgoyette base, test_dirname_table[i].output); 189 1.1 pgoyette atf_tc_fail("Output does not match expected value."); 190 1.1 pgoyette } 191 1.1 pgoyette } 192 1.1 pgoyette } 193 1.1 pgoyette 194 1.1 pgoyette ATF_TP_ADD_TCS(tp) 195 1.1 pgoyette { 196 1.2 jruoho ATF_TP_ADD_TC(tp, basename_posix); 197 1.2 jruoho ATF_TP_ADD_TC(tp, dirname_posix); 198 1.1 pgoyette 199 1.1 pgoyette return atf_no_error(); 200 1.1 pgoyette } 201