Browse Source

Merge branch 'cleanup' into 'master'

tests: Macro based error handling

See merge request redox-os/relibc!195
jD91mZM2 6 years ago
parent
commit
269b8a1d3e
100 changed files with 830 additions and 402 deletions
  1. 2 1
      tests/Makefile
  2. 2 0
      tests/alloca.c
  3. 3 2
      tests/args.c
  4. 2 1
      tests/arpainet.c
  5. 2 0
      tests/assert.c
  6. 1 0
      tests/constructor.c
  7. 8 4
      tests/ctype.c
  8. 1 0
      tests/destructor.c
  9. 6 6
      tests/dirent/main.c
  10. 5 4
      tests/dirent/scandir.c
  11. 2 0
      tests/error.c
  12. 21 18
      tests/expected/libgen.stdout
  13. 1 1
      tests/expected/stdio/all.stdout
  14. 1 1
      tests/expected/stdio/fseek.stdout
  15. 0 1
      tests/expected/stdio/popen.stdout
  16. 2 0
      tests/expected/stdlib/rand.stdout
  17. 1 1
      tests/expected/string/strrchr.stdout
  18. 0 1
      tests/expected/unistd/brk.stdout
  19. 0 1
      tests/expected/unistd/fchdir.stdout
  20. 0 1
      tests/expected/unistd/fsync.stdout
  21. 0 1
      tests/expected/unistd/ftruncate.stdout
  22. 0 1
      tests/expected/unistd/rmdir.stdout
  23. 0 3
      tests/expected/unistd/sleep.stderr
  24. 1 0
      tests/expected/unistd/sleep.stdout
  25. 11 8
      tests/fcntl/create.c
  26. 22 4
      tests/fcntl/fcntl.c
  27. 2 0
      tests/fnmatch.c
  28. 112 65
      tests/libgen.c
  29. 2 0
      tests/locale.c
  30. 2 0
      tests/math.c
  31. 3 1
      tests/netdb/getaddrinfo.c
  32. 2 0
      tests/netdb/netdb.c
  33. 10 8
      tests/pwd.c
  34. 4 2
      tests/regex.c
  35. 10 4
      tests/resource/getrusage.c
  36. 2 0
      tests/select.c
  37. 2 0
      tests/setjmp.c
  38. 8 10
      tests/signal.c
  39. 24 7
      tests/stdio/all.c
  40. 2 0
      tests/stdio/buffer.c
  41. 5 2
      tests/stdio/fgets.c
  42. 14 4
      tests/stdio/fputs.c
  43. 4 1
      tests/stdio/fread.c
  44. 8 4
      tests/stdio/freopen.c
  45. 13 6
      tests/stdio/fseek.c
  46. 17 13
      tests/stdio/fwrite.c
  47. 4 2
      tests/stdio/getc_unget.c
  48. 7 4
      tests/stdio/mutex.c
  49. 7 18
      tests/stdio/popen.c
  50. 2 0
      tests/stdio/printf.c
  51. 41 13
      tests/stdio/rename.c
  52. 2 0
      tests/stdio/scanf.c
  53. 2 0
      tests/stdio/setvbuf.c
  54. 4 2
      tests/stdio/sprintf.c
  55. 4 2
      tests/stdlib/a64l.c
  56. 2 0
      tests/stdlib/alloc.c
  57. 2 0
      tests/stdlib/atof.c
  58. 2 0
      tests/stdlib/atoi.c
  59. 46 46
      tests/stdlib/bsearch.c
  60. 18 15
      tests/stdlib/div.c
  61. 3 1
      tests/stdlib/env.c
  62. 2 0
      tests/stdlib/mkostemps.c
  63. 2 0
      tests/stdlib/mktemp.c
  64. 28 2
      tests/stdlib/rand.c
  65. 11 20
      tests/stdlib/realpath.c
  66. 2 0
      tests/stdlib/strtod.c
  67. 2 0
      tests/stdlib/strtol.c
  68. 2 0
      tests/stdlib/strtoul.c
  69. 4 1
      tests/stdlib/system.c
  70. 8 6
      tests/string/mem.c
  71. 2 0
      tests/string/strcat.c
  72. 2 0
      tests/string/strchr.c
  73. 2 0
      tests/string/strcpy.c
  74. 2 0
      tests/string/strcspn.c
  75. 2 0
      tests/string/strncmp.c
  76. 2 0
      tests/string/strpbrk.c
  77. 19 15
      tests/string/strrchr.c
  78. 2 0
      tests/string/strspn.c
  79. 2 0
      tests/string/strstr.c
  80. 2 0
      tests/string/strtok.c
  81. 2 0
      tests/string/strtok_r.c
  82. 2 0
      tests/strings.c
  83. 10 10
      tests/sys_utsname/uname.c
  84. 91 0
      tests/test_helpers.h
  85. 3 1
      tests/time/asctime.c
  86. 7 1
      tests/time/gettimeofday.c
  87. 3 9
      tests/time/gmtime.c
  88. 2 0
      tests/time/localtime.c
  89. 2 0
      tests/time/macros.c
  90. 18 7
      tests/time/mktime.c
  91. 2 0
      tests/time/strftime.c
  92. 5 12
      tests/time/time.c
  93. 5 1
      tests/time/times.c
  94. 4 2
      tests/unistd/access.c
  95. 5 1
      tests/unistd/brk.c
  96. 21 9
      tests/unistd/chdir.c
  97. 32 5
      tests/unistd/dup.c
  98. 6 2
      tests/unistd/exec.c
  99. 13 4
      tests/unistd/fchdir.c
  100. 13 4
      tests/unistd/fsync.c

+ 2 - 1
tests/Makefile

@@ -162,7 +162,8 @@ CFLAGS=\
 	-g \
 	-nostdinc \
 	-nostdlib \
-	-isystem ../sysroot/include
+	-isystem ../sysroot/include \
+	-I .
 
 HEADLIBS=\
 	../sysroot/lib/crt0.o \

+ 2 - 0
tests/alloca.c

@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char *str = (char *) alloca(17);
 

+ 3 - 2
tests/args.c

@@ -1,9 +1,10 @@
 #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);
     }

+ 2 - 1
tests/arpainet.c

@@ -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 - 0
tests/assert.c

@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     assert(1 == 1);
     assert(1 + 1 == 2);

+ 1 - 0
tests/constructor.c

@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include "test_helpers.h"
 
 __attribute__((constructor))
 void constructor_no_priority(void) {

+ 8 - 4
tests/ctype.c

@@ -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;

+ 1 - 0
tests/destructor.c

@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include "test_helpers.h"
 
 __attribute__((destructor))
 void destructor_no_priority(void) {

+ 6 - 6
tests/dirent/main.c

@@ -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);
 }

