From 513f4ba53c39fde05d5c651ddb074024ea00b938 Mon Sep 17 00:00:00 2001 From: Tibor Nagy <xnagytibor@gmail.com> Date: Fri, 22 Feb 2019 13:19:38 +0100 Subject: [PATCH] tests: Documentation for test_helpers.h, more refactoring --- tests/signal.c | 16 +++++-------- tests/stdio/all.c | 29 +++++++++++++++++------ tests/stdio/fgets.c | 3 ++- tests/stdio/fputs.c | 16 +++++++++---- tests/stdio/fread.c | 1 + tests/stdio/fseek.c | 4 +++- tests/stdio/fwrite.c | 28 ++++++++++++---------- tests/stdio/mutex.c | 3 ++- tests/stdio/popen.c | 23 ++++-------------- tests/test_helpers.h | 56 ++++++++++++++++++++++++++++++++++++++------ tests/waitpid.c | 5 +++- 11 files changed, 121 insertions(+), 63 deletions(-) diff --git a/tests/signal.c b/tests/signal.c index 57d1323e2..b192ad397 100644 --- a/tests/signal.c +++ b/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."); } diff --git a/tests/stdio/all.c b/tests/stdio/all.c index 2ccc35eb4..de7c60ab6 100644 --- a/tests/stdio/all.c +++ b/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"); } diff --git a/tests/stdio/fgets.c b/tests/stdio/fgets.c index 6e2b715bf..ed02999cd 100644 --- a/tests/stdio/fgets.c +++ b/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) { diff --git a/tests/stdio/fputs.c b/tests/stdio/fputs.c index 7d76d12ab..e377bfe8d 100644 --- a/tests/stdio/fputs.c +++ b/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); } diff --git a/tests/stdio/fread.c b/tests/stdio/fread.c index ea14368eb..75eb7ff8f 100644 --- a/tests/stdio/fread.c +++ b/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) { diff --git a/tests/stdio/fseek.c b/tests/stdio/fseek.c index c07cf79b5..8bc948799 100644 --- a/tests/stdio/fseek.c +++ b/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); diff --git a/tests/stdio/fwrite.c b/tests/stdio/fwrite.c index 24c7040fb..308c9c296 100644 --- a/tests/stdio/fwrite.c +++ b/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); } diff --git a/tests/stdio/mutex.c b/tests/stdio/mutex.c index aae45caa1..3d9be9d8d 100644 --- a/tests/stdio/mutex.c +++ b/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); diff --git a/tests/stdio/popen.c b/tests/stdio/popen.c index 967ad78ac..3d314d52a 100644 --- a/tests/stdio/popen.c +++ b/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); } diff --git a/tests/test_helpers.h b/tests/test_helpers.h index 6db31e2d7..d3559a4e5 100644 --- a/tests/test_helpers.h +++ b/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. diff --git a/tests/waitpid.c b/tests/waitpid.c index e0b77829f..ec4c6dedc 100644 --- a/tests/waitpid.c +++ b/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); } } -- GitLab