#include "config.h" #include #include #include #include "logerr.h" /** * @tags infallible */ void vlogerr( const char *const file, const char *const function, const int lineno, FILE *restrict stream, const char *restrict format, ... ) { (void)fprintf(stream, "%s:%s:%d: ", file, function, lineno); va_list args; va_start(args, format); (void)vfprintf(stream, format, args); va_end(args); return; } #ifdef TEST #include #include #include #include "testing.h" #include "../tests/slurp.h" static const char *const FNAME = __FILE__ ".txt"; static int test_vlogerr(void) { int rc = 0; test_start("vlogerr()"); FILE *file = NULL; char *str = NULL; { testing("empty varargs"); file = fopen(FNAME, "w"); if (!file) { perror("fopen(FNAME, \"w\")"); rc = -1; goto out; } #line 100 vlogerr(__FILE__, __func__, __LINE__, file, ""); const int ret = fclose(file); file = NULL; if (ret) { perror("fclose(file)"); rc = -1; goto out; } if (slurp_for_tests(FNAME, &str)) { perror("slurp_for_tests(FNAME, &str)"); rc = -1; goto out; } const char *const expected = "src/logerr.c:test_vlogerr:100: "; assert(strcmp(expected, str) == 0); free(str); str = NULL; test_ok(); } { testing("a newline only"); file = fopen(FNAME, "w"); if (!file) { perror("fopen(FNAME, \"w\")"); rc = -1; goto out; } #line 200 vlogerr(__FILE__, __func__, __LINE__, file, "\n"); const int ret = fclose(file); file = NULL; if (ret) { perror("fclose(file)"); rc = -1; goto out; } if (slurp_for_tests(FNAME, &str)) { perror("slurp_for_tests(FNAME, &str)"); rc = -1; goto out; } const char *const expected = "src/logerr.c:test_vlogerr:200: \n"; assert(strcmp(expected, str) == 0); free(str); str = NULL; test_ok(); } { testing("static format string"); file = fopen(FNAME, "w"); if (!file) { perror("fopen(FNAME, \"w\")"); rc = -1; goto out; } #line 300 vlogerr(__FILE__, __func__, __LINE__, file, "some static string\n"); const int ret = fclose(file); file = NULL; if (ret) { perror("fclose(file)"); rc = -1; goto out; } if (slurp_for_tests(FNAME, &str)) { perror("slurp_for_tests(FNAME, &str)"); rc = -1; goto out; } const char *const expected = "src/logerr.c:test_vlogerr:300: some static string\n"; assert(strcmp(expected, str) == 0); free(str); str = NULL; test_ok(); } { testing("single arg format string"); file = fopen(FNAME, "w"); if (!file) { perror("fopen(FNAME, \"w\")"); rc = -1; goto out; } #line 400 vlogerr(__FILE__, __func__, __LINE__, file, "fn(%s)\n", "an-arg"); const int ret = fclose(file); file = NULL; if (ret) { perror("fclose(file)"); rc = -1; goto out; } if (slurp_for_tests(FNAME, &str)) { perror("slurp_for_tests(FNAME, &str)"); rc = -1; goto out; } const char *const expected = "src/logerr.c:test_vlogerr:400: fn(an-arg)\n"; assert(strcmp(expected, str) == 0); free(str); str = NULL; test_ok(); } { testing("multiple format strings"); file = fopen(FNAME, "w"); if (!file) { perror("fopen(FNAME, \"w\")"); rc = -1; goto out; } #line 500 vlogerr(__FILE__, __func__, __LINE__, file, "int (%d), string (%s) and char (%c)\n", 123, "another-str", 'z'); const int ret = fclose(file); file = NULL; if (ret) { perror("fclose(file)"); rc = -1; goto out; } if (slurp_for_tests(FNAME, &str)) { perror("slurp_for_tests(FNAME, &str)"); rc = -1; goto out; } const char *const expected = "src/logerr.c:test_vlogerr:500: " "int (123), string (another-str) and char (z)\n"; assert(strcmp(expected, str) == 0); free(str); str = NULL; test_ok(); } out: if (str) { free(str); } if (file) { if (fclose(file)) { perror("fclose(file)"); rc = -1; } } return rc; } static int test_logerr(void) { int rc = 0; test_start("logerr()"); { testing("can be called with an empty string"); logerr(""); test_ok(); } { testing("can be called with a static string"); logerr("some err\n"); test_ok(); } { testing("can be called with a formatted string"); logerr("some err: %s\n", strerror(errno)); test_ok(); } { testing("can be called with formatting arguments"); logerr("int: %d\nstr: %s\n", 123, "an example string"); test_ok(); } return rc; } int main(void) { int rc = 0; if (test_vlogerr()) { perror("test_vlogerr()"); rc = -1; goto out; } if (test_logerr()) { perror("test_logerr()"); rc = -1; goto out; } out: return !!rc; } #endif