+ 5 - 4
tests/dirent/scandir.c

@@ -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);

+ 2 - 0
tests/error.c

@@ -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));

+ 21 - 18
tests/expected/libgen.stdout

@@ -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 - 1
tests/expected/stdio/all.stdout

@@ -1,4 +1,4 @@
 H
-Hello World!
+Jello World!
 
 Hello

+ 1 - 1
tests/expected/stdio/fseek.stdout

@@ -1,2 +1,2 @@
 Line 2
-ftell: 21
+ftello: 21

+ 0 - 1
tests/expected/stdio/popen.stdout

@@ -6,4 +6,3 @@
 6-never-gonna-say-goodbye
 7-never-gonna-tell-a-lie
 8-and-hurt-you
-status 0

+ 2 - 0
tests/expected/stdlib/rand.stdout

@@ -1,2 +1,4 @@
 67141780
 201425341
+201425341
+67141780

+ 1 - 1
tests/expected/string/strrchr.stdout

@@ -1 +1 @@
-strrch PASS, exiting with status code 0
+strrch PASS

+ 0 - 1
tests/expected/unistd/brk.stdout

@@ -1 +0,0 @@
-brk exited with status code 0

+ 0 - 1
tests/expected/unistd/fchdir.stdout

@@ -1 +0,0 @@
-fchdir exited with status code 0

+ 0 - 1
tests/expected/unistd/fsync.stdout

@@ -1 +0,0 @@
-fsync exited with status code 0

+ 0 - 1
tests/expected/unistd/ftruncate.stdout

@@ -1 +0,0 @@
-ftruncate exited with status code 0

+ 0 - 1
tests/expected/unistd/rmdir.stdout

@@ -1 +0,0 @@
-rmdir exited with status code 0

+ 0 - 3
tests/expected/unistd/sleep.stderr

@@ -1,3 +0,0 @@
-sleep: Success
-usleep: Success
-nanosleep: Success

+ 1 - 0
tests/expected/unistd/sleep.stdout

@@ -0,0 +1 @@
+unslept: 0

+ 11 - 8
tests/fcntl/create.c

@@ -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);
 }

+ 22 - 4
tests/fcntl/fcntl.c

@@ -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);
 }

+ 2 - 0
tests/fnmatch.c

@@ -1,6 +1,8 @@
 #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);

+ 112 - 65
tests/libgen.c

@@ -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 - 0
tests/locale.c

@@ -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);

+ 2 - 0
tests/math.c

@@ -1,6 +1,8 @@
 #include <math.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     double pi = 3.14;
     float c = cos(pi);

+ 3 - 1
tests/netdb/getaddrinfo.c

@@ -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) {

+ 2 - 0
tests/netdb/netdb.c

@@ -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)

+ 10 - 8
tests/pwd.c

@@ -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 👍");
 }

+ 4 - 2
tests/regex.c

@@ -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) {

+ 10 - 4
tests/resource/getrusage.c

@@ -1,21 +1,27 @@
 #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);

+ 2 - 0
tests/select.c

@@ -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);
 

+ 2 - 0
tests/setjmp.c

@@ -1,6 +1,8 @@
 #include <stdio.h>
 #include <setjmp.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     jmp_buf buf;
     if (setjmp(buf)) {

+ 8 - 10
tests/signal.c

@@ -4,22 +4,20 @@
 #include <unistd.h>
 #include <errno.h>
 
+#include "test_helpers.h"
+
 void handler(int sig) {
     puts("Signal handler called!");
 }
 
 int main(void) {
-    if (signal(SIGUSR1, &handler) == SIG_ERR) {
-        puts("Signal error!");
-        printf("%d\n", errno);
-        return EXIT_FAILURE;
-    }
+    void (*signal_status)(int) = signal(SIGUSR1, &handler);
+    ERROR_IF(signal, signal_status, == SIG_ERR);
 
     puts("Raising...");
-    if (raise(SIGUSR1)) {
-        puts("Raise error!");
-        printf("%d\n", errno);
-        return EXIT_FAILURE;
-    }
+
+    int raise_status = raise(SIGUSR1);
+    ERROR_IF(raise, raise_status, < 0);
+
     puts("Raised.");
 }

+ 24 - 7
tests/stdio/all.c

@@ -1,12 +1,29 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-	FILE *f = fopen("stdio/stdio.in", "r");
-	printf("%c\n", fgetc(f));
-	ungetc('H', f);
-	char *in = malloc(30);
-	printf("%s\n", fgets(in, 30, f));
-	setvbuf(stdout, 0, _IONBF, 0);
-	printf("Hello\n");
+    FILE *f = fopen("stdio/stdio.in", "r");
+    ERROR_IF(fopen, f, == NULL);
+
+    int c = fgetc(f);
+    ERROR_IF(fgetc, c, == EOF);
+    UNEXP_IF(fgetc, c, < 0);
+    UNEXP_IF(fgetc, c, > 255);
+    printf("%c\n", c);
+
+    int u = ungetc('J', f);
+    ERROR_IF(ungetc, u, == EOF);
+
+    char in[30] = { 0 };
+    char *s = fgets(in, 30, f);
+    ERROR_IF(fgets, s, == NULL);
+    printf("%s\n", in);
+
+    int vb = setvbuf(stdout, 0, _IONBF, 0);
+    //ERROR_IF(setvbuf, vb, > 0); // TODO: Cannot use this, doesn't set errno
+    //UNEXP_IF(setvbuf, vb, != 0);
+
+    printf("Hello\n");
 }

+ 2 - 0
tests/stdio/buffer.c

