From 7e45283246f935b797e1dc419f8882e0d39e3a6b Mon Sep 17 00:00:00 2001 From: David Wragg Date: Wed, 21 Sep 2011 12:10:21 +0100 Subject: Automatically run test_tables in 'make check' This involves making test_tables self-contained. Previously, it would write to stdout, and that output had to be manually compared with test_tables.expected. Now the comparison is automated. --- tests/Makefile.am | 4 +- tests/test_tables.c | 354 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 236 insertions(+), 122 deletions(-) (limited to 'tests') diff --git a/tests/Makefile.am b/tests/Makefile.am index 3bd5e6e..c6c4ed9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,6 @@ -noinst_PROGRAMS = test_tables +check_PROGRAMS = test_tables +TESTS = $(check_PROGRAMS) +EXTRA_DIST = test_tables.expected AM_CFLAGS = -I$(top_srcdir)/librabbitmq diff --git a/tests/test_tables.c b/tests/test_tables.c index 70d42f6..4effd6e 100644 --- a/tests/test_tables.c +++ b/tests/test_tables.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include @@ -46,71 +48,175 @@ #include +void die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + abort(); +} + #define M_PI 3.14159265358979323846264338327 -static void dump_indent(int indent) { +static void dump_indent(int indent, FILE *out) +{ int i; - for (i = 0; i < indent; i++) { putchar(' '); } + + for (i = 0; i < indent; i++) + fputc(' ', out); } -static void dump_value(int indent, amqp_field_value_t v) { - dump_indent(indent); - putchar(v.kind); +static void dump_value(int indent, amqp_field_value_t v, FILE *out) +{ + int i; + + dump_indent(indent, out); + fputc(v.kind, out); + switch (v.kind) { - case AMQP_FIELD_KIND_BOOLEAN: puts(v.value.boolean ? " true" : " false"); break; - case AMQP_FIELD_KIND_I8: printf(" %"PRId8"\n", v.value.i8); break; - case AMQP_FIELD_KIND_U8: printf(" %"PRIu8"\n", v.value.u8); break; - case AMQP_FIELD_KIND_I16: printf(" %"PRId16"\n", v.value.i16); break; - case AMQP_FIELD_KIND_U16: printf(" %"PRIu16"\n", v.value.u16); break; - case AMQP_FIELD_KIND_I32: printf(" %"PRId32"\n", v.value.i32); break; - case AMQP_FIELD_KIND_U32: printf(" %"PRIu32"\n", v.value.u32); break; - case AMQP_FIELD_KIND_I64: printf(" %"PRId64"\n", v.value.i64); break; - case AMQP_FIELD_KIND_F32: printf(" %g\n", (double) v.value.f32); break; - case AMQP_FIELD_KIND_F64: printf(" %g\n", v.value.f64); break; - case AMQP_FIELD_KIND_DECIMAL: - printf(" %d:::%u\n", v.value.decimal.decimals, v.value.decimal.value); break; - case AMQP_FIELD_KIND_UTF8: - printf(" %.*s\n", (int) v.value.bytes.len, (char *) v.value.bytes.bytes); break; - case AMQP_FIELD_KIND_BYTES: - { - int i; - putchar(' '); - for (i = 0; i < v.value.bytes.len; i++) { - printf("%02x", ((char *) v.value.bytes.bytes)[i]); - } - putchar('\n'); - } - break; - case AMQP_FIELD_KIND_ARRAY: - putchar('\n'); - { - int i; - for (i = 0; i < v.value.array.num_entries; i++) { - dump_value(indent + 2, v.value.array.entries[i]); - } - } - break; - case AMQP_FIELD_KIND_TIMESTAMP: printf(" %"PRIu64"\n", v.value.u64); break; - case AMQP_FIELD_KIND_TABLE: - putchar('\n'); - { - int i; - for (i = 0; i < v.value.table.num_entries; i++) { - dump_indent(indent + 2); - printf("%.*s ->\n", - (int) v.value.table.entries[i].key.len, - (char *) v.value.table.entries[i].key.bytes); - dump_value(indent + 4, v.value.table.entries[i].value); - } - } - break; - case AMQP_FIELD_KIND_VOID: putchar('\n'); break; - default: - printf("???\n"); - break; + case AMQP_FIELD_KIND_BOOLEAN: + fputs(v.value.boolean ? " true\n" : " false\n", out); + break; + + case AMQP_FIELD_KIND_I8: + fprintf(out, " %"PRId8"\n", v.value.i8); + break; + + case AMQP_FIELD_KIND_U8: + fprintf(out, " %"PRIu8"\n", v.value.u8); + break; + + case AMQP_FIELD_KIND_I16: + fprintf(out, " %"PRId16"\n", v.value.i16); + break; + + case AMQP_FIELD_KIND_U16: + fprintf(out, " %"PRIu16"\n", v.value.u16); + break; + + case AMQP_FIELD_KIND_I32: + fprintf(out, " %"PRId32"\n", v.value.i32); + break; + + case AMQP_FIELD_KIND_U32: + fprintf(out, " %"PRIu32"\n", v.value.u32); + break; + + case AMQP_FIELD_KIND_I64: + fprintf(out, " %"PRId64"\n", v.value.i64); + break; + + case AMQP_FIELD_KIND_F32: + fprintf(out, " %g\n", (double) v.value.f32); + break; + + case AMQP_FIELD_KIND_F64: + fprintf(out, " %g\n", v.value.f64); + break; + + case AMQP_FIELD_KIND_DECIMAL: + fprintf(out, " %d:::%u\n", v.value.decimal.decimals, + v.value.decimal.value); + break; + + case AMQP_FIELD_KIND_UTF8: + fprintf(out, " %.*s\n", (int)v.value.bytes.len, + (char *)v.value.bytes.bytes); + break; + + case AMQP_FIELD_KIND_BYTES: + fputc(' ', out); + for (i = 0; i < v.value.bytes.len; i++) + fprintf(out, "%02x", ((char *) v.value.bytes.bytes)[i]); + + fputc('\n', out); + break; + + case AMQP_FIELD_KIND_ARRAY: + fputc('\n', out); + for (i = 0; i < v.value.array.num_entries; i++) + dump_value(indent + 2, v.value.array.entries[i], out); + + break; + + case AMQP_FIELD_KIND_TIMESTAMP: + fprintf(out, " %"PRIu64"\n", v.value.u64); + break; + + case AMQP_FIELD_KIND_TABLE: + fputc('\n', out); + for (i = 0; i < v.value.table.num_entries; i++) { + dump_indent(indent + 2, out); + fprintf(out, "%.*s ->\n", + (int)v.value.table.entries[i].key.len, + (char *)v.value.table.entries[i].key.bytes); + dump_value(indent + 4, v.value.table.entries[i].value, out); + } + + break; + + case AMQP_FIELD_KIND_VOID: + fputc('\n', out); + break; + + default: + fprintf(out, "???\n"); + break; } } +static void test_dump_value(FILE *out) +{ + amqp_table_entry_t entries[8]; + amqp_table_t table; + amqp_field_value_t val; + + entries[0].key = amqp_cstring_bytes("zebra"); + entries[0].value.kind = AMQP_FIELD_KIND_UTF8; + entries[0].value.value.bytes = amqp_cstring_bytes("last"); + + entries[1].key = amqp_cstring_bytes("aardvark"); + entries[1].value.kind = AMQP_FIELD_KIND_UTF8; + entries[1].value.value.bytes = amqp_cstring_bytes("first"); + + entries[2].key = amqp_cstring_bytes("middle"); + entries[2].value.kind = AMQP_FIELD_KIND_UTF8; + entries[2].value.value.bytes = amqp_cstring_bytes("third"); + + entries[3].key = amqp_cstring_bytes("number"); + entries[3].value.kind = AMQP_FIELD_KIND_I32; + entries[3].value.value.i32 = 1234; + + entries[4].key = amqp_cstring_bytes("decimal"); + entries[4].value.kind = AMQP_FIELD_KIND_DECIMAL; + entries[4].value.value.decimal.decimals = 2; + entries[4].value.value.decimal.value = 1234; + + entries[5].key = amqp_cstring_bytes("time"); + entries[5].value.kind = AMQP_FIELD_KIND_TIMESTAMP; + entries[5].value.value.u64 = 1234123412341234; + + entries[6].key = amqp_cstring_bytes("beta"); + entries[6].value.kind = AMQP_FIELD_KIND_UTF8; + entries[6].value.value.bytes = amqp_cstring_bytes("second"); + + entries[7].key = amqp_cstring_bytes("wombat"); + entries[7].value.kind = AMQP_FIELD_KIND_UTF8; + entries[7].value.value.bytes = amqp_cstring_bytes("fourth"); + + table.num_entries = 8; + table.entries = entries; + + qsort(table.entries, table.num_entries, sizeof(amqp_table_entry_t), &amqp_table_entry_cmp); + + val.kind = AMQP_FIELD_KIND_TABLE; + val.value.table = table; + + dump_value(0, val, out); +} + static uint8_t pre_encoded_table[] = { 0x00, 0x00, 0x00, 0xff, 0x07, 0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x72, 0x53, 0x00, 0x00, 0x00, @@ -147,7 +253,8 @@ static uint8_t pre_encoded_table[] = { 0x44, 0x2d, 0x18 }; -static void test_table_codec(void) { +static void test_table_codec(FILE *out) +{ amqp_pool_t pool; int result; @@ -239,13 +346,13 @@ static void test_table_codec(void) { table.num_entries = 14; table.entries = entries; - printf("AAAAAAAAAA\n"); + fprintf(out, "AAAAAAAAAA\n"); { amqp_field_value_t val; val.kind = AMQP_FIELD_KIND_TABLE; val.value.table = table; - dump_value(0, val); + dump_value(0, val, out); } init_amqp_pool(&pool, 4096); @@ -257,21 +364,19 @@ static void test_table_codec(void) { decoding_bytes.len = sizeof(pre_encoded_table); decoding_bytes.bytes = pre_encoded_table; - result = amqp_decode_table(decoding_bytes, &pool, &decoded, &decoding_offset); - if (result < 0) { - char *errstr = amqp_error_string(-result); - printf("Table decoding failed: %d (%s)\n", result, errstr); - free(errstr); - abort(); - } - printf("BBBBBBBBBB\n"); + result = amqp_decode_table(decoding_bytes, &pool, &decoded, + &decoding_offset); + if (result < 0) + die("Table decoding failed: %s", amqp_error_string(-result)); + + fprintf(out, "BBBBBBBBBB\n"); { amqp_field_value_t val; val.kind = AMQP_FIELD_KIND_TABLE; val.value.table = decoded; - dump_value(0, val); + dump_value(0, val, out); } } @@ -285,81 +390,88 @@ static void test_table_codec(void) { encoding_result.bytes = &encoding_buffer[0]; result = amqp_encode_table(encoding_result, &table, &offset); - if (result < 0) { - char *errstr = amqp_error_string(-result); - printf("Table encoding failed: %d (%s)\n", result, errstr); - free(errstr); - abort(); - } + if (result < 0) + die("Table encoding failed: %s", amqp_error_string(-result)); - if (offset != sizeof(pre_encoded_table)) { - printf("Offset should be %d, was %d\n", (int) sizeof(pre_encoded_table), (int)offset); - abort(); - } + if (offset != sizeof(pre_encoded_table)) + die("Offset should be %ld, was %ld", (long)sizeof(pre_encoded_table), + (long)offset); result = memcmp(pre_encoded_table, encoding_buffer, offset); - if (result != 0) { - printf("Table encoding differed, result = %d\n", result); - abort(); - } + if (result != 0) + die("Table encoding differed", result); } empty_amqp_pool(&pool); } -int main(int argc, char const * const *argv) { - amqp_table_entry_t entries[8]; - amqp_table_t table; +#define CHUNK_SIZE 4096 - entries[0].key = amqp_cstring_bytes("zebra"); - entries[0].value.kind = AMQP_FIELD_KIND_UTF8; - entries[0].value.value.bytes = amqp_cstring_bytes("last"); +static int compare_files(const char *f1, const char *f2) +{ + FILE *f1_in; + FILE *f2_in; + char f1_buf[CHUNK_SIZE]; + char f2_buf[CHUNK_SIZE]; + int res; - entries[1].key = amqp_cstring_bytes("aardvark"); - entries[1].value.kind = AMQP_FIELD_KIND_UTF8; - entries[1].value.value.bytes = amqp_cstring_bytes("first"); + f1_in = fopen(f1, "r"); + if (f1_in == NULL) + die("opening %s: %s", f1, strerror(errno)); - entries[2].key = amqp_cstring_bytes("middle"); - entries[2].value.kind = AMQP_FIELD_KIND_UTF8; - entries[2].value.value.bytes = amqp_cstring_bytes("third"); + f2_in = fopen(f2, "r"); + if (f2_in == NULL) + die("opening %s: %s", f2, strerror(errno)); - entries[3].key = amqp_cstring_bytes("number"); - entries[3].value.kind = AMQP_FIELD_KIND_I32; - entries[3].value.value.i32 = 1234; + for (;;) { + size_t f1_got = fread(f1_buf, 1, CHUNK_SIZE, f1_in); + size_t f2_got = fread(f2_buf, 1, CHUNK_SIZE, f2_in); + res = memcmp(f1_buf, f2_buf, f1_got < f2_got ? f1_got : f2_got); - entries[4].key = amqp_cstring_bytes("decimal"); - entries[4].value.kind = AMQP_FIELD_KIND_DECIMAL; - entries[4].value.value.decimal.decimals = 2; - entries[4].value.value.decimal.value = 1234; + if (res) + break; - entries[5].key = amqp_cstring_bytes("time"); - entries[5].value.kind = AMQP_FIELD_KIND_TIMESTAMP; - entries[5].value.value.u64 = 1234123412341234; + if (f1_got < CHUNK_SIZE || f2_got < CHUNK_SIZE) { + if (f1_got != f2_got) + res = (f1_got < f2_got ? -1 : 1); + break; + } + } - entries[6].key = amqp_cstring_bytes("beta"); - entries[6].value.kind = AMQP_FIELD_KIND_UTF8; - entries[6].value.value.bytes = amqp_cstring_bytes("second"); + fclose(f1_in); + fclose(f2_in); - entries[7].key = amqp_cstring_bytes("wombat"); - entries[7].value.kind = AMQP_FIELD_KIND_UTF8; - entries[7].value.value.bytes = amqp_cstring_bytes("fourth"); + return res; +} - table.num_entries = 8; - table.entries = entries; +const char *expected_file_name = "test_tables.expected"; - test_table_codec(); +int main(int argc, char **argv) +{ + char *srcdir = getenv("srcdir"); + char out_path[L_tmpnam]; + FILE *out = fopen(tmpnam(out_path), "w"); + char *expected_path; - qsort(table.entries, table.num_entries, sizeof(amqp_table_entry_t), &amqp_table_entry_cmp); + if (out == NULL) + die("opening %s: %s", out_path, strerror(errno)); - printf("----------\n"); + test_table_codec(out); + fprintf(out, "----------\n"); + test_dump_value(out); - { - amqp_field_value_t val; - val.kind = AMQP_FIELD_KIND_TABLE; - val.value.table = table; + fclose(out); - dump_value(0, val); - } + if (srcdir == NULL) + die("'srcdir' environment variable not defined"); + + expected_path = malloc(strlen(srcdir) + strlen(expected_file_name) + 2); + sprintf(expected_path, "%s/%s", srcdir, expected_file_name); + if (compare_files(expected_path, out_path)) + die("output file did not have expected contents; see %s", out_path); + + if (remove(out_path)) + die("deleting %s: %s", out_path, strerror(errno)); return 0; } -- cgit v1.2.1