tests: Rewrite libgen tests based on ctype (nice table layout), fix error handling of sleep tests
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
Testing libgen.h
|
||||
OK on basename(/usr/lib), expected: 'lib', got: 'lib'
|
||||
OK on basename(//usr//lib//), expected: 'lib', got: 'lib'
|
||||
OK on basename(/usr/), expected: 'usr', got: 'usr'
|
||||
OK on basename(), expected: '.', got: '.'
|
||||
OK on basename(/), expected: '/', got: '/'
|
||||
OK on basename(///), expected: '/', got: '/'
|
||||
OK on basename(NULL), expected: '.', got: '.'
|
||||
OK on dirname(/usr/lib), expected: '/usr', got: '/usr'
|
||||
OK on dirname(//usr//lib//), expected: '//usr', got: '//usr'
|
||||
OK on dirname(/usr), expected: '/', got: '/'
|
||||
OK on dirname(usr), expected: '.', got: '.'
|
||||
OK on dirname(/), expected: '/', got: '/'
|
||||
OK on dirname(///), expected: '/', got: '/'
|
||||
OK on dirname(.), expected: '.', got: '.'
|
||||
OK on dirname(..), expected: '.', got: '.'
|
||||
OK on dirname(), expected: '.', got: '.'
|
||||
OK on dirname(NULL), expected: '.', got: '.'
|
||||
dirname("") == "."
|
||||
basename("") == "."
|
||||
dirname(".") == "."
|
||||
basename(".") == "."
|
||||
dirname("..") == "."
|
||||
basename("..") == ".."
|
||||
dirname("/") == "/"
|
||||
basename("/") == "/"
|
||||
dirname("///") == "/"
|
||||
basename("///") == "/"
|
||||
dirname("//usr//lib//") == "//usr"
|
||||
basename("//usr//lib//") == "lib"
|
||||
dirname("/usr") == "/"
|
||||
basename("/usr") == "usr"
|
||||
dirname("/usr/") == "/"
|
||||
basename("/usr/") == "usr"
|
||||
dirname("/usr/lib") == "/usr"
|
||||
basename("/usr/lib") == "lib"
|
||||
dirname(NULL) == "."
|
||||
basename(NULL) == "."
|
||||
Success: 0
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
sleep: Success
|
||||
usleep: Success
|
||||
nanosleep: Success
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
unslept: 0
|
||||
|
||||
+111
-66
@@ -5,78 +5,123 @@
|
||||
|
||||
#include "test_helpers.h"
|
||||
|
||||
typedef struct {
|
||||
char * in;
|
||||
char * expected_out;
|
||||
} test_case;
|
||||
#define TODO NULL
|
||||
|
||||
// API for basename and dirname allow the passed in string to
|
||||
// be modified. This means we have to pass a modifiable copy.
|
||||
char * get_mutable_string(char *str) {
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
char * copy = malloc(sizeof(char) * (strlen(str) + 1));
|
||||
copy = strcpy(copy, str);
|
||||
return copy;
|
||||
}
|
||||
// TODO: Tests for Redox schemes
|
||||
struct test_case {
|
||||
char *path;
|
||||
char *dirname;
|
||||
char *basename;
|
||||
} test_cases[] = {
|
||||
// Classic UNIX
|
||||
// path dirname basename
|
||||
{ "", ".", "." },
|
||||
{ ".", ".", "." },
|
||||
{ "..", ".", ".." },
|
||||
{ "/", "/", "/" },
|
||||
{ "///", "/", "/" },
|
||||
{ "//usr//lib//", "//usr", "lib" },
|
||||
{ "/usr", "/", "usr" },
|
||||
{ "/usr/", "/", "usr" },
|
||||
{ "/usr/lib", "/usr", "lib" },
|
||||
{ NULL, ".", "." }
|
||||
// Root scheme
|
||||
// path dirname basename
|
||||
//{ ":", TODO, TODO },
|
||||
//{ ":/", TODO, TODO },
|
||||
//{ ":/scheme", TODO, TODO },
|
||||
// Regular scheme
|
||||
// path dirname basename
|
||||
//{ "file:", TODO, TODO },
|
||||
//{ "file:usr", TODO, TODO },
|
||||
//{ "file:usr/", TODO, TODO },
|
||||
//{ "file:usr/lib", TODO, TODO },
|
||||
//{ "file:/", TODO, TODO },
|
||||
//{ "file:/usr", TODO, TODO },
|
||||
//{ "file:/usr/", TODO, TODO },
|
||||
//{ "file:/usr/lib", TODO, TODO },
|
||||
//{ "file:///", TODO, TODO },
|
||||
//{ "file://usr", TODO, TODO },
|
||||
//{ "file://usr//", TODO, TODO },
|
||||
// Hierarchical scheme
|
||||
// path dirname basename
|
||||
//{ "disk/0:", TODO, TODO },
|
||||
//{ "disk/0:/", TODO, TODO },
|
||||
//{ "disk/0:///", TODO, TODO },
|
||||
//{ "disk/0:/usr", TODO, TODO },
|
||||
//{ "disk/0:/usr/", TODO, TODO },
|
||||
//{ "disk/0:/usr/lib", TODO, TODO },
|
||||
// Malformed
|
||||
// path dirname basename
|
||||
//{ "/file:/sys:/usr", TODO, TODO },
|
||||
//{ "/file:/usr", TODO, TODO },
|
||||
//{ "/file:sys:/usr", TODO, TODO },
|
||||
//{ "/file:usr", TODO, TODO },
|
||||
//{ ":file/usr", TODO, TODO },
|
||||
//{ "file:/sys:/usr", TODO, TODO },
|
||||
//{ "file::/", TODO, TODO },
|
||||
//{ "file::/usr/lib", TODO, TODO }
|
||||
};
|
||||
|
||||
void test_basename(void) {
|
||||
test_case test_cases[] =
|
||||
{ {"/usr/lib", "lib"},
|
||||
{"//usr//lib//", "lib"},
|
||||
{"/usr/", "usr"},
|
||||
{"", "."},
|
||||
{"/", "/"},
|
||||
{"///","/"},
|
||||
{NULL, "."}
|
||||
};
|
||||
for (int i = 0;i < sizeof(test_cases)/sizeof(test_case);i++) {
|
||||
char * in = get_mutable_string(test_cases[i].in);
|
||||
char * out = basename(in);
|
||||
if (!out) {
|
||||
printf("Error on basename(%s), expected: '%s', got NULL\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out);
|
||||
} else if (strcmp(out, test_cases[i].expected_out) != 0) {
|
||||
printf("Error on basename(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
size_t num_test_cases = sizeof(test_cases) / sizeof(struct test_case);
|
||||
|
||||
int safe_strcmp(char *s1, char *s2) {
|
||||
if (s1 == NULL && s2 == NULL) {
|
||||
return 0;
|
||||
} else if (s1 == NULL && s2 != NULL) {
|
||||
return 1;
|
||||
} else if (s1 != NULL && s2 == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
printf("OK on basename(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
if (!in)
|
||||
free(in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void test_dirname(void) {
|
||||
test_case test_cases[] =
|
||||
{ {"/usr/lib", "/usr"},
|
||||
{"//usr//lib//", "//usr"},
|
||||
{"/usr", "/"},
|
||||
{"usr", "."},
|
||||
{"/", "/"},
|
||||
{"///","/"},
|
||||
{".", "."},
|
||||
{"..", "."},
|
||||
{"", "."},
|
||||
{NULL, "."}
|
||||
};
|
||||
for (int i = 0;i < sizeof(test_cases)/sizeof(test_case);i++) {
|
||||
char * in = get_mutable_string(test_cases[i].in);
|
||||
char * out = dirname(in);
|
||||
if (!out) {
|
||||
printf("Error on dirname(%s), expected: '%s', got NULL\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out);
|
||||
} else if (strcmp(out, test_cases[i].expected_out) != 0) {
|
||||
printf("Error on dirname(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
} else {
|
||||
printf("OK on dirname(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
}
|
||||
if (!in)
|
||||
free(in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#define CHECK_TEST(tc, fn, retval) \
|
||||
do { \
|
||||
/* API for basename and dirname allow the passed in string to */ \
|
||||
/* be modified. This means we have to pass a modifiable copy. */ \
|
||||
char *path = NULL; \
|
||||
if (tc.path != NULL) \
|
||||
path = strdup(tc.path); \
|
||||
\
|
||||
char *output = fn(path); \
|
||||
\
|
||||
/* Printing NULLs with printf("%s") is undefined behaviour, */ \
|
||||
/* that's why they are handled here this way. */ \
|
||||
char display_path[64] = "NULL"; \
|
||||
char display_output[64] = "NULL"; \
|
||||
char display_expected[64] = "NULL"; \
|
||||
if (tc.path != NULL) sprintf(display_path, "\"%s\"", tc.path); \
|
||||
if (output != NULL) sprintf(display_output, "\"%s\"", output); \
|
||||
if (tc.fn != NULL) sprintf(display_expected, "\"%s\"", tc.fn); \
|
||||
\
|
||||
if (safe_strcmp(output, tc.fn) != 0) { \
|
||||
retval = EXIT_FAILURE; \
|
||||
printf("%s(%s) != %s, expected: %s\n", \
|
||||
#fn, display_path, display_output, display_expected); \
|
||||
} else { \
|
||||
printf("%s(%s) == %s\n", \
|
||||
#fn, display_path, display_output); \
|
||||
} \
|
||||
\
|
||||
free(path); \
|
||||
} while (0)
|
||||
|
||||
int main(void) {
|
||||
printf("Testing libgen.h\n");
|
||||
test_basename();
|
||||
test_dirname();
|
||||
int retval = EXIT_SUCCESS;
|
||||
|
||||
for(int i = 0; i < num_test_cases; ++i) {
|
||||
struct test_case tc = test_cases[i];
|
||||
CHECK_TEST(tc, dirname, retval);
|
||||
CHECK_TEST(tc, basename, retval);
|
||||
}
|
||||
|
||||
if (retval == EXIT_SUCCESS) {
|
||||
printf("Success: %d\n", retval);
|
||||
} else {
|
||||
printf("Failure: %d\n", retval);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
+11
-6
@@ -5,11 +5,16 @@
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main(void) {
|
||||
sleep(2);
|
||||
perror("sleep");
|
||||
usleep(1000);
|
||||
perror("usleep");
|
||||
// sleep has no error codes and doesn't set errno
|
||||
unsigned int unslept = sleep(2);
|
||||
printf("unslept: %u\n", unslept);
|
||||
|
||||
int us_status = usleep(1000);
|
||||
ERROR_IF(usleep, us_status, == -1);
|
||||
UNEXP_IF(usleep, us_status, != 0);
|
||||
|
||||
struct timespec tm = {0, 10000};
|
||||
nanosleep(&tm, NULL);
|
||||
perror("nanosleep");
|
||||
int ns_status = nanosleep(&tm, NULL);
|
||||
ERROR_IF(nanosleep, ns_status, == -1);
|
||||
UNEXP_IF(nanosleep, ns_status, != 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user