@@ -1,5 +1,7 @@
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     // Tests what used to be a bug with buffering
     fwrite("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 1, 999, stdout);

+ 5 - 2
tests/stdio/fgets.c

@@ -1,9 +1,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-    //FILE *f = fopen("/etc/ssl/certs/ca-certificates.crt", "r");
     FILE *f = fopen("stdio/stdio.in", "r");
+    ERROR_IF(fopen, f, == NULL);
+
     char line[256];
 
     while (1) {
@@ -13,7 +16,7 @@ int main(void) {
             puts("EOF");
             if (!feof(f)) {
                 puts("feof() not updated!");
-                return EXIT_FAILURE;
+                exit(EXIT_FAILURE);
             }
             break;
         }

+ 14 - 4
tests/stdio/fputs.c

@@ -1,9 +1,19 @@
 #include <stdio.h>
 #include <errno.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-	FILE *f = fopen("stdio/fputs.out", "w");
-	char *in = "Hello World!";
-	fputs(in, f); // calls fwrite, helpers::fwritex, internal::to_write and internal::stdio_write
-	fclose(f);
+    FILE *f = fopen("stdio/fputs.out", "w");
+    ERROR_IF(fopen, f, == NULL);
+
+    char *in = "Hello World!";
+
+    int p = fputs(in, f);
+    ERROR_IF(fputs, p, == EOF);
+    UNEXP_IF(fputs, p, < 0);
+
+    int c = fclose(f);
+    ERROR_IF(fclose, c, == EOF);
+    UNEXP_IF(fclose, c, != 0);
 }

+ 4 - 1
tests/stdio/fread.c

@@ -2,14 +2,17 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     FILE *fp = fopen("stdio/fread.in", "rb");
+    ERROR_IF(fopen, fp, == NULL);
 
     char buf[33] = { 0 };
     for (int i = 1; i <= 32; ++i) {
         if (fread(buf, 1, i, fp) < 0) {
             perror("fread");
-            return EXIT_FAILURE;
+            exit(EXIT_FAILURE);
         }
         buf[i] = 0;
 

+ 8 - 4
tests/stdio/freopen.c

@@ -1,8 +1,12 @@
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-	freopen("stdio/stdio.in", "r", stdin);
-	char in[6];
-	fgets(in, 6, stdin);
-	printf("%s\n", in); // should print Hello
+    FILE *f = freopen("stdio/stdio.in", "r", stdin);
+    ERROR_IF(freopen, f, == NULL);
+
+    char in[6];
+    fgets(in, 6, stdin);
+    printf("%s\n", in); // should print Hello
 }

+ 13 - 6
tests/stdio/fseek.c

@@ -1,13 +1,20 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-	FILE *f = fopen("stdio/stdio.in", "r");
-    if (fseek(f, 14, SEEK_CUR) < 0) {
-        puts("fseek error");
-        return EXIT_FAILURE;
-    }
+    FILE *f = fopen("stdio/stdio.in", "r");
+    ERROR_IF(fopen, f, == NULL);
+
+    int status = fseek(f, 14, SEEK_CUR);
+    ERROR_IF(fseek, status, == -1);
+    UNEXP_IF(fseek, status, != 0);
+
     char buffer[256];
     printf("%s", fgets(buffer, 256, f));
-    printf("ftell: %ld\n", ftello(f));
+
+    off_t pos = ftello(f);
+    ERROR_IF(ftello, pos, == -1);
+    printf("ftello: %ld\n", pos);
 }

+ 17 - 13
tests/stdio/fwrite.c

@@ -2,22 +2,26 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-	FILE *f = fopen("stdio/fwrite.out", "w");
-	const char ptr[] = "Hello World!";
+    FILE *f = fopen("stdio/fwrite.out", "w");
+    ERROR_IF(fopen, f, == NULL);
+
+    const char ptr[] = "Hello World!";
 
-	if (fwrite(ptr, 0, 17, f)) {
-		return EXIT_FAILURE;
-	}
+    if (fwrite(ptr, 0, 17, f)) {
+        exit(EXIT_FAILURE);
+    }
 
-	if (fwrite(ptr, 7, 0, f)) {
-		return EXIT_FAILURE;
-	}
+    if (fwrite(ptr, 7, 0, f)) {
+        exit(EXIT_FAILURE);
+    }
 
-	if (fwrite(ptr, 0, 0, f)) {
-		return EXIT_FAILURE;
-	}
+    if (fwrite(ptr, 0, 0, f)) {
+        exit(EXIT_FAILURE);
+    }
 
-	fwrite(ptr, sizeof(ptr), 1, f);
-	fclose(f);
+    fwrite(ptr, sizeof(ptr), 1, f);
+    fclose(f);
 }

+ 4 - 2
tests/stdio/getc_unget.c

@@ -1,13 +1,15 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
 	ungetc('h', stdin);
 	char c;
 	if ((c = getchar()) == 'h') {
 		printf("Worked!\n");
-		return EXIT_SUCCESS;
+		exit(EXIT_SUCCESS);
 	}
 	printf("failed :( %c\n", c);
-	return EXIT_FAILURE;
+	exit(EXIT_FAILURE);
 }

+ 7 - 4
tests/stdio/mutex.c

@@ -1,8 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-    FILE* f = fopen("stdio/stdio.in", "r");
+    FILE *f = fopen("stdio/stdio.in", "r");
+    ERROR_IF(fopen, f, == NULL);
 
     flockfile(f);
 
