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