1272343Sngie/* $NetBSD: t_basedirname.c,v 1.2 2011/07/07 09:49:59 jruoho Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Regression test for basename(3). 5272343Sngie * 6272343Sngie * Written by Jason R. Thorpe <thorpej@NetBSD.org>, Oct. 2002. 7272343Sngie * Public domain. 8272343Sngie */ 9272343Sngie 10272343Sngie#include <atf-c.h> 11272343Sngie 12272343Sngie#include <assert.h> 13272343Sngie#include <stdio.h> 14272343Sngie#include <stdlib.h> 15272343Sngie#include <string.h> 16272343Sngie#include <libgen.h> 17272343Sngie 18272343Sngiestruct { 19272343Sngie const char *input; 20272343Sngie const char *output; 21272343Sngie} test_basename_table[] = { 22272343Sngie/* 23272343Sngie * The following are taken from the "Sample Input and Output Strings 24272343Sngie * for basename()" table in IEEE Std 1003.1-2001. 25272343Sngie */ 26272343Sngie { "/usr/lib", "lib" }, 27272343Sngie { "/usr/", "usr" }, 28272343Sngie { "/", "/" }, 29272343Sngie { "///", "/" }, 30272343Sngie { "//usr//lib//", "lib" }, 31272343Sngie/* 32272343Sngie * IEEE Std 1003.1-2001: 33272343Sngie * 34272343Sngie * If path is a null pointer or points to an empty string, 35272343Sngie * basename() shall return a pointer to the string "." . 36272343Sngie */ 37272343Sngie { "", "." }, 38272343Sngie { NULL, "." }, 39272343Sngie/* 40272343Sngie * IEEE Std 1003.1-2001: 41272343Sngie * 42272343Sngie * If the string is exactly "//", it is implementation-defined 43272343Sngie * whether "/" or "//" is returned. 44272343Sngie * 45272343Sngie * The NetBSD implementation returns "/". 46272343Sngie */ 47272343Sngie { "//", "/" }, 48272343Sngie 49272343Sngie { NULL, NULL } 50272343Sngie}; 51272343Sngie 52272343Sngiestruct { 53272343Sngie const char *input; 54272343Sngie const char *output; 55272343Sngie} test_dirname_table[] = { 56272343Sngie/* 57272343Sngie * The following are taken from the "Sample Input and Output Strings 58272343Sngie * for dirname()" table in IEEE Std 1003.1-2001. 59272343Sngie */ 60272343Sngie { "/usr/lib", "/usr" }, 61272343Sngie { "/usr/", "/" }, 62272343Sngie { "usr", "." }, 63272343Sngie { "/", "/" }, 64272343Sngie { ".", "." }, 65272343Sngie { "..", "." }, 66272343Sngie/* 67272343Sngie * IEEE Std 1003.1-2001: 68272343Sngie * 69272343Sngie * If path is a null pointer or points to an empty string, 70272343Sngie * dirname() shall return a pointer to the string "." . 71272343Sngie */ 72272343Sngie { "", "." }, 73272343Sngie { NULL, "." }, 74272343Sngie/* 75272343Sngie * IEEE Std 1003.1-2001: 76272343Sngie * 77272343Sngie * Since the meaning of the leading "//" is implementation-defined, 78272343Sngie * dirname("//foo") may return either "//" or "/" (but nothing else). 79272343Sngie * 80272343Sngie * The NetBSD implementation returns "/". 81272343Sngie */ 82272343Sngie { "//foo", "/" }, 83272343Sngie/* 84272343Sngie * Make sure the trailing slashes after the directory name component 85272343Sngie * get trimmed. The Std does not talk about this, but this is what 86272343Sngie * Solaris 8's dirname(3) does. 87272343Sngie */ 88272343Sngie { "/usr///lib", "/usr" }, 89272343Sngie 90272343Sngie { NULL, NULL } 91272343Sngie}; 92272343Sngie 93272343SngieATF_TC(basename_posix); 94272343SngieATF_TC_HEAD(basename_posix, tc) 95272343Sngie{ 96272343Sngie atf_tc_set_md_var(tc, "descr", "Test basename(3) with POSIX examples"); 97272343Sngie} 98272343Sngie 99272343SngieATF_TC_BODY(basename_posix, tc) 100272343Sngie{ 101272343Sngie char testbuf[32], *base; 102272343Sngie int i; 103272343Sngie 104272343Sngie for (i = 0; test_basename_table[i].output != NULL; i++) { 105272343Sngie if (test_basename_table[i].input != NULL) { 106272343Sngie if (strlen(test_basename_table[i].input) >= 107272343Sngie sizeof(testbuf)) 108272343Sngie atf_tc_skip("Testbuf too small!"); 109272343Sngie strcpy(testbuf, test_basename_table[i].input); 110272343Sngie base = basename(testbuf); 111272343Sngie } else 112272343Sngie base = basename(NULL); 113272343Sngie 114272343Sngie /* 115272343Sngie * basename(3) is allowed to modify the input buffer. 116272343Sngie * However, that is considered hostile by some programs, 117272343Sngie * and so we elect to consider this an error. 118272343Sngie * 119272343Sngie * This is not a problem, as basename(3) is also allowed 120272343Sngie * to return a pointer to a statically-allocated buffer 121272343Sngie * (it is explicitly not required to be reentrant). 122272343Sngie */ 123272343Sngie if (test_basename_table[i].input != NULL && 124272343Sngie strcmp(test_basename_table[i].input, testbuf) != 0) { 125272343Sngie fprintf(stderr, 126272343Sngie "Input buffer for \"%s\" was modified\n", 127272343Sngie test_basename_table[i].input); 128272343Sngie atf_tc_fail("Input buffer was modified."); 129272343Sngie } 130272343Sngie 131272343Sngie /* Make sure the result is correct. */ 132272343Sngie if (strcmp(test_basename_table[i].output, base) != 0) { 133272343Sngie fprintf(stderr, 134272343Sngie "Input \"%s\", output \"%s\", expected \"%s\"\n", 135272343Sngie test_basename_table[i].input == 136272343Sngie NULL ? "(null)" : test_basename_table[i].input, 137272343Sngie base, test_basename_table[i].output); 138272343Sngie atf_tc_fail("Output does not match expected value."); 139272343Sngie } 140272343Sngie } 141272343Sngie} 142272343Sngie 143272343Sngie 144272343SngieATF_TC(dirname_posix); 145272343SngieATF_TC_HEAD(dirname_posix, tc) 146272343Sngie{ 147272343Sngie atf_tc_set_md_var(tc, "descr", "Test dirname(3) with POSIX examples"); 148272343Sngie} 149272343Sngie 150272343SngieATF_TC_BODY(dirname_posix, tc) 151272343Sngie{ 152272343Sngie char testbuf[32], *base; 153272343Sngie int i; 154272343Sngie 155272343Sngie for (i = 0; test_dirname_table[i].output != NULL; i++) { 156272343Sngie if (test_dirname_table[i].input != NULL) { 157272343Sngie if (strlen(test_dirname_table[i].input) >= 158272343Sngie sizeof(testbuf)) 159272343Sngie atf_tc_skip("Testbuf too small!"); 160272343Sngie strcpy(testbuf, test_dirname_table[i].input); 161272343Sngie base = dirname(testbuf); 162272343Sngie } else 163272343Sngie base = dirname(NULL); 164272343Sngie 165272343Sngie /* 166272343Sngie * dirname(3) is allowed to modify the input buffer. 167272343Sngie * However, that is considered hostile by some programs, 168272343Sngie * and so we elect to consider this an error. 169272343Sngie * 170272343Sngie * This is not a problem, as dirname(3) is also allowed 171272343Sngie * to return a pointer to a statically-allocated buffer 172272343Sngie * (it is explicitly not required to be reentrant). 173272343Sngie */ 174272343Sngie if (test_dirname_table[i].input != NULL && 175272343Sngie strcmp(test_dirname_table[i].input, testbuf) != 0) { 176272343Sngie fprintf(stderr, 177272343Sngie "Input buffer for \"%s\" was modified\n", 178272343Sngie test_dirname_table[i].input); 179272343Sngie atf_tc_fail("Input buffer was modified."); 180272343Sngie } 181272343Sngie 182272343Sngie /* Make sure the result is correct. */ 183272343Sngie if (strcmp(test_dirname_table[i].output, base) != 0) { 184272343Sngie fprintf(stderr, 185272343Sngie "Input \"%s\", output \"%s\", expected \"%s\"\n", 186272343Sngie test_dirname_table[i].input == 187272343Sngie NULL ? "(null)" : test_dirname_table[i].input, 188272343Sngie base, test_dirname_table[i].output); 189272343Sngie atf_tc_fail("Output does not match expected value."); 190272343Sngie } 191272343Sngie } 192272343Sngie} 193272343Sngie 194272343SngieATF_TP_ADD_TCS(tp) 195272343Sngie{ 196272343Sngie ATF_TP_ADD_TC(tp, basename_posix); 197272343Sngie ATF_TP_ADD_TC(tp, dirname_posix); 198272343Sngie 199272343Sngie return atf_no_error(); 200272343Sngie} 201