157718be8SEnji Cooper /*	$NetBSD: t_basedirname.c,v 1.2 2011/07/07 09:49:59 jruoho Exp $	*/
257718be8SEnji Cooper 
357718be8SEnji Cooper /*
457718be8SEnji Cooper  * Regression test for basename(3).
557718be8SEnji Cooper  *
657718be8SEnji Cooper  * Written by Jason R. Thorpe <thorpej@NetBSD.org>, Oct. 2002.
757718be8SEnji Cooper  * Public domain.
857718be8SEnji Cooper  */
957718be8SEnji Cooper 
1057718be8SEnji Cooper #include <atf-c.h>
1157718be8SEnji Cooper 
1257718be8SEnji Cooper #include <assert.h>
1357718be8SEnji Cooper #include <stdio.h>
1457718be8SEnji Cooper #include <stdlib.h>
1557718be8SEnji Cooper #include <string.h>
1657718be8SEnji Cooper #include <libgen.h>
1757718be8SEnji Cooper 
1857718be8SEnji Cooper struct {
1957718be8SEnji Cooper 	const char *input;
2057718be8SEnji Cooper 	const char *output;
2157718be8SEnji Cooper } test_basename_table[] = {
2257718be8SEnji Cooper /*
2357718be8SEnji Cooper  * The following are taken from the "Sample Input and Output Strings
2457718be8SEnji Cooper  * for basename()" table in IEEE Std 1003.1-2001.
2557718be8SEnji Cooper  */
2657718be8SEnji Cooper 	{ "/usr/lib",		"lib" },
2757718be8SEnji Cooper 	{ "/usr/",		"usr" },
2857718be8SEnji Cooper 	{ "/",			"/" },
2957718be8SEnji Cooper 	{ "///",		"/" },
3057718be8SEnji Cooper 	{ "//usr//lib//",	"lib" },
3157718be8SEnji Cooper /*
3257718be8SEnji Cooper  * IEEE Std 1003.1-2001:
3357718be8SEnji Cooper  *
3457718be8SEnji Cooper  *	If path is a null pointer or points to an empty string,
3557718be8SEnji Cooper  *	basename() shall return a pointer to the string "." .
3657718be8SEnji Cooper  */
3757718be8SEnji Cooper 	{ "",			"." },
3857718be8SEnji Cooper 	{ NULL,			"." },
3957718be8SEnji Cooper /*
4057718be8SEnji Cooper  * IEEE Std 1003.1-2001:
4157718be8SEnji Cooper  *
4257718be8SEnji Cooper  *	If the string is exactly "//", it is implementation-defined
4357718be8SEnji Cooper  *	whether "/" or "//" is returned.
4457718be8SEnji Cooper  *
4557718be8SEnji Cooper  * The NetBSD implementation returns "/".
4657718be8SEnji Cooper  */
4757718be8SEnji Cooper 	{ "//",			"/" },
4857718be8SEnji Cooper 
4957718be8SEnji Cooper 	{ NULL,			NULL }
5057718be8SEnji Cooper };
5157718be8SEnji Cooper 
5257718be8SEnji Cooper struct {
5357718be8SEnji Cooper 	const char *input;
5457718be8SEnji Cooper 	const char *output;
5557718be8SEnji Cooper } test_dirname_table[] = {
5657718be8SEnji Cooper /*
5757718be8SEnji Cooper  * The following are taken from the "Sample Input and Output Strings
5857718be8SEnji Cooper  * for dirname()" table in IEEE Std 1003.1-2001.
5957718be8SEnji Cooper  */
6057718be8SEnji Cooper 	{ "/usr/lib",		"/usr" },
6157718be8SEnji Cooper 	{ "/usr/",		"/" },
6257718be8SEnji Cooper 	{ "usr",		"." },
6357718be8SEnji Cooper 	{ "/",			"/" },
6457718be8SEnji Cooper 	{ ".",			"." },
6557718be8SEnji Cooper 	{ "..",			"." },
6657718be8SEnji Cooper /*
6757718be8SEnji Cooper  * IEEE Std 1003.1-2001:
6857718be8SEnji Cooper  *
6957718be8SEnji Cooper  *	If path is a null pointer or points to an empty string,
7057718be8SEnji Cooper  *	dirname() shall return a pointer to the string "." .
7157718be8SEnji Cooper  */
7257718be8SEnji Cooper 	{ "",			"." },
7357718be8SEnji Cooper 	{ NULL,			"." },
7457718be8SEnji Cooper /*
7557718be8SEnji Cooper  * IEEE Std 1003.1-2001:
7657718be8SEnji Cooper  *
7757718be8SEnji Cooper  *	Since the meaning of the leading "//" is implementation-defined,
7857718be8SEnji Cooper  *	dirname("//foo") may return either "//" or "/" (but nothing else).
7957718be8SEnji Cooper  *
8057718be8SEnji Cooper  * The NetBSD implementation returns "/".
8157718be8SEnji Cooper  */
8257718be8SEnji Cooper 	{ "//foo",		"/" },
8357718be8SEnji Cooper /*
8457718be8SEnji Cooper  * Make sure the trailing slashes after the directory name component
8557718be8SEnji Cooper  * get trimmed.  The Std does not talk about this, but this is what
8657718be8SEnji Cooper  * Solaris 8's dirname(3) does.
8757718be8SEnji Cooper  */
8857718be8SEnji Cooper 	{ "/usr///lib",		"/usr" },
8957718be8SEnji Cooper 
9057718be8SEnji Cooper 	{ NULL,			NULL }
9157718be8SEnji Cooper };
9257718be8SEnji Cooper 
9357718be8SEnji Cooper ATF_TC(basename_posix);
ATF_TC_HEAD(basename_posix,tc)9457718be8SEnji Cooper ATF_TC_HEAD(basename_posix, tc)
9557718be8SEnji Cooper {
9657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test basename(3) with POSIX examples");
9757718be8SEnji Cooper }
9857718be8SEnji Cooper 
ATF_TC_BODY(basename_posix,tc)9957718be8SEnji Cooper ATF_TC_BODY(basename_posix, tc)
10057718be8SEnji Cooper {
10157718be8SEnji Cooper 	char testbuf[32], *base;
10257718be8SEnji Cooper 	int i;
10357718be8SEnji Cooper 
10457718be8SEnji Cooper 	for (i = 0; test_basename_table[i].output != NULL; i++) {
10557718be8SEnji Cooper 		if (test_basename_table[i].input != NULL) {
10657718be8SEnji Cooper 			if (strlen(test_basename_table[i].input) >=
10757718be8SEnji Cooper 			    sizeof(testbuf))
10857718be8SEnji Cooper 				atf_tc_skip("Testbuf too small!");
10957718be8SEnji Cooper 			strcpy(testbuf, test_basename_table[i].input);
11057718be8SEnji Cooper 			base = basename(testbuf);
11157718be8SEnji Cooper 		} else
11257718be8SEnji Cooper 			base = basename(NULL);
11357718be8SEnji Cooper 
114576a9e49SEd Schouten #ifdef __NetBSD__
11557718be8SEnji Cooper 		/*
11657718be8SEnji Cooper 		 * basename(3) is allowed to modify the input buffer.
11757718be8SEnji Cooper 		 * However, that is considered hostile by some programs,
11857718be8SEnji Cooper 		 * and so we elect to consider this an error.
11957718be8SEnji Cooper 		 *
12057718be8SEnji Cooper 		 * This is not a problem, as basename(3) is also allowed
12157718be8SEnji Cooper 		 * to return a pointer to a statically-allocated buffer
12257718be8SEnji Cooper 		 * (it is explicitly not required to be reentrant).
12357718be8SEnji Cooper 		 */
12457718be8SEnji Cooper 		if (test_basename_table[i].input != NULL &&
12557718be8SEnji Cooper 		    strcmp(test_basename_table[i].input, testbuf) != 0) {
12657718be8SEnji Cooper 			fprintf(stderr,
12757718be8SEnji Cooper 			    "Input buffer for \"%s\" was modified\n",
12857718be8SEnji Cooper 			    test_basename_table[i].input);
12957718be8SEnji Cooper 			atf_tc_fail("Input buffer was modified.");
13057718be8SEnji Cooper 		}
131576a9e49SEd Schouten #endif
13257718be8SEnji Cooper 
13357718be8SEnji Cooper 		/* Make sure the result is correct. */
13457718be8SEnji Cooper 		if (strcmp(test_basename_table[i].output, base) != 0) {
13557718be8SEnji Cooper 			fprintf(stderr,
13657718be8SEnji Cooper 			    "Input \"%s\", output \"%s\", expected \"%s\"\n",
13757718be8SEnji Cooper 			    test_basename_table[i].input ==
13857718be8SEnji Cooper 				NULL ? "(null)" : test_basename_table[i].input,
13957718be8SEnji Cooper 			    base, test_basename_table[i].output);
14057718be8SEnji Cooper 			atf_tc_fail("Output does not match expected value.");
14157718be8SEnji Cooper 		}
14257718be8SEnji Cooper 	}
14357718be8SEnji Cooper }
14457718be8SEnji Cooper 
14557718be8SEnji Cooper 
14657718be8SEnji Cooper ATF_TC(dirname_posix);
ATF_TC_HEAD(dirname_posix,tc)14757718be8SEnji Cooper ATF_TC_HEAD(dirname_posix, tc)
14857718be8SEnji Cooper {
14957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test dirname(3) with POSIX examples");
15057718be8SEnji Cooper }
15157718be8SEnji Cooper 
ATF_TC_BODY(dirname_posix,tc)15257718be8SEnji Cooper ATF_TC_BODY(dirname_posix, tc)
15357718be8SEnji Cooper {
15457718be8SEnji Cooper 	char testbuf[32], *base;
15557718be8SEnji Cooper 	int i;
15657718be8SEnji Cooper 
15757718be8SEnji Cooper 	for (i = 0; test_dirname_table[i].output != NULL; i++) {
15857718be8SEnji Cooper 		if (test_dirname_table[i].input != NULL) {
15957718be8SEnji Cooper 			if (strlen(test_dirname_table[i].input) >=
16057718be8SEnji Cooper 			    sizeof(testbuf))
16157718be8SEnji Cooper 				atf_tc_skip("Testbuf too small!");
16257718be8SEnji Cooper 			strcpy(testbuf, test_dirname_table[i].input);
16357718be8SEnji Cooper 			base = dirname(testbuf);
16457718be8SEnji Cooper 		} else
16557718be8SEnji Cooper 			base = dirname(NULL);
16657718be8SEnji Cooper 
167576a9e49SEd Schouten #ifdef __NetBSD__
16857718be8SEnji Cooper 		/*
16957718be8SEnji Cooper 		 * dirname(3) is allowed to modify the input buffer.
17057718be8SEnji Cooper 		 * However, that is considered hostile by some programs,
17157718be8SEnji Cooper 		 * and so we elect to consider this an error.
17257718be8SEnji Cooper 		 *
17357718be8SEnji Cooper 		 * This is not a problem, as dirname(3) is also allowed
17457718be8SEnji Cooper 		 * to return a pointer to a statically-allocated buffer
17557718be8SEnji Cooper 		 * (it is explicitly not required to be reentrant).
17657718be8SEnji Cooper 		 */
17757718be8SEnji Cooper 		if (test_dirname_table[i].input != NULL &&
17857718be8SEnji Cooper 		    strcmp(test_dirname_table[i].input, testbuf) != 0) {
17957718be8SEnji Cooper 			fprintf(stderr,
18057718be8SEnji Cooper 			    "Input buffer for \"%s\" was modified\n",
18157718be8SEnji Cooper 			    test_dirname_table[i].input);
18257718be8SEnji Cooper 			atf_tc_fail("Input buffer was modified.");
18357718be8SEnji Cooper 		}
184576a9e49SEd Schouten #endif
18557718be8SEnji Cooper 
18657718be8SEnji Cooper 		/* Make sure the result is correct. */
18757718be8SEnji Cooper 		if (strcmp(test_dirname_table[i].output, base) != 0) {
18857718be8SEnji Cooper 			fprintf(stderr,
18957718be8SEnji Cooper 			    "Input \"%s\", output \"%s\", expected \"%s\"\n",
19057718be8SEnji Cooper 			    test_dirname_table[i].input ==
19157718be8SEnji Cooper 				NULL ? "(null)" : test_dirname_table[i].input,
19257718be8SEnji Cooper 			    base, test_dirname_table[i].output);
19357718be8SEnji Cooper 			atf_tc_fail("Output does not match expected value.");
19457718be8SEnji Cooper 		}
19557718be8SEnji Cooper 	}
19657718be8SEnji Cooper }
19757718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)19857718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
19957718be8SEnji Cooper {
20057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, basename_posix);
20157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, dirname_posix);
20257718be8SEnji Cooper 
20357718be8SEnji Cooper 	return atf_no_error();
20457718be8SEnji Cooper }
205