+#include "config.h"
+
+#include <assert.h>
+#include <float.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dstr.h"
+
+static int win = 0, lose = 0;
+static dstr d = DSTR_INIT;
+static char buf[1024];
+
+static void check(const char *what, const char *want)
+{
+ if (strcmp(want, d.buf) == 0)
+ win++;
+ else {
+ lose++;
+ fprintf(stderr, "test failed: %s\n expected: %s\n found: %s\n",
+ what, want, d.buf);
+ }
+}
+
+static void PRINTF_LIKE(1, 2) format(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ dstr_reset(&d);
+ dstr_vputf(&d, fmt, &ap);
+ va_end(ap);
+}
+
+static void PRINTF_LIKE(1, 2) prepare(const char *fmt, ...)
+{
+ va_list ap;
+ int n;
+
+ va_start(ap, fmt);
+#ifdef HAVE_SNPRINTF
+ n = vsnprintf(buf, sizeof(buf), fmt, ap);
+#else
+ n = vsprintf(buf, fmt, ap);
+#endif
+ assert(0 <= n && n < sizeof(buf));
+}
+
+#define TEST1(fmtargs) do { \
+ format fmtargs; \
+ prepare fmtargs; \
+ check(#fmtargs, buf); \
+} while (0)
+
+#define TEST2(fmtargs, want) do { \
+ format fmtargs; \
+ check(#fmtargs, want); \
+} while (0)
+
+#define LENGTHY \
+ "This is a rather longer string than the code is expecting: will it fit?"
+
+int main(void)
+{
+ TEST2(("Hello, world!"), "Hello, world!");
+ TEST2(("just a ->%%<- sign"), "just a ->%<- sign");
+ TEST2(("Testing, testing, %d, %d, %d.", 1, 2, 3),
+ "Testing, testing, 1, 2, 3.");
+ TEST2(("->%5d<-", 138), "-> 138<-");
+ TEST2(("->%*d<-", 5, 138), "-> 138<-");
+ TEST2(("->%-*d<-", 5, 138), "->138 <-");
+ TEST2(("->%*d<-", -5, 138), "->138 <-");
+ TEST2(("->%-*d<-", -5, 138), "->138 <-");
+ TEST2(("->%.*s<-", 5, "truncate me"), "->trunc<-");
+ TEST2(("->%.*s<-", -5, "don't truncate me"), "->don't truncate me<-");
+ TEST2(("Truncation indirect: ->%.*s<-", 10, "a long string to be chopped"),
+ "Truncation indirect: ->a long str<-");
+ TEST2(("%08lx:%s", 0x65604204ul, "tripe-ec"), "65604204:tripe-ec");
+ TEST2(("%s", LENGTHY), LENGTHY);
+
+ TEST1(("big float: ->%f<- and integer %d\n", DBL_MAX, 42));
+
+ TEST2(("Testing, testing, %3$d, %2$d, %1$d.", 3, 2, 1),
+ "Testing, testing, 1, 2, 3.");
+ TEST2(("Truncation indirect: ->%1$.*2$s<-",
+ "a long string to be chopped", 10),
+ "Truncation indirect: ->a long str<-");
+
+ if (!lose) printf("All tests successful.\n");
+ else printf("FAILED %d of %d tests.\n", lose, win + lose);
+ return (!!lose);
+}