@@ -11,17 +14,17 @@ int main(void) {
 
     if (!ftrylockfile(f)) {
         puts("Mutex unlocked but it shouldn't be");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     funlockfile(f);
 
     if (ftrylockfile(f)) {
         puts("Mutex locked but it shouldn't be");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     if (!ftrylockfile(f)) {
         puts("Mutex unlocked but it shouldn't be");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     funlockfile(f);
 }

+ 7 - 18
tests/stdio/popen.c

@@ -1,28 +1,17 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-int main(void) {
-    FILE *fp;
-    int status;
-    char path[256];
-
+#include "test_helpers.h"
 
-    fp = popen("ls -1 example_dir", "r");
-    if (fp == NULL) {
-        perror("popen");
-        return EXIT_FAILURE;
-    }
+int main(void) {
+    FILE *fp = popen("ls -1 example_dir", "r");
+    ERROR_IF(popen, fp, == NULL);
 
+    char path[256] = { 0 };
     while (fgets(path, 256, fp) != NULL) {
         printf("%s", path);
     }
 
-
-    status = pclose(fp);
-    if (status == -1) {
-        perror("pclose");
-        return EXIT_FAILURE;
-    } else {
-        printf("status %x\n", status);
-    }
+    int status = pclose(fp);
+    ERROR_IF(pclose, status, == -1);
 }

+ 2 - 0
tests/stdio/printf.c

@@ -1,5 +1,7 @@
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     int sofar = 0;
     int len = printf(

+ 41 - 13
tests/stdio/rename.c

@@ -4,25 +4,53 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "test_helpers.h"
+
 static char oldpath[] = "old-name.out";
 static char newpath[] = "new-name.out";
 static char str[] = "Hello, World!";
-int str_len = 13;
 
 int main(void) {
-    char buf[14];
-    buf[13] = 0x00;
+    char buf[14] = { 0 };
+
+    // Create old file
     int fd = creat(oldpath, 0777);
-    write(fd, str, str_len);
-    close(fd);
-    rename(oldpath, newpath);
+    ERROR_IF(creat, fd, == -1);
+    UNEXP_IF(creat, fd, < 0);
+
+    int written_bytes = write(fd, str, strlen(str));
+    ERROR_IF(write, written_bytes, == -1);
+
+    int c1 = close(fd);
+    ERROR_IF(close, c1, == -1);
+    UNEXP_IF(close, c1, != 0);
+
+    // Rename old file to new file
+    int rn_status = rename(oldpath, newpath);
+    ERROR_IF(rename, rn_status, == -1);
+    UNEXP_IF(rename, rn_status, != 0);
+
+    // Read new file
     fd = open(newpath, O_RDONLY);
-    read(fd, buf, str_len);
-    close(fd);
-    remove(newpath);
-    if (strcmp(str, buf) == 0) {
-        return EXIT_SUCCESS;
-    } else {
-        return EXIT_FAILURE;
+    ERROR_IF(open, fd, == -1);
+    UNEXP_IF(open, fd, < 0);
+
+    int read_bytes = read(fd, buf, strlen(str));
+    ERROR_IF(read, read_bytes, == -1);
+    UNEXP_IF(read, read_bytes, < 0);
+
+    int c2 = close(fd);
+    ERROR_IF(close, c2, == -1);
+    UNEXP_IF(close, c2, != 0);
+
+    // Remove new file
+    int rm_status = remove(newpath);
+    ERROR_IF(remove, rm_status, == -1);
+    UNEXP_IF(remove, rm_status, != 0);
+
+    // Compare file contents
+    if (strcmp(str, buf) != 0) {
+        puts("Comparison failed!");
+        exit(EXIT_FAILURE);
     }
 }

+ 2 - 0
tests/stdio/scanf.c

@@ -1,6 +1,8 @@
 #include <stdarg.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 struct params {
     short sa;
     int ia;

+ 2 - 0
tests/stdio/setvbuf.c

@@ -1,6 +1,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
 	setvbuf(stdout, 0, _IONBF, 0);
 	FILE *f = fopen("stdio/stdio.in", "r");

+ 4 - 2
tests/stdio/sprintf.c

@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char buffer[72];
 
@@ -12,7 +14,7 @@ int main(void) {
     );
     if (ret != 68) {
         printf("Failed! Return value was %d\n", ret);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
 
     memset(buffer, 0, sizeof(buffer));
@@ -25,7 +27,7 @@ int main(void) {
     );
     if (ret != 86) {
         printf("Failed! Return value was %d\n", ret);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
 
     puts(buffer);

+ 4 - 2
tests/stdlib/a64l.c

@@ -1,12 +1,14 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char * s = "azAZ9."; // test boundaries
     long l = a64l(s);
     if (l != 194301926) {
         printf("Invalid result: a64l(%s) = %ld\n", s, l);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     printf("Correct a64l: %s = %ld\n", s, l);
 
@@ -15,7 +17,7 @@ int main(void) {
     l = a64l(s);
     if (l != 53222) {
         printf("Invalid result: a64l(%s) = %ld\n", s, l);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     printf("Correct a64l: %s = %ld\n", s, l);
 }

+ 2 - 0
tests/stdlib/alloc.c

@@ -3,6 +3,8 @@
 #include <stdlib.h>
 #include <stdint.h> /* for SIZE_MAX */
 
+#include "test_helpers.h"
+
 int main(void) {
     char * ptr = (char *)malloc(256);
     printf("malloc %p\n", ptr);

+ 2 - 0
tests/stdlib/atof.c

@@ -1,6 +1,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     double d = atof("-3.14");
     printf("%f\n", d);

+ 2 - 0
tests/stdlib/atoi.c

@@ -1,6 +1,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     printf("%d\n", atoi("         -42"));
     printf("%d\n", atoi(" +555"));

+ 46 - 46
tests/stdlib/bsearch.c

@@ -1,56 +1,56 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int int_cmp(const void* a, const void* b) {
-  return *(const int*) a - *(const int*) b;
+    return *(const int*) a - *(const int*) b;
 }
 
 #define BSEARCH_TEST_INT(key, arr, len, expect) \
-  do { \
-    void* res = bsearch((const void*) &key, (void*) arr, len, sizeof(int), int_cmp); \
-    if (res != expect) { \
-      printf("FAIL bsearch for %d in [", key); \
-      size_t i = 0; \
-      for (; i < len; ++i) printf("%d,", arr[i]); \
-      printf("] expected %p but got %p\n", (void*) expect, res); \
-      return EXIT_FAILURE; \
-    } \
-  } while (0);
-
-
+    do { \
+        void* res = bsearch((const void*) &key, (void*) arr, len, sizeof(int), int_cmp); \
+        if (res != expect) { \
+            printf("FAIL bsearch for %d in [", key); \
+            size_t i = 0; \
+            for (; i < len; ++i) printf("%d,", arr[i]); \
+            printf("] expected %p but got %p\n", (void*) expect, res); \
+            exit(EXIT_FAILURE); \
+        } \
+    } while (0)
 
 int main(void) {
-  int x = 0;
-  int y = 1024;
-
-  // TODO: Zero sized arrays are a non-standard GNU extension
-  //int empty[] = {};
-  //BSEARCH_TEST_INT(x, empty, 0, NULL);
-
-  int singleton[] = {42};
-  printf("%p\n%p\n", singleton, &singleton[1]);
-  BSEARCH_TEST_INT(x, singleton, 1, NULL);
-  BSEARCH_TEST_INT(singleton[0], singleton, 1, &singleton[0]);
-  BSEARCH_TEST_INT(y, singleton, 1, NULL);
-
-  int two[] = {14, 42};
-  BSEARCH_TEST_INT(x, two, 2, NULL);
-  BSEARCH_TEST_INT(y, two, 2, NULL);
-  BSEARCH_TEST_INT(two[0], two, 2, &two[0]);
-  BSEARCH_TEST_INT(two[0], two, 1, &two[0]);
-  BSEARCH_TEST_INT(two[1], two, 2, &two[1]);
-  BSEARCH_TEST_INT(two[1], two, 1, NULL);
-
-  int three[] = {-5, -1, 4};
-  BSEARCH_TEST_INT(three[0], three, 3, &three[0]);
-  BSEARCH_TEST_INT(three[1], three, 3, &three[1]);
-  BSEARCH_TEST_INT(three[2], three, 3, &three[2]);
-
-  int big[] = {-19, -13, -7, -3, 2, 5, 11};
-  BSEARCH_TEST_INT(big[0], big, 7, big);
-  BSEARCH_TEST_INT(big[6], big, 7, &big[6]);
-  BSEARCH_TEST_INT(big[3], big, 7, &big[3]);
-  BSEARCH_TEST_INT(x, big, 7, NULL);
-
-  printf("PASS bsearch\n");
+    int x = 0;
+    int y = 1024;
+
+    // TODO: Zero sized arrays are a non-standard GNU extension
+    //int empty[] = {};
+    //BSEARCH_TEST_INT(x, empty, 0, NULL);
+
+    int singleton[] = {42};
+    printf("%p\n%p\n", singleton, &singleton[1]);
+    BSEARCH_TEST_INT(x, singleton, 1, NULL);
+    BSEARCH_TEST_INT(singleton[0], singleton, 1, &singleton[0]);
+    BSEARCH_TEST_INT(y, singleton, 1, NULL);
+
+    int two[] = {14, 42};
+    BSEARCH_TEST_INT(x, two, 2, NULL);
+    BSEARCH_TEST_INT(y, two, 2, NULL);
+    BSEARCH_TEST_INT(two[0], two, 2, &two[0]);
+    BSEARCH_TEST_INT(two[0], two, 1, &two[0]);
+    BSEARCH_TEST_INT(two[1], two, 2, &two[1]);
+    BSEARCH_TEST_INT(two[1], two, 1, NULL);
+
+    int three[] = {-5, -1, 4};
+    BSEARCH_TEST_INT(three[0], three, 3, &three[0]);
+    BSEARCH_TEST_INT(three[1], three, 3, &three[1]);
+    BSEARCH_TEST_INT(three[2], three, 3, &three[2]);
+
+    int big[] = {-19, -13, -7, -3, 2, 5, 11};
+    BSEARCH_TEST_INT(big[0], big, 7, big);
+    BSEARCH_TEST_INT(big[6], big, 7, &big[6]);
+    BSEARCH_TEST_INT(big[3], big, 7, &big[3]);
+    BSEARCH_TEST_INT(x, big, 7, NULL);
+
+    printf("PASS bsearch\n");
 }

+ 18 - 15
tests/stdlib/div.c

@@ -1,20 +1,23 @@
 #include <stdlib.h>
-         volatile float f;
-         volatile long double ld;
-         volatile unsigned long long ll;
-         lldiv_t mydivt;
+
+#include "test_helpers.h"
+
+volatile float f;
+volatile long double ld;
+volatile unsigned long long ll;
+lldiv_t mydivt;
 
 int main(void) {
-         char* tmp;
-         f = strtof("gnu", &tmp);
-         ld = strtold("gnu", &tmp);
-         ll = strtoll("gnu", &tmp, 10);
-         ll = strtoull("gnu", &tmp, 10);
-         ll = llabs(10);
-         mydivt = lldiv(10,1);
-         ll = mydivt.quot;
-         ll = mydivt.rem;
-         ll = atoll("10");
-         _Exit(0);
+    char* tmp;
+    f = strtof("gnu", &tmp);
+    ld = strtold("gnu", &tmp);
+    ll = strtoll("gnu", &tmp, 10);
+    ll = strtoull("gnu", &tmp, 10);
+    ll = llabs(10);
+    mydivt = lldiv(10,1);
+    ll = mydivt.quot;
+    ll = mydivt.rem;
+    ll = atoll("10");
+    _Exit(0);
 }
 

+ 3 - 1
tests/stdlib/env.c

@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     //puts(getenv("SHELL"));
     //puts(getenv("CC"));
@@ -34,7 +36,7 @@ int main(void) {
     if (env) {
         puts("This should be null, but isn't");
         puts(env);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     } else {
         puts("Value deleted successfully!");
     }

+ 2 - 0
tests/stdlib/mkostemps.c

@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char* file_name = (char*) calloc(18, sizeof(char));
     strcpy(file_name, "tempXXXXXX.suffix");

+ 2 - 0
tests/stdlib/mktemp.c

@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char* string = (char*) calloc(20, sizeof(char));
     strcpy(string, "tempXXXXXX");

+ 28 - 2
tests/stdlib/rand.c

@@ -1,8 +1,34 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-    printf("%d\n", rand());
+    // Uninitialized generator
+    int rand_uninit = rand();
+    printf("%d\n", rand_uninit);
+
+    // Testing the reproducibility of values
+    srand(259);
+    int rand_seed259_1 = rand();
+    printf("%d\n", rand_seed259_1);
+
     srand(259);
-    printf("%d\n", rand());
+    int rand_seed259_2 = rand();
+    printf("%d\n", rand_seed259_2);
+
+    if (rand_seed259_1 != rand_seed259_2) {
+        puts("rand() doesn't return reproducible values");
+        exit(EXIT_FAILURE);
+    }
+
+    // Seed value 1 should return the same values as the ininitialized generator
+    srand(1);
+    int rand_seed1 = rand();
+    printf("%d\n", rand_seed1);
+
+    if (rand_uninit != rand_seed1) {
+        puts("srand(1) doesn't work");
+        exit(EXIT_FAILURE);
+    }
 }

+ 11 - 20
tests/stdlib/realpath.c

@@ -4,26 +4,17 @@
 #include <stdlib.h>
 #include <string.h>
 
-int main(void) {
-    char* path = realpath("stdlib/realpath.c", NULL);
-    if (!path) {
-        perror("realpath");
-        return EXIT_FAILURE;
-    }
-    puts(path);
-
-    free(path);
+#include "test_helpers.h"
 
-    path = malloc(PATH_MAX);
-    memset(path, 0, PATH_MAX);
-
-    realpath("stdlib/realpath.c", path);
-    if (!path) {
-        perror("realpath");
-        free(path);
-        return EXIT_FAILURE;
-    }
-    puts(path);
+int main(void) {
+    char *path_res = realpath("stdlib/realpath.c", NULL);
+    ERROR_IF(realpath, path_res, == NULL);
+    puts(path_res);
+    free(path_res);
 
-    free(path);
+    char path_arg[PATH_MAX] = { 0 };
+    char *res = realpath("stdlib/realpath.c", path_arg);
+    ERROR_IF(realpath, res, == NULL);
+    puts(path_arg);
+    free(path_arg);
 }

+ 2 - 0
tests/stdlib/strtod.c

@@ -1,6 +1,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char* endptr = 0;
     double d;

+ 2 - 0
tests/stdlib/strtol.c

@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     printf("%ld\n", strtol("         -42", NULL, 0));
     printf("%ld\n", strtol(" +555", NULL, 0));

+ 2 - 0
tests/stdlib/strtoul.c

@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     printf("%ld\n", strtoul("         -42", NULL, 0));
     printf("%ld\n", strtoul(" +555", NULL, 0));

+ 4 - 1
tests/stdlib/system.c

@@ -1,5 +1,8 @@
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-    system("echo test of system");
+    int status = system("echo test of system");
+    ERROR_IF(system, status, == -1);
 }

+ 8 - 6
tests/string/mem.c

@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     puts("# mem #");
     char arr[100];
@@ -9,7 +11,7 @@ int main(void) {
     arr[50] = 1;
     if ((size_t)memchr((void *)arr, 1, 100) - (size_t)arr != 50) {
         puts("Incorrect memchr");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     puts("Correct memchr");
     char arr2[51];
@@ -17,25 +19,25 @@ int main(void) {
     memccpy((void *)arr2, (void *)arr, 1, 100);
     if (arr[50] != 1) {
         puts("Incorrect memccpy");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     puts("Correct memccpy");
     int res;
     if ((res = memcmp("hello world", "hello world", 11))) {
         printf("Incorrect memcmp (1), expected 0 found %d\n", res);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     if ((res = memcmp("hello world", "hello worlt", 11)) >= 0) {
         printf("Incorrect memcmp (2), expected -, found %d\n", res);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     if ((res = memcmp("hello world", "hallo world", 5)) <= 0) {
         printf("Incorrect memcmp (3), expected +, found %d\n", res);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     if ((res = memcmp("hello world", "henlo world", 5)) >= 0) {
         printf("Incorrect memcmp (4), expected -, found %d\n", res);
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     puts("Correct memcmp");
 }

+ 2 - 0
tests/string/strcat.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char dest1[12] = "hello";
 	  printf("%s\n", strcat(dest1, " world")); // should be hello world

+ 2 - 0
tests/string/strchr.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
 	printf("%s\n", strchr("hello", 'e')); // should be ello
 	printf("%s\n", strchr("world", 'l')); // should be ld

+ 2 - 0
tests/string/strcpy.c

@@ -1,6 +1,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char dst[20];
 

+ 2 - 0
tests/string/strcspn.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
 	char *world = "world";
 	printf("%ld\n", strcspn("hello", world)); // should be 2

+ 2 - 0
tests/string/strncmp.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     printf("%d\n", strncmp("a", "aa", 2));
     printf("%d\n", strncmp("a", "aä", 2));

+ 2 - 0
tests/string/strpbrk.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char* source = "The quick drawn fix jumps over the lazy bug";
 

+ 19 - 15
tests/string/strrchr.c

@@ -2,20 +2,24 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-  char s0[] = "hello, world";
-  char* ptr = strrchr(s0, 'l');
-  if (ptr != &s0[10]) {
-    printf("%p != %p\n", ptr, &s0[10]);
-    printf("strrchr FAIL , exit with status code %d\n", 1);
-    return EXIT_FAILURE;
-  }
-  char s1[] = "";
-  ptr = strrchr(s1, 'a');
-  if (ptr != NULL) {
-    printf("%p != 0\n", ptr);
-    printf("strrchr FAIL, exit with status code %d\n", 1);
-    return EXIT_FAILURE;
-  }
-  printf("strrch PASS, exiting with status code %d\n", 0);
+    char s0[] = "hello, world";
+    char *ptr = strrchr(s0, 'l');
+    if (ptr != &s0[10]) {
+        printf("%p != %p\n", ptr, &s0[10]);
+        puts("strrchr FAIL");
+        exit(EXIT_FAILURE);
+    }
+
+    char s1[] = "";
+    ptr = strrchr(s1, 'a');
+    if (ptr != NULL) {
+        printf("%p != 0\n", ptr);
+        puts("strrchr FAIL");
+        exit(EXIT_FAILURE);
+    }
+
+    puts("strrch PASS");
 }

+ 2 - 0
tests/string/strspn.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
 	char *hello = "hello";
 	char *world = "world";

+ 2 - 0
tests/string/strstr.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     printf("%s\n", strstr("In relibc we trust", "rust"));
     printf("%s\n", strstr("In relibc we trust", "libc"));

+ 2 - 0
tests/string/strtok.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char source[] = "I'd just like to interject for a moment.  What you're referring to as Linux, "
                     "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.\n";

+ 2 - 0
tests/string/strtok_r.c

@@ -1,6 +1,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     char source[] = "I'd just like to interject for a moment.  What you're referring to as Linux, "
                     "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.\n";

+ 2 - 0
tests/strings.c

@@ -3,6 +3,8 @@
 #include <stdio.h>
 #include <strings.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     assert(!bcmp("hello", "hehe", 2));
     assert(bcmp("hello", "haha", 2));

+ 10 - 10
tests/sys_utsname/uname.c

@@ -1,19 +1,19 @@
 #include <stdio.h>
 #include <sys/utsname.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     struct utsname system_info;
 
     int result = uname(&system_info);
+    ERROR_IF(uname, result, == -1);
+    UNEXP_IF(uname, result, < 0);
 
-    if (result < 0) {
-        perror("uname");
-    } else {
-        printf("sysname: '%s'\n", system_info.sysname);
-        printf("nodename: '%s'\n", system_info.nodename);
-        printf("release: '%s'\n", system_info.release);
-        printf("version: '%s'\n", system_info.version);
-        printf("machine: '%s'\n", system_info.machine);
-        //printf("domainname: '%s'\n", system_info.domainname);
-    }
+    printf("sysname: '%s'\n", system_info.sysname);
+    printf("nodename: '%s'\n", system_info.nodename);
+    printf("release: '%s'\n", system_info.release);
+    printf("version: '%s'\n", system_info.version);
+    printf("machine: '%s'\n", system_info.machine);
+    //printf("domainname: '%s'\n", system_info.domainname);
 }

+ 91 - 0
tests/test_helpers.h

@@ -0,0 +1,91 @@
+#ifndef _TEST_HELPERS
+#define _TEST_HELPERS
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Throws errors on a well-defined API error values.
+//
+// Only use with API functions that sets the errno variable.
+// Do not pass functions as the status or condition arguments, they might be
+// evaluated multiple times.
+//
+// Usage example:
+//
+// > Upon successful completion, fclose() returns 0.
+// > Otherwise, it returns EOF and sets errno to indicate the error.
+//
+// int status = fclose(fp);
+// ERROR_IF(fclose, status, == EOF);
+//
+// Use it only for checking the API error values.
+// Do not use it for checking the correctness of the results. If you need to
+// do that, print the values to the standard output and use the expected outputs
+// directory.
+//
+// For example:
+//
+// int c = fgetc(f);            // !!! DO NOT USE THIS WAY !!!
+// ERROR_IF(fgetc, c, != 'H');  // !!! DO NOT USE THIS WAY !!!
+//
+// Correct usage:
+//
+// int c = fgetc(f);            // OK
+// ERROR_IF(fgetc, c, == EOF);  // OK
+// printf("result: %c\n", c);   // OK
+//
+#define ERROR_IF(func, status, condition) \
+    do { \
+        if (status condition) { \
+            fprintf(stderr, "%s:%s:%d: '%s' failed: %s (%d)\n", \
+                __FILE__, __func__, __LINE__, #func, strerror(errno), errno); \
+            _exit(EXIT_FAILURE); \
+        } \
+    } while(0)
+
+// Throws errors on API return values not defined by the standards.
+//
+// Do not pass functions as the status or condition arguments, they might be
+// evaluated multiple times.
+//
+// Use it only for detecting return values that should have never been returned
+// in any case by the API functions.
+//
+// Usage example:
+//
+// > The fgetc() function obtains the next byte as an unsigned char
+// > converted to an int.
+//
+// int c = fgetc(f);
+// UNEXP_IF(fgetc, c, < 0);
+// UNEXP_IF(fgetc, c, > 255);
+//
+#define UNEXP_IF(func, status, condition) \
+    do { \
+        if (status condition) { \
+            fprintf(stderr, "%s:%s:%d: '%s' returned a non-standard value: ", \
+                __FILE__, __func__, __LINE__, #func); \
+            fprintf(stderr, _Generic((status), \
+                char *: "char*(%p) = \"%1$s\"", \
+                void *: "void*(%p)", \
+                default: "%i" \
+            ), status); \
+            fprintf(stderr, "\n"); \
+            _exit(EXIT_FAILURE); \
+        } \
+    } while (0)
+
+// A convenience macro to show where the test fail.
+#define exit(code) \
+    do { \
+        if (code != EXIT_SUCCESS) { \
+            fprintf(stderr, "%s:%s:%d: Test failed with exit(%s)\n", \
+                __FILE__, __func__, __LINE__, #code); \
+        } \
+        _exit(code); \
+    } while(0)
+
+#endif /* _TEST_HELPERS */

+ 3 - 1
tests/time/asctime.c

@@ -3,6 +3,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     time_t a = 0;
     struct tm *time_info = gmtime(&a);
@@ -10,6 +12,6 @@ int main(void) {
     char *time_string = asctime(time_info);
 
     if (time_string == NULL || strcmp(time_string, "Thu Jan  1 00:00:00 1970\n") != 0) {
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
 }

+ 7 - 1
tests/time/gettimeofday.c

@@ -1,8 +1,14 @@
 #include <sys/time.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     struct timeval tv;
-    gettimeofday(&tv, NULL);
+
+    // gettimeofday always returns 0, no errors are defined
+    int gtod = gettimeofday(&tv, NULL);
+    UNEXP_IF(gettimeofday, gtod, != 0);
+
     printf("%ld: %ld\n", tv.tv_sec, tv.tv_usec);
 }

+ 3 - 9
tests/time/gmtime.c

@@ -3,6 +3,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     time_t a = 0;
     struct tm expected = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_year = 70,
@@ -14,14 +16,6 @@ int main(void) {
         info->tm_year != expected.tm_year || info->tm_wday != expected.tm_wday ||
         info->tm_yday != expected.tm_yday || info->tm_isdst != expected.tm_isdst ||
         info->tm_gmtoff != expected.tm_gmtoff || strcmp(info->tm_zone, expected.tm_zone) != 0) {
-            return EXIT_FAILURE;
-    }
-
-    if (info->tm_sec != expected.tm_sec || info->tm_min != expected.tm_min ||
-        info->tm_hour != expected.tm_hour || info->tm_mday != expected.tm_mday ||
-        info->tm_year != expected.tm_year || info->tm_wday != expected.tm_wday ||
-        info->tm_yday != expected.tm_yday || info->tm_isdst != expected.tm_isdst ||
-        info->tm_gmtoff != expected.tm_gmtoff || strcmp(info->tm_zone, expected.tm_zone) != 0) {
-            return EXIT_FAILURE;
+            exit(EXIT_FAILURE);
     }
 }

+ 2 - 0
tests/time/localtime.c

@@ -1,6 +1,8 @@
 #include <stdio.h>
 #include <time.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     int day = 60 * 60 * 24;
     time_t inputs[] = { -(day * 33), -day, -1, -500, 0, 1, 1531454950 };

+ 2 - 0
tests/time/macros.c

@@ -1,6 +1,8 @@
 #include <assert.h>
 #include <sys/time.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     struct timeval x = { .tv_usec = 15 };
     struct timeval y = { 0 };

+ 18 - 7
tests/time/mktime.c

@@ -3,20 +3,26 @@
 #include <stdlib.h>
 #include <time.h>
 
+#include "test_helpers.h"
+
 int check(time_t input) {
-    struct tm* t = localtime(&input);
+    struct tm *t = localtime(&input);
+    ERROR_IF(localtime, t, == NULL);
+
+    time_t output = mktime(t);
+    ERROR_IF(mktime, output, == (time_t)-1);
 
-    printf("%ld = %ld\n", input, mktime(t));
+    printf("%ld = %ld\n", input, output);
 
-    if (input != mktime(t)) {
+    if (input != output) {
         printf(
             "Year %d, Day of year: %d, Month %d, Day of month: %d, Day of week: %d, %d:%d:%d\n",
             t->tm_year, t->tm_yday, t->tm_mon, t->tm_mday, t->tm_wday, t->tm_hour, t->tm_min, t->tm_sec
         );
         puts("Failed!");
-        return EXIT_FAILURE;
+        return 1;
     }
-    return EXIT_SUCCESS;
+    return 0;
 }
 
 int main(void) {
@@ -31,7 +37,7 @@ int main(void) {
     time_t inputs[] = { -(day * 33), -day, -500, 0, 1531454950 };
     for (int i = 0; i < 5; i += 1) {
         if (check(inputs[i])) {
-            return EXIT_FAILURE;
+            exit(EXIT_FAILURE);
         }
     }
 
@@ -39,8 +45,13 @@ int main(void) {
 
     for (int i = 0; i < 10; i += 1) {
         time_t input = (time_t) rand();
-        struct tm* time = localtime(&input);
+
+        struct tm *time = localtime(&input);
+        ERROR_IF(localtime, time, == NULL);
+
         time_t output = mktime(time);
+        ERROR_IF(mktime, output, == (time_t)-1);
+
         if (input != output) {
             // asctime has newline
             printf("Comparison %ld == %ld failed. Time: %s", input, output, asctime(time));

+ 2 - 0
tests/time/strftime.c

@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <time.h>
 
+#include "test_helpers.h"
+
 void print(time_t timestamp, char* fmt) {
     char* out = malloc(50);
     size_t n = strftime(out, 50, fmt, localtime(&timestamp));

+ 5 - 12
tests/time/time.c

@@ -2,24 +2,17 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     struct timespec tm = {0, 0};
 
     int cgt = clock_gettime(CLOCK_REALTIME, &tm);
-    if (cgt == -1) {
-        perror("clock_gettime");
-        return EXIT_FAILURE;
-    }
+    ERROR_IF(clock_gettime, cgt, == -1);
 
     time_t t = time(NULL);
-    if (t == (time_t)-1) {
-        perror("time");
-        return EXIT_FAILURE;
-    }
+    ERROR_IF(time, t, == (time_t)-1);
 
     clock_t c = clock();
-    if (c == (clock_t)-1) {
-        perror("clock");
-        return EXIT_FAILURE;
-    }
+    ERROR_IF(clock, c, == (clock_t)-1);
 }

+ 5 - 1
tests/time/times.c

@@ -2,9 +2,13 @@
 #include <sys/times.h>
 #include <unistd.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     struct tms tms;
-    printf("return: %ld\n", times(&tms));
+
+    int status = times(&tms);
+    ERROR_IF(times, status, == (time_t)-1);
 
     printf("tm_utime: %ld\n", tms.tms_utime);
     printf("tm_stime: %ld\n", tms.tms_stime);

+ 4 - 2
tests/unistd/access.c

@@ -2,14 +2,16 @@
 #include <unistd.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
     if (access("example_dir/1-never-gonna-give-you-up", R_OK | W_OK)) {
         perror("access");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
     if (!access("example_dir/1-never-gonna-give-you-up", X_OK)) {
         puts("Accessing a file with X_OK worked even though it... probably... shouldn't?");
         puts("Please run `chmod 644 example_dir/*` and try again.");
-        return EXIT_FAILURE;
+        exit(EXIT_FAILURE);
     }
 }

+ 5 - 1
tests/unistd/brk.c

@@ -1,7 +1,11 @@
 #include <unistd.h>
 #include <stdio.h>
+#include <stdlib.h>
+
+#include "test_helpers.h"
 
 int main(void) {
     int status = brk((void*)100);
-    printf("brk exited with status code %d\n", status);
+    ERROR_IF(brk, status, == -1);
+    UNEXP_IF(brk, status, != 0);
 }

+ 21 - 9
tests/unistd/chdir.c

@@ -1,15 +1,27 @@
+#include <limits.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-    char* cwd1 = malloc(4096*sizeof(char));//(char*) calloc(4096 + 1, sizeof(char));
-    getcwd(cwd1, 4096);
-    printf("initial cwd: %s\n", cwd1);
-    free(cwd1);
-    chdir("..");
-    char* cwd2 = malloc(4096*sizeof(char));//(char*) calloc(4096 + 1, sizeof(char));
-    getcwd(cwd2, 4096);
-    printf("final cwd: %s\n", cwd2);
-    free(cwd2);
+    char cwd[PATH_MAX] = { 0 };
+    char *cwd_result = NULL;
+
+    cwd_result = getcwd(cwd, PATH_MAX);
+    ERROR_IF(getcwd, cwd_result, == NULL);
+    UNEXP_IF(getcwd, cwd_result, != cwd);
+
+    printf("getcwd before chdir: %s\n", cwd);
+
+    int status = chdir("..");
+    ERROR_IF(chdir, status, == -1);
+    UNEXP_IF(chdir, status, != 0);
+
+    cwd_result = getcwd(cwd, PATH_MAX);
+    ERROR_IF(getcwd, cwd_result, == NULL);
+    UNEXP_IF(getcwd, cwd_result, != cwd);
+
+    printf("getcwd after chdir: %s\n", cwd);
 }

+ 32 - 5
tests/unistd/dup.c

@@ -2,15 +2,42 @@
 #include <fcntl.h>
 #include <stdio.h>
 
+#include "test_helpers.h"
+
 int main(void) {
-    creat("dup.out", 0777);
+    int fd0 = creat("dup.out", 0777);
+    ERROR_IF(creat, fd0, == -1);
+    UNEXP_IF(creat, fd0, < 0);
+
     int fd1 = open("dup.out", 0);
+    ERROR_IF(open, fd1, == -1);
+    UNEXP_IF(open, fd1, < 0);
+
     int fd2 = dup(fd1);
+    ERROR_IF(dup, fd2, == -1);
+    UNEXP_IF(dup, fd2, < 0);
+
     printf("fd %d duped into fd %d\n", fd1, fd2);
-    close(fd1);
-    close(fd2);
+
+    int c1 = close(fd1);
+    ERROR_IF(close, c1, == -1);
+    UNEXP_IF(close, c1, != 0);
+
+    int c2 = close(fd2);
+    ERROR_IF(close, c2, == -1);
+    UNEXP_IF(close, c2, != 0);
+
     int fd3 = open("dup.out", 0x0002, 0x1000);
-    dup2(fd3, 1);
+    ERROR_IF(open, fd3, == -1);
+    UNEXP_IF(open, fd3, < 0);
+
+    int fd4 = dup2(fd3, 1);
+    ERROR_IF(dup2, fd4, == -1);
+    UNEXP_IF(dup2, fd4, < 0);
+
     printf("hello fd %d", fd3);
-    close(fd3);
+
+    int c3 = close(fd3);
+    ERROR_IF(close, c3, == -1);
+    UNEXP_IF(close, c3, != 0);
 }

+ 6 - 2
tests/unistd/exec.c

@@ -1,8 +1,12 @@
 #include <unistd.h>
 #include <stdio.h>
+#include <stdlib.h>
+
+#include "test_helpers.h"
 
 int main(void) {
     char* args[] = {"sh", "-c", "echo 'exec works :D'", NULL};
-    execv("/bin/sh", args);
-    perror("execv");
+
+    int status = execv("/bin/sh", args);
+    ERROR_IF(execv, status, == -1);
 }

+ 13 - 4
tests/unistd/fchdir.c

@@ -1,11 +1,20 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
+
+#include "test_helpers.h"
 
 int main(void) {
     int fd = open("..", 0, 0);
-    int status;
-    status = fchdir(fd);
-    printf("fchdir exited with status code %d\n", status);
-    close(fd);
+    ERROR_IF(open, fd, == -1);
+    UNEXP_IF(open, fd, < 0);
+
+    int status = fchdir(fd);
+    ERROR_IF(fchdir, status, == -1);
+    UNEXP_IF(fchdir, status, != 0);
+
+    int c = close(fd);
+    ERROR_IF(close, c, == -1);
+    UNEXP_IF(close, c, != 0);
 }

+ 13 - 4
tests/unistd/fsync.c

@@ -1,11 +1,20 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
+
+#include "test_helpers.h"
 
 int main(void) {
     int fd = open(".", 0, 0);
-    int status;
-    status = fsync(fd);
-    printf("fsync exited with status code %d\n", status);
-    close(fd);
+    ERROR_IF(open, fd, == -1);
+    UNEXP_IF(open, fd, < 0);
+
+    int status = fsync(fd);
+    ERROR_IF(fsync, status, == -1);
+    UNEXP_IF(fsync, status, != 0);
+
+    int c = close(fd);
+    ERROR_IF(close, c, == -1);
+    UNEXP_IF(close, c, != 0);
 }

Some files were not shown because too many files changed in this diff