blob: 3381f48abc2650edf55362bd5e75016ab072085a [file] [log] [blame]
/* Test the gnulib dirname module.
Copyright (C) 2005-2007, 2009-2020 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct test {
const char *name; /* Name under test. */
const char *dir; /* dir_name (name). */
const char *last; /* last_component (name). */
const char *base; /* base_name (name). */
const char *stripped; /* name after strip_trailing_slashes (name). */
bool modified; /* result of strip_trailing_slashes (name). */
bool absolute; /* IS_ABSOLUTE_FILE_NAME (name). */
};
static struct test tests[] = {
{"d/f", "d", "f", "f", "d/f", false, false},
{"/d/f", "/d", "f", "f", "/d/f", false, true},
{"d/f/", "d", "f/", "f/", "d/f", true, false},
{"d/f//", "d", "f//", "f/", "d/f", true, false},
{"f", ".", "f", "f", "f", false, false},
{"/", "/", "", "/", "/", false, true},
#if DOUBLE_SLASH_IS_DISTINCT_ROOT
{"//", "//", "", "//", "//", false, true},
{"//d", "//", "d", "d", "//d", false, true},
#else
{"//", "/", "", "/", "/", true, true},
{"//d", "/", "d", "d", "//d", false, true},
#endif
{"///", "/", "", "/", "/", true, true},
{"///a///", "/", "a///", "a/", "///a", true, true},
/* POSIX requires dirname("") and basename("") to both return ".",
but dir_name and base_name are defined differently. */
{"", ".", "", "", "", false, false},
{".", ".", ".", ".", ".", false, false},
{"..", ".", "..", "..", "..", false, false},
#if ISSLASH ('\\')
{"a\\", ".", "a\\", "a\\", "a", true, false},
{"a\\b", "a", "b", "b", "a\\b", false, false},
{"\\", "\\", "", "\\", "\\", false, true},
{"\\/\\", "\\", "", "\\", "\\", true, true},
{"\\\\/", "\\", "", "\\", "\\", true, true},
{"\\//", "\\", "", "\\", "\\", true, true},
{"//\\", "/", "", "/", "/", true, true},
#else
{"a\\", ".", "a\\", "a\\", "a\\", false, false},
{"a\\b", ".", "a\\b", "a\\b", "a\\b", false, false},
{"\\", ".", "\\", "\\", "\\", false, false},
{"\\/\\", "\\", "\\", "\\", "\\/\\",false, false},
{"\\\\/", ".", "\\\\/","\\\\/","\\\\", true, false},
{"\\//", ".", "\\//", "\\/", "\\", true, false},
# if DOUBLE_SLASH_IS_DISTINCT_ROOT
{"//\\", "//", "\\", "\\", "//\\", false, true},
# else
{"//\\", "/", "\\", "\\", "//\\", false, true},
# endif
#endif
#if ISSLASH ('\\')
# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
{"c:", "c:", "", "c:", "c:", false, false},
{"c:/", "c:/", "", "c:/", "c:/", false, true},
{"c://", "c:/", "", "c:/", "c:/", true, true},
{"c:/d", "c:/", "d", "d", "c:/d", false, true},
{"c://d", "c:/", "d", "d", "c://d",false, true},
{"c:/d/", "c:/", "d/", "d/", "c:/d", true, true},
{"c:/d/f", "c:/d", "f", "f", "c:/d/f",false, true},
{"c:d", "c:.", "d", "d", "c:d", false, false},
{"c:d/", "c:.", "d/", "d/", "c:d", true, false},
{"c:d/f", "c:d", "f", "f", "c:d/f",false, false},
{"a:b:c", "a:.", "b:c", "./b:c","a:b:c",false, false},
{"a/b:c", "a", "b:c", "./b:c","a/b:c",false, false},
{"a/b:c/", "a", "b:c/", "./b:c/","a/b:c",true, false},
# else /* ! FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE */
{"c:", "c:", "", "c:", "c:", false, true},
{"c:/", "c:", "", "c:", "c:", true, true},
{"c://", "c:", "", "c:", "c:", true, true},
{"c:/d", "c:", "d", "d", "c:/d", false, true},
{"c://d", "c:", "d", "d", "c://d",false, true},
{"c:/d/", "c:", "d/", "d/", "c:/d", true, true},
{"c:/d/f", "c:/d", "f", "f", "c:/d/f",false, true},
{"c:d", "c:", "d", "d", "c:d", false, true},
{"c:d/", "c:", "d/", "d/", "c:d", true, true},
{"c:d/f", "c:d", "f", "f", "c:d/f",false, true},
{"a:b:c", "a:", "b:c", "./b:c","a:b:c",false, true},
{"a/b:c", "a", "b:c", "./b:c","a/b:c",false, false},
{"a/b:c/", "a", "b:c/", "./b:c/","a/b:c",true, false},
# endif
#else /* ! ISSLASH ('\\') */
{"c:", ".", "c:", "c:", "c:", false, false},
{"c:/", ".", "c:/", "c:/", "c:", true, false},
{"c://", ".", "c://", "c:/", "c:", true, false},
{"c:/d", "c:", "d", "d", "c:/d", false, false},
{"c://d", "c:", "d", "d", "c://d",false, false},
{"c:/d/", "c:", "d/", "d/", "c:/d", true, false},
{"c:/d/f", "c:/d", "f", "f", "c:/d/f",false, false},
{"c:d", ".", "c:d", "c:d", "c:d", false, false},
{"c:d/", ".", "c:d/", "c:d/", "c:d", true, false},
{"c:d/f", "c:d", "f", "f", "c:d/f",false, false},
{"a:b:c", ".", "a:b:c","a:b:c","a:b:c",false, false},
{"a/b:c", "a", "b:c", "b:c", "a/b:c",false, false},
{"a/b:c/", "a", "b:c/", "b:c/", "a/b:c",true, false},
#endif
{"1:", ".", "1:", "1:", "1:", false, false},
{"1:/", ".", "1:/", "1:/", "1:", true, false},
{"/:", "/", ":", ":", "/:", false, true},
{"/:/", "/", ":/", ":/", "/:", true, true},
/* End sentinel. */
{NULL, NULL, NULL, NULL, NULL, false, false}
};
int
main (void)
{
struct test *t;
bool ok = true;
for (t = tests; t->name; t++)
{
char *dir = dir_name (t->name);
int dirlen = dir_len (t->name);
char *last = last_component (t->name);
char *base = base_name (t->name);
int baselen = base_len (base);
char *stripped = strdup (t->name);
bool modified = strip_trailing_slashes (stripped);
bool absolute = IS_ABSOLUTE_FILE_NAME (t->name);
if (! (strcmp (dir, t->dir) == 0
&& (dirlen == strlen (dir)
|| (dirlen + 1 == strlen (dir) && dir[dirlen] == '.'))))
{
ok = false;
printf ("dir_name '%s': got '%s' len %d,"
" expected '%s' len %lu\n",
t->name, dir, dirlen,
t->dir, (unsigned long) strlen (t->dir));
}
if (strcmp (last, t->last))
{
ok = false;
printf ("last_component '%s': got '%s', expected '%s'\n",
t->name, last, t->last);
}
if (! (strcmp (base, t->base) == 0
&& (baselen == strlen (base)
|| (baselen + 1 == strlen (base)
&& ISSLASH (base[baselen])))))
{
ok = false;
printf ("base_name '%s': got '%s' len %d,"
" expected '%s' len %lu\n",
t->name, base, baselen,
t->base, (unsigned long) strlen (t->base));
}
if (strcmp (stripped, t->stripped) || modified != t->modified)
{
ok = false;
printf ("strip_trailing_slashes '%s': got %s %s, expected %s %s\n",
t->name, stripped, modified ? "changed" : "unchanged",
t->stripped, t->modified ? "changed" : "unchanged");
}
if (t->absolute != absolute)
{
ok = false;
printf ("'%s': got %s, expected %s\n", t->name,
absolute ? "absolute" : "relative",
t->absolute ? "absolute" : "relative");
}
free (dir);
free (base);
free (stripped);
}
return ok ? 0 : 1;
}