diff options
Diffstat (limited to '')
-rw-r--r-- | src/dns/dns_rr_test.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/dns/dns_rr_test.c b/src/dns/dns_rr_test.c new file mode 100644 index 0000000..7bbe769 --- /dev/null +++ b/src/dns/dns_rr_test.c @@ -0,0 +1,433 @@ + /* + * System library. + */ +#include <sys_defs.h> +#include <stdlib.h> + + /* + * Utility library. + */ +#include <msg.h> +#include <msg_vstream.h> +#include <mymalloc.h> +#include <stringops.h> +#include <vstring.h> + + /* + * DNS library. + */ +#include <dns.h> + +#define STR(x) vstring_str(x) + + /* + * Test helpers. TODO: move eq_dns_rr() to testing/dns_rr_testers.c; need to + * verify that the expected difference is reported, or use a GTEST matcher. + */ + +/* print_dns_rr - format as { qname, reply, flags } */ + +static char *print_dns_rr(VSTRING *buf, DNS_RR *rr) +{ + static VSTRING *tmp; + + if (tmp == 0) + tmp = vstring_alloc(100); + vstring_sprintf(buf, "{qname=%s, reply='%s', flags=0x%x}", + rr->qname, dns_strrecord(tmp, rr), rr->flags); + return (STR(buf)); +} + +/* eq_dns_rr - predicate that two lists are equivalent */ + +static int eq_dns_rr(DNS_RR *got, DNS_RR *want) +{ + VSTRING *got_buf = 0; + VSTRING *want_buf = 0; + +#define EQ_DNS_RR_RETURN(val) do { \ + if (got_buf) \ + vstring_free(got_buf); \ + if (want_buf) \ + vstring_free(want_buf); \ + return (val); \ + } while (0) + + /* Same length. */ + if (got == 0 && want == 0) + EQ_DNS_RR_RETURN(1); + if (want == 0) { + msg_warn("got %s, want null", + print_dns_rr(got_buf = vstring_alloc(100), got)); + } + if (got == 0) { + msg_warn("got null, want %s", + print_dns_rr(want_buf = vstring_alloc(100), want)); + EQ_DNS_RR_RETURN(0); + } + /* Same query name, resource record, flags. */ + if (strcmp(print_dns_rr(got_buf = vstring_alloc(100), got), + print_dns_rr(want_buf = vstring_alloc(100), want)) != 0) { + msg_warn("got %s, want %s", STR(want_buf), STR(got_buf)); + EQ_DNS_RR_RETURN(0); + } + /* Same children. */ + EQ_DNS_RR_RETURN(eq_dns_rr(got->next, want->next)); +} + +static int eq_dns_rr_free(DNS_RR *got, DNS_RR *want) +{ + int res = eq_dns_rr(got, want); + + dns_rr_free(got); + dns_rr_free(want); + return (res); +} + + /* + * Tests and test cases. + */ +typedef struct TEST_CASE { + const char *label; /* identifies test case */ + int (*fn) (void); +} TEST_CASE; + +#define PASS (0) +#define FAIL (1) + + /* + * Begin helper tests. TODO: move these to testing/dns_rr_testers_test.c. + */ + +static int eq_dns_rr_qname_differ(void) +{ + DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 4); + DNS_RR *want = dns_rr_copy(got); + + myfree(want->qname); + want->qname = mystrdup("qb"); + return (!eq_dns_rr_free(got, want)); +} + +static int eq_dns_rr_reply_differ(void) +{ + DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 4); + DNS_RR *want = dns_rr_copy(got); + + want->port += 1; + return (!eq_dns_rr_free(got, want)); +} + + /* + * End helper tests. + */ + + /* + * Begin DNS_RR tests. + */ + +static int eq_dns_rr_flags_differ(void) +{ + DNS_RR *got = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *want = dns_rr_copy(got); + + want->flags |= DNS_RR_FLAG_TRUNCATED; + return (!eq_dns_rr_free(got, want)); +} + +static int append_to_null_from_null(void) +{ + DNS_RR *got = dns_rr_append((DNS_RR *) 0, (DNS_RR *) 0); + DNS_RR *want = 0; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_null(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_copy(a), (DNS_RR *) 0); + + want = a; + + return (eq_dns_rr_free(got, want)); +} + +static int appent_to_null_from_elem(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *got, *want; + + got = dns_rr_append((DNS_RR *) 0, dns_rr_copy(a)); + + want = a; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_elem(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b)); + + (want = a)->next = b; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_list(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_copy(a), + dns_rr_append(dns_rr_copy(b), + dns_rr_copy(c))); + + ((want = a)->next = b)->next = c; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_append(dns_rr_copy(a), + dns_rr_copy(b)), + dns_rr_copy(c)); + + ((want = a)->next = b)->next = c; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_list(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_append(dns_rr_copy(a), + dns_rr_copy(b)), + dns_rr_append(dns_rr_copy(c), + dns_rr_copy(d))); + + (((want = a)->next = b)->next = c)->next = d; + + return (eq_dns_rr_free(got, want)); +} + +static int append_propagates_flags(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *left = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b)); + DNS_RR *rite = dns_rr_append(dns_rr_copy(c), dns_rr_copy(d)); + DNS_RR *got, *want, *rr; + + for (rr = rite; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(left, rite); + + (((want = a)->next = b)->next = c)->next = d; + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_list_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 3; + + ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(dns_rr_append(a, b), + dns_rr_append(c, d)); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem_elem_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 2; + + (want = dns_rr_copy(a))->next = dns_rr_copy(b); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(a, b); + got = dns_rr_append(got, c); /* should be logged */ + got = dns_rr_append(got, d); /* should be silent */ + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 2; + + (want = dns_rr_copy(a))->next = dns_rr_copy(b); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(dns_rr_append(a, b), c); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_list_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 2; + + (want = dns_rr_copy(a))->next = dns_rr_copy(b); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(a, dns_rr_append(b, c)); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem_exact_fit(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + var_dns_rr_list_limit = 3; + + ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c); + + got = dns_rr_append(dns_rr_append(a, b), c); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_list_exact_fit(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + var_dns_rr_list_limit = 3; + + ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c); + + got = dns_rr_append(a, dns_rr_append(b, c)); + + return (eq_dns_rr_free(got, want)); +} + + /* + * The test cases. + */ +static const TEST_CASE test_cases[] = { + + /* + * Test eq_dns_rr; TODO: move to testing/dns_rr_testers_test.c + */ + "eq_dns_rr qname differ", eq_dns_rr_qname_differ, + "eq_dns_rr reply differ", eq_dns_rr_reply_differ, + "eq_dns_rr flags differ", eq_dns_rr_flags_differ, + + /* + * Test dns_rr_append() without truncation. + */ + "append to null from null", append_to_null_from_null, + "append to null from element", appent_to_null_from_elem, + "append to element from null", append_to_elem_from_null, + "append to element from element", append_to_elem_from_elem, + "append to element from list", append_to_elem_from_list, + "append to list from element", append_to_list_from_elem, + "append to list from list", append_to_list_from_list, + + /* + * Test dns_rr_append() flag propagation. + */ + "append propagates flags", append_propagates_flags, + + /* + * Test dns_rr_append() with truncation. + */ + "append to list from list truncate", append_to_list_from_list_truncate, + "append to list from element element truncate", append_to_list_from_elem_elem_truncate, + "append to list from element truncate", append_to_list_from_elem_truncate, + "append to element from list truncate", append_to_elem_from_list_truncate, + "append to list from element exact fit", append_to_list_from_elem_exact_fit, + "append to element from list exact fit", append_to_elem_from_list_exact_fit, + + /* + * TODO: tests dns_rr_sort(), dns_rr_srv_sort(), dns_rr_remove(), + * dns_rr_shuffle(), etc. + */ + 0, +}; + +int main(int argc, char **argv) +{ + const TEST_CASE *tp; + int pass = 0; + int fail = 0; + VSTRING *res_buf = vstring_alloc(100); + int saved_limit = var_dns_rr_list_limit; + + msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR); + + for (tp = test_cases; tp->label != 0; tp++) { + msg_info("RUN %s", tp->label); + if (tp->fn() == 0) { + fail++; + msg_info("FAIL %s", tp->label); + } else { + msg_info("PASS %s", tp->label); + pass++; + } + var_dns_rr_list_limit = saved_limit; + } + msg_info("PASS=%d FAIL=%d", pass, fail); + vstring_free(res_buf); + exit(fail != 0); +} |