| 1 | #include "config.h" |
| 2 | |
| 3 | #include <assert.h> |
| 4 | #include <float.h> |
| 5 | #include <stdarg.h> |
| 6 | #include <stdio.h> |
| 7 | #include <stdlib.h> |
| 8 | #include <string.h> |
| 9 | |
| 10 | #include "dstr.h" |
| 11 | #include "macros.h" |
| 12 | #include "report.h" |
| 13 | #include "tvec.h" |
| 14 | |
| 15 | static struct tvec_state tvstate; |
| 16 | static dstr d = DSTR_INIT; |
| 17 | static char strbuf[1024]; |
| 18 | |
| 19 | #define TESTGROUP(name) TVEC_TESTGROUP_TAG(grp, &tvstate, name) |
| 20 | |
| 21 | static void PRINTF_LIKE(1, 2) format(const char *fmt, ...) |
| 22 | { |
| 23 | va_list ap; |
| 24 | va_start(ap, fmt); |
| 25 | dstr_reset(&d); |
| 26 | dstr_vputf(&d, fmt, &ap); |
| 27 | va_end(ap); |
| 28 | } |
| 29 | |
| 30 | static void PRINTF_LIKE(1, 2) prepare(const char *fmt, ...) |
| 31 | { |
| 32 | va_list ap; |
| 33 | int n; |
| 34 | |
| 35 | va_start(ap, fmt); |
| 36 | #ifdef HAVE_SNPRINTF |
| 37 | n = vsnprintf(strbuf, sizeof(strbuf), fmt, ap); |
| 38 | #else |
| 39 | n = vsprintf(strbuf, fmt, ap); |
| 40 | #endif |
| 41 | assert(0 <= n && n < sizeof(strbuf)); |
| 42 | } |
| 43 | |
| 44 | #define TEST_KNOWN(fmtargs, want) do { \ |
| 45 | format fmtargs; \ |
| 46 | tvec_claimeq_string(&tvstate, d.buf, d.len, want, strlen(want), \ |
| 47 | __FILE__, __LINE__, "format " #fmtargs); \ |
| 48 | } while (0) |
| 49 | |
| 50 | #define TEST_REF(fmtargs) do { \ |
| 51 | format fmtargs; \ |
| 52 | prepare fmtargs; \ |
| 53 | tvec_claimeq_string(&tvstate, d.buf, d.len, strbuf, strlen(strbuf), \ |
| 54 | __FILE__, __LINE__, "format " #fmtargs); \ |
| 55 | } while (0) |
| 56 | |
| 57 | #define LENGTHY \ |
| 58 | "This is a rather longer string than the code is expecting: will it fit?" |
| 59 | |
| 60 | int main(int argc, char *argv[]) |
| 61 | { |
| 62 | struct tvec_test test; |
| 63 | int argpos; |
| 64 | |
| 65 | tvec_parseargs(argc, argv, &tvstate, &argpos, &tvec_adhocconfig); |
| 66 | if (argpos < argc) die(2, "no input files expected"); |
| 67 | tvec_adhoc(&tvstate, &test); |
| 68 | |
| 69 | TESTGROUP("basics") { |
| 70 | TEST_KNOWN(("Hello, world!"), "Hello, world!"); |
| 71 | TEST_KNOWN(("just a ->%%<- sign"), "just a ->%<- sign"); |
| 72 | } |
| 73 | |
| 74 | TESTGROUP("integers") { |
| 75 | TEST_KNOWN(("Testing, testing, %d, %d, %d.", 1, 2, 3), |
| 76 | "Testing, testing, 1, 2, 3."); |
| 77 | TEST_KNOWN(("->%5d<-", 138), "-> 138<-"); |
| 78 | TEST_KNOWN(("->%*d<-", 5, 138), "-> 138<-"); |
| 79 | TEST_KNOWN(("->%-*d<-", 5, 138), "->138 <-"); |
| 80 | TEST_KNOWN(("->%*d<-", -5, 138), "->138 <-"); |
| 81 | TEST_KNOWN(("->%-*d<-", -5, 138), "->138 <-"); |
| 82 | } |
| 83 | |
| 84 | TESTGROUP("strings") { |
| 85 | TEST_KNOWN(("->%.*s<-", 5, "truncate me"), "->trunc<-"); |
| 86 | TEST_KNOWN(("->%.*s<-", -5, "don't truncate me"), |
| 87 | "->don't truncate me<-"); |
| 88 | TEST_KNOWN(("Truncation indirect: ->%.*s<-", 10, |
| 89 | "a long string to be chopped"), |
| 90 | "Truncation indirect: ->a long str<-"); |
| 91 | } |
| 92 | |
| 93 | TESTGROUP("combinations") { |
| 94 | TEST_KNOWN(("%08lx:%s", 0x65604204ul, "tripe-ec"), "65604204:tripe-ec"); |
| 95 | TEST_REF(("big float: ->%f<- and integer %d\n", DBL_MAX, 42)); |
| 96 | } |
| 97 | |
| 98 | TESTGROUP("argument-order") { |
| 99 | TEST_KNOWN(("Testing, testing, %3$d, %2$d, %1$d.", 3, 2, 1), |
| 100 | "Testing, testing, 1, 2, 3."); |
| 101 | TEST_KNOWN(("Truncation indirect: ->%1$.*2$s<-", |
| 102 | "a long string to be chopped", 10), |
| 103 | "Truncation indirect: ->a long str<-"); |
| 104 | } |
| 105 | |
| 106 | TESTGROUP("misc") |
| 107 | TEST_KNOWN(("%s", LENGTHY), LENGTHY); |
| 108 | |
| 109 | return (tvec_end(&tvstate)); |
| 110 | } |