Browse Source

tests: Documentation for test_helpers.h, more refactoring

Tibor Nagy 6 years ago
parent
commit
513f4ba53c
11 changed files with 121 additions and 63 deletions
  1. 6 10
      tests/signal.c
  2. 22 7
      tests/stdio/all.c
  3. 2 1
      tests/stdio/fgets.c
  4. 12 4
      tests/stdio/fputs.c
  5. 1 0
      tests/stdio/fread.c
  6. 3 1
      tests/stdio/fseek.c
  7. 15 13
      tests/stdio/fwrite.c
  8. 2 1
      tests/stdio/mutex.c
  9. 5 18
      tests/stdio/popen.c
  10. 49 7
      tests/test_helpers.h
  11. 4 1
      tests/waitpid.c

+ 6 - 10
tests/signal.c

@@ -11,17 +11,13 @@ void handler(int sig) {
 }
 
 int main(void) {
-    if (signal(SIGUSR1, &handler) == SIG_ERR) {
-        puts("Signal error!");
-        printf("%d\n", errno);
-        exit(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);
-        exit(EXIT_FAILURE);
-    }
+
+    int raise_status = raise(SIGUSR1);
+    ERROR_IF(raise, raise_status, < 0);
+
     puts("Raised.");
 }

+ 22 - 7
tests/stdio/all.c

@@ -4,11 +4,26 @@
 #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 - 1
tests/stdio/fgets.c

@@ -4,8 +4,9 @@
 #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) {

+ 12 - 4
tests/stdio/fputs.c

@@ -4,8 +4,16 @@
 #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);
 }

+ 1 - 0
tests/stdio/fread.c

@@ -6,6 +6,7 @@
 
 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) {

+ 3 - 1
tests/stdio/fseek.c

@@ -4,7 +4,9 @@
 #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);
+
     if (fseek(f, 14, SEEK_CUR) < 0) {
         puts("fseek error");
         exit(EXIT_FAILURE);

+ 15 - 13
tests/stdio/fwrite.c

@@ -5,21 +5,23 @@
 #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);
 
-	if (fwrite(ptr, 0, 17, f)) {
-		exit(EXIT_FAILURE);
-	}
+    const char ptr[] = "Hello World!";
 
-	if (fwrite(ptr, 7, 0, f)) {
-		exit(EXIT_FAILURE);
-	}
+    if (fwrite(ptr, 0, 17, f)) {
+        exit(EXIT_FAILURE);
+    }
 
-	if (fwrite(ptr, 0, 0, f)) {
-		exit(EXIT_FAILURE);
-	}
+    if (fwrite(ptr, 7, 0, f)) {
+        exit(EXIT_FAILURE);
+    }
 
-	fwrite(ptr, sizeof(ptr), 1, f);
-	fclose(f);
+    if (fwrite(ptr, 0, 0, f)) {
+        exit(EXIT_FAILURE);
+    }
+
+    fwrite(ptr, sizeof(ptr), 1, f);
+    fclose(f);
 }

+ 2 - 1
tests/stdio/mutex.c

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

+ 5 - 18
tests/stdio/popen.c

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

+ 49 - 7
tests/test_helpers.h

@@ -7,25 +7,67 @@
 #include <string.h>
 #include <unistd.h>
 
-// Throws an error on a well-defined error value.
-// Don't pass functions as status or condition, it might evaluate them multiple times.
+// 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) { \
     if (status condition) { \
         fprintf(stderr, "%s:%s:%d: '%s' returned an error: %s (%d)\n", \
             __FILE__, __func__, __LINE__, #func, strerror(errno), errno); \
         _exit(EXIT_FAILURE); \
-    }\
+    } \
 }
 
-// Throws an error on an return value not defined by the standards.
-// Used for sanity checking the return values.
-// Don't pass functions as status or condition it might evaluate them multiple times.
+// 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) { \
     if (status condition) { \
         fprintf(stderr, "%s:%s:%d: '%s' returned a non-standard value: %d\n", \
             __FILE__, __func__, __LINE__, #func, status); \
         _exit(EXIT_FAILURE); \
-    }\
+    } \
 }
 
 // A convenience macro to show where the test fail.

+ 4 - 1
tests/waitpid.c

@@ -6,6 +6,8 @@
 
 int main(void) {
     pid_t pid = fork();
+    ERROR_IF(fork, pid, == -1);
+
     if (pid == 0) {
         // child
         sleep(1);
@@ -13,6 +15,7 @@ int main(void) {
     } else {
         // parent
         int stat_loc;
-        waitpid(pid, &stat_loc, 0);
+        pid_t wid = waitpid(pid, &stat_loc, 0);
+        ERROR_IF(waitpid, wid, == -1);
     }
 }