summaryrefslogtreecommitdiff
path: root/src/logerr.c
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2022-01-28 07:33:30 -0300
committerEuAndreh <eu@euandre.org>2024-01-01 12:35:01 -0300
commit9f554a72b01705ebf6be66143c5e69b09b3c1372 (patch)
treefadf04038b2d5df32fd4b5bc93ba291269c322a0 /src/logerr.c
downloadpindaiba-9f554a72b01705ebf6be66143c5e69b09b3c1372.tar.gz
pindaiba-9f554a72b01705ebf6be66143c5e69b09b3c1372.tar.xz
Init project: copy files and skeletons from others
Diffstat (limited to 'src/logerr.c')
-rw-r--r--src/logerr.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/logerr.c b/src/logerr.c
new file mode 100644
index 0000000..eb160d2
--- /dev/null
+++ b/src/logerr.c
@@ -0,0 +1,314 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "logerr.h"
+
+#ifdef TEST
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "testing.h"
+#include "../tests/slurp.h"
+#endif
+
+
+/**
+ * @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
+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