Commit 269b8a1d authored by jD91mZM2's avatar jD91mZM2

Merge branch 'cleanup' into 'master'

tests: Macro based error handling

See merge request !195
parents 37c97694 fa2c6d29
Pipeline #3100 passed with stages
in 11 minutes and 15 seconds
......@@ -162,7 +162,8 @@ CFLAGS=\
-g \
-nostdinc \
-nostdlib \
-isystem ../sysroot/include
-isystem ../sysroot/include \
-I .
HEADLIBS=\
../sysroot/lib/crt0.o \
......
......@@ -2,6 +2,8 @@
#include <stdio.h>
#include <string.h>
#include "test_helpers.h"
int main(void) {
char *str = (char *) alloca(17);
......
#include <string.h>
#include <unistd.h>
#include "test_helpers.h"
int main(int argc, char *argv[]) {
int i;
for(i = 0; i < argc; i++) {
for(int i = 0; i < argc; i++) {
write(STDOUT_FILENO, argv[i], strlen(argv[i]));
write(STDOUT_FILENO, " ", 1);
}
......
......@@ -3,6 +3,8 @@
#include <string.h>
#include <stdlib.h>
#include "test_helpers.h"
int main(void) {
uint32_t hl = 0xBADFACED;
uint32_t nl = htonl(hl);
......@@ -20,5 +22,4 @@ int main(void) {
struct in_addr* addr = malloc(sizeof addr);
inet_aton(addr_str, addr);
assert(strcmp(inet_ntoa(*addr), addr_str) == 0);
}
......@@ -2,6 +2,8 @@
#include <stdlib.h>
#include <stdio.h>
#include "test_helpers.h"
int main(void) {
assert(1 == 1);
assert(1 + 1 == 2);
......
#include <stdio.h>
#include "test_helpers.h"
__attribute__((constructor))
void constructor_no_priority(void) {
......
......@@ -2,6 +2,8 @@
#include <stdio.h>
#include <stdlib.h>
#include "test_helpers.h"
struct test_case {
int c;
int isalnum;
......@@ -289,10 +291,12 @@ struct test_case {
size_t num_test_cases = sizeof(test_cases) / sizeof(struct test_case);
#define CHECK_TEST(tc, fn, retval) \
if (fn(tc.c) != tc.fn) { \
retval = EXIT_FAILURE; \
printf("Unexpected result: " #fn "('%c') != %d // Char value: %d\n", tc.c, tc.fn, tc.c); \
}
do { \
if (fn(tc.c) != tc.fn) { \
retval = EXIT_FAILURE; \
printf("Unexpected result: " #fn "('%c') != %d // Char value: %d\n", tc.c, tc.fn, tc.c); \
} \
} while (0)
int main(void) {
int retval = EXIT_SUCCESS;
......
#include <stdio.h>
#include "test_helpers.h"
__attribute__((destructor))
void destructor_no_priority(void) {
......
......@@ -3,15 +3,13 @@
#include <stdio.h>
#include <stdlib.h>
#include "test_helpers.h"
int main(void) {
printf("%lu\n", sizeof(struct dirent));
DIR* dir = opendir("example_dir/");
if (dir == NULL) {
perror("opendir");
return EXIT_FAILURE;
}
ERROR_IF(opendir, dir, == NULL);
struct dirent* entry;
......@@ -37,5 +35,7 @@ int main(void) {
// entry = readdir(dir);
// puts(entry->d_name);
closedir(dir);
int c = closedir(dir);
ERROR_IF(closedir, c, == -1);
UNEXP_IF(closedir, c, != 0);
}
......@@ -3,17 +3,18 @@
#include <stdlib.h>
#include <string.h>
#include "test_helpers.h"
int filter(const struct dirent* dirent) {
return strstr(dirent->d_name, "3") == NULL;
}
int main(void) {
struct dirent** array;
int len = scandir("example_dir/", &array, filter, alphasort);
if (len < 0) {
perror("scandir");
return EXIT_FAILURE;
}
ERROR_IF(scandir, len, == -1);
UNEXP_IF(scandir, len, < 0);
for(int i = 0; i < len; i += 1) {
puts(array[i]->d_name);
......
......@@ -3,6 +3,8 @@
#include <string.h>
#include <errno.h>
#include "test_helpers.h"
int main(void) {
chdir("nonexistent");
printf("errno: %d = %s\n", errno, strerror(errno));
......
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
......@@ -6,4 +6,3 @@
6-never-gonna-say-goodbye
7-never-gonna-tell-a-lie
8-and-hurt-you
status 0
67141780
201425341
201425341
67141780
strrch PASS, exiting with status code 0
strrch PASS
sleep: Success
usleep: Success
nanosleep: Success
......@@ -2,14 +2,17 @@
#include <stdlib.h>
#include <unistd.h>
#include "test_helpers.h"
int main(void) {
int fd = creat("create.out", 0755);
if (fd >= 0) {
write(fd, "Hello World!\n", 13);
close(fd);
return EXIT_SUCCESS;
} else {
write(STDERR_FILENO, "creat failed\n", 13);
return EXIT_FAILURE;
}
ERROR_IF(creat, fd, == -1);
UNEXP_IF(creat, fd, < 0);
int written = write(fd, "Hello World!\n", 13);
ERROR_IF(write, written, == -1);
int c = close(fd);
ERROR_IF(close, c, == -1);
UNEXP_IF(close, c, != 0);
}
......@@ -2,12 +2,30 @@
#include <stdio.h>
#include <unistd.h>
#include "test_helpers.h"
int main(void) {
//Lose our fd and pull it again
creat("fcntl.out", 0777);
// Lose our fd and pull it again
{
int fd = creat("fcntl.out", 0777);
ERROR_IF(creat, fd, == -1);
UNEXP_IF(creat, fd, < 0);
}
int newfd = open("fcntl.out", 0);
ERROR_IF(open, newfd, == -1);
UNEXP_IF(open, newfd, < 0);
int newfd2 = fcntl(newfd, F_DUPFD, 0);
// TODO: The standard doesn't define errors for F_DUPFD
printf("fd %d duped into fd %d\n", newfd, newfd2);
close(newfd);
close(newfd2);
int c1 = close(newfd);
ERROR_IF(close, c1, == -1);
UNEXP_IF(close, c1, != 0);
int c2 = close(newfd2);
ERROR_IF(close, c2, == -1);
UNEXP_IF(close, c2, != 0);
}
#include <fnmatch.h>
#include <stdio.h>
#include "test_helpers.h"
void test(char* pattern, char* input, int flags) {
if (!fnmatch(pattern, input, flags)) {
printf("\"%s\" matches \"%s\"\n", pattern, input);
......
......@@ -3,78 +3,125 @@
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char * in;
char * expected_out;
} test_case;
#include "test_helpers.h"
// 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;
}
#define TODO NULL
// 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 }
};
size_t num_test_cases = sizeof(test_cases) / sizeof(struct test_case);
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);
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);
#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) {
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("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);
printf("Failure: %d\n", retval);
}
if (!in)
free(in);
}
return;
}
int main(void) {
printf("Testing libgen.h\n");
test_basename();
test_dirname();
return retval;
}
......@@ -2,6 +2,8 @@
#include <stdio.h>
#include <string.h>
#include "test_helpers.h"
int main(void) {
// TODO: Implement locale properly and test it here
char* val = setlocale(LC_ALL, NULL);
......
#include <math.h>
#include <stdio.h>
#include "test_helpers.h"
int main(void) {
double pi = 3.14;
float c = cos(pi);
......
......@@ -8,6 +8,8 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include "test_helpers.h"
int main(void) {
struct addrinfo hints, *res;
int errcode;
......@@ -22,7 +24,7 @@ int main(void) {
errcode = getaddrinfo("www.redox-os.org", NULL, &hints, &res);
if (errcode != 0) {
perror("getaddrinfo");
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
while (res) {
......
......@@ -35,6 +35,8 @@
#include <unistd.h>
#include <errno.h>
#include "test_helpers.h"
int error_count;
static void
output_servent (const char *call, struct servent *sptr)
......
......@@ -3,6 +3,8 @@
#include <stdio.h>
#include <stdlib.h>
#include "test_helpers.h"
void print(struct passwd *pwd) {
printf("pw_name: %s\n", pwd->pw_name);
printf("pw_password: %s\n", pwd->pw_passwd);
......@@ -19,7 +21,7 @@ int main(void) {
struct passwd *pwd = getpwuid(0);
if (errno != 0) {
perror("getpwuid");
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
if (pwd != NULL) {
print(pwd);
......@@ -30,7 +32,7 @@ int main(void) {
pwd = getpwnam("nobody");
if (errno != 0) {
perror("getpwnam");
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
if (pwd != NULL) {
print(pwd);
......@@ -43,12 +45,12 @@ int main(void) {
if (getpwuid_r(0, &pwd2, buf, 100, &result) < 0) {
perror("getpwuid_r");
free(buf);
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
if (result != NULL) {
if (result != &pwd2) {
free(buf);
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
print(&pwd2);
}
......@@ -57,12 +59,12 @@ int main(void) {
if (getpwnam_r("nobody", &pwd2, buf, 100, &result) < 0) {
perror("getpwuid_r");
free(buf);
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
if (result != NULL) {
if (result != &pwd2) {
free(buf);
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
print(&pwd2);
}
......@@ -72,11 +74,11 @@ int main(void) {
char buf2[1];
if (getpwuid_r(0, &pwd2, buf2, 1, &result) == 0) {
puts("This shouldn't have succeeded, but did!");
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
if (errno != ERANGE) {
perror("getpwuid_r");
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
puts("Returned ERANGE because the buffer was too small 👍");
}
......@@ -2,6 +2,8 @@
#include <stdio.h>
#include <stdlib.h>
#include "test_helpers.h"
int main(void) {
regex_t regex;
char error_buf[256];
......@@ -11,7 +13,7 @@ int main(void) {
regerror(error, &regex, error_buf, 255);
error_buf[255] = 0;
printf("regcomp error: %d = %s\n", error, error_buf);
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
regmatch_t matches[3] = {{0}};
......@@ -23,7 +25,7 @@ int main(void) {
if (error) {
regerror(error, &regex, error_buf, 255);
printf("regexec error: %d = %s\n", error, error_buf);
return EXIT_FAILURE;
exit(EXIT_FAILURE);
}
for (int group = 0; group < 3; group += 1) {
......
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include "test_helpers.h"
void ptimeval(struct timeval* val) {
printf("{ tv_sec: %ld, tv_usec: %ld }\n", val->tv_sec, val->tv_usec);
}
int main(void) {
struct rusage r_usage;
if (getrusage(RUSAGE_SELF, &r_usage) < 0) {
perror("getrusage");
return EXIT_FAILURE;
}
int status = getrusage(RUSAGE_SELF, &r_usage);
ERROR_IF(getrusage, status, == -1);
UNEXP_IF(getrusage, status, != 0);
printf("ru_utime:");
ptimeval(&r_usage.ru_utime);
printf("ru_stime:");
ptimeval(&r_usage.ru_utime);
printf("ru_maxrss: %ld\n", r_usage.ru_maxrss);
printf("ru_ixrss: %ld\n", r_usage.ru_ixrss);
printf("ru_idrss: %ld\n", r_usage.ru_idrss);
......
......@@ -3,6 +3,8 @@
#include <sys/select.h>
#include <unistd.h>
#include "test_helpers.h"
int main(void) {
int fd = open("select.c", 0, 0);
......
#include <stdio.h>
#include <setjmp.h>
#include "test_helpers.h"
int main(void) {
jmp_buf buf;
if (setjmp(buf)) {
......