summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--testapp.c47
-rw-r--r--util.c17
-rw-r--r--util.h15
3 files changed, 78 insertions, 1 deletions
diff --git a/testapp.c b/testapp.c
index c6b46c6..9afcf39 100644
--- a/testapp.c
+++ b/testapp.c
@@ -22,6 +22,8 @@
#include "cache.h"
#include "util.h"
+#define TMP_TEMPLATE "/tmp/test_file.XXXXXXX"
+
enum test_return { TEST_SKIP, TEST_PASS, TEST_FAIL };
static enum test_return cache_create_test(void)
@@ -387,6 +389,50 @@ static int connect_server(const char *hostname, in_port_t port)
return sock;
}
+static enum test_return test_vperror(void) {
+ int rv = 0;
+ int oldstderr = dup(STDERR_FILENO);
+ char tmpl[sizeof(TMP_TEMPLATE)+1];
+ strncpy(tmpl, TMP_TEMPLATE, sizeof(TMP_TEMPLATE)+1);
+
+ int newfile = mkstemp(tmpl);
+ assert(newfile > 0);
+ rv = dup2(newfile, STDERR_FILENO);
+ assert(rv == STDERR_FILENO);
+ rv = close(newfile);
+ assert(rv == 0);
+
+ errno = EIO;
+ vperror("Old McDonald had a farm. %s", "EI EIO");
+
+ /* Restore stderr */
+ rv = dup2(oldstderr, STDERR_FILENO);
+ assert(rv == STDERR_FILENO);
+
+
+ /* Go read the file */
+ char buf[80] = { 0 };
+ FILE *efile = fopen(tmpl, "r");
+ assert(efile);
+ char *prv = fgets(buf, sizeof(buf), efile);
+ assert(prv);
+ fclose(efile);
+
+ unlink(tmpl);
+
+ char expected[80] = { 0 };
+ snprintf(expected, sizeof(expected),
+ "Old McDonald had a farm. EI EIO: %s\n", strerror(EIO));
+
+ /*
+ fprintf(stderr,
+ "\nExpected: ``%s''"
+ "\nGot: ``%s''\n", expected, buf);
+ */
+
+ return strcmp(expected, buf) == 0 ? TEST_PASS : TEST_FAIL;
+}
+
static enum test_return test_issue_72(void) {
in_port_t port;
@@ -435,6 +481,7 @@ struct testcase testcases[] = {
{ "strtoull", test_safe_strtoull },
{ "issue_44", test_issue_44 },
{ "issue_72", test_issue_72 },
+ { "vperror", test_vperror },
{ NULL, NULL }
};
diff --git a/util.c b/util.c
index 307f7f0..083bff4 100644
--- a/util.c
+++ b/util.c
@@ -1,9 +1,10 @@
-#include <stdlib.h>
+#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#include <stdarg.h>
#include "memcached.h"
@@ -88,3 +89,17 @@ bool safe_strtol(const char *str, int32_t *out) {
}
return false;
}
+
+void vperror(const char *fmt, ...) {
+ int old_errno = errno;
+ char buf[80];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ errno = old_errno;
+
+ perror(buf);
+}
diff --git a/util.h b/util.h
index 9af886d..b89d15e 100644
--- a/util.h
+++ b/util.h
@@ -11,3 +11,18 @@ bool safe_strtoull(const char *str, uint64_t *out);
bool safe_strtoll(const char *str, int64_t *out);
bool safe_strtoul(const char *str, uint32_t *out);
bool safe_strtol(const char *str, int32_t *out);
+
+#ifdef __GCC
+# define __gcc_attribute__ __attribute__
+#else
+# define __gcc_attribute__(x)
+#endif
+
+/**
+ * Vararg variant of perror that makes for more useful error messages
+ * when reporting with parameters.
+ *
+ * @param fmt a printf format
+ */
+void vperror(const char *fmt, ...)
+ __gcc_attribute__ ((format (printf, 1, 2)));