From 6d0bc40a132e2337bc80b20a1125eaedb81ee546 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 17 Dec 2013 16:03:10 -0500 Subject: [PATCH 01/35] Added unit test program that uses check. --- src/test/Makefile.in | 11 +- src/test/check_getdns_general_sync.c | 614 +++++++++++++++++++++++++++ 2 files changed, 622 insertions(+), 3 deletions(-) create mode 100644 src/test/check_getdns_general_sync.c diff --git a/src/test/Makefile.in b/src/test/Makefile.in index b16ca313..67890798 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -18,8 +18,8 @@ VPATH = @srcdir@ CC=gcc CFLAGS=@CFLAGS@ -Wall -I$(srcdir)/ -I$(srcdir)/../ -I/usr/local/include -std=c99 $(cflags) LDFLAGS=@LDFLAGS@ -L. -L.. -L/usr/local/lib -LDLIBS=-lgetdns @LIBS@ -PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync +LDLIBS=-lgetdns @LIBS@ -lcheck +PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns_general_sync .SUFFIXES: .c .o .a .lo .h @@ -40,7 +40,12 @@ tests_stub_async: tests_stub_async.o testmessages.o $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_stub_async.o testmessages.o tests_stub_sync: tests_stub_sync.o - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_stub_sync.o + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_stub_sync.o + +check_getdns_general_sync: check_getdns_general_sync.o + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_general_sync.o + + test: all ./testscript.sh diff --git a/src/test/check_getdns_general_sync.c b/src/test/check_getdns_general_sync.c new file mode 100644 index 00000000..43171873 --- /dev/null +++ b/src/test/check_getdns_general_sync.c @@ -0,0 +1,614 @@ +#include +#include +#include +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 +#define MAXLEN 200 + +struct extracted_response { + uint32_t top_answer_type; + struct getdns_bindata *top_canonical_name; + struct getdns_list *just_address_answers; + struct getdns_list *replies_full; + struct getdns_list *replies_tree; + struct getdns_dict *replies_tree_sub_dict; + struct getdns_list *additional; + struct getdns_list *answer; + uint32_t answer_type; + struct getdns_list *authority; + struct getdns_bindata *canonical_name; + struct getdns_dict *header; + struct getdns_dict *question; + uint32_t status; +}; + +/* + * The STANDARD_TEST_DECLARATIONS macro defines + * ithe standard variable definitions most tests + * will need. + * + */ +#define STANDARD_TEST_DECLARATIONS \ + struct getdns_context *context = NULL; \ + struct getdns_dict *response = NULL; \ + size_t buflen = MAXLEN; \ + char error_string[MAXLEN]; + +/* + * The ASSERT_RC macro is used to assert + * whether the return code from the last + * getdns API call is what was expected. + */ +#define ASSERT_RC(rc, expected_rc, prefix) \ + getdns_strerror(rc, error_string, buflen); \ + ck_assert_msg(rc == expected_rc, \ + "%s: expecting %s: %d, but received: %d: %s", \ + prefix, #expected_rc, expected_rc, rc, error_string); + +/* + * The CONTEXT_CREATE macro is used to \ + * create a context and assert the proper \ + * return code is returned. \ + */ \ +#define CONTEXT_CREATE \ + ASSERT_RC(getdns_context_create(&context, TRUE), \ + GETDNS_RETURN_GOOD, \ + "Return code from getdns_context_create()"); + +/* \ + * The process_response macro declares the \ + * variables needed to house the response and \ + * calls the function that extracts it. \ + */ \ +#define EXTRACT_RESPONSE \ + struct extracted_response ex_response; \ + extract_response(response, &ex_response); + +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); +void assert_noerror(struct extracted_response *ex_response); +void assert_nodata(struct extracted_response *ex_response); +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); +void assert_nxdomain(struct extracted_response *ex_response); +void assert_soa_in_authority(struct extracted_response *ex_response); +void assert_ptr_in_answer(struct extracted_response *ex_response); + +START_TEST (getdns_general_sync_1) +{ + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + STANDARD_TEST_DECLARATIONS; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general_sync()"); +} +END_TEST + +START_TEST (getdns_general_sync_2) +{ + /* + * name = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); +} +END_TEST + +START_TEST (getdns_general_sync_3) +{ + /* + * name = invalid domain (too many octets) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); +} +END_TEST + +START_TEST (getdns_general_sync_4) +{ + /* + * name = invalid domain (label too long) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); +} +END_TEST + +START_TEST (getdns_general_sync_5) +{ + /* + * response = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); +} +END_TEST + +START_TEST (getdns_general_sync_6) +{ + /* + * name = "google.com" + * request_type = 0 (minimum valid RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", 0, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_nodata(&ex_response); +} +END_TEST + +START_TEST (getdns_general_sync_7) +{ + /* + * name = "google.com" + * request_type = 65279 (maximum unassigned RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", 65279, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_nodata(&ex_response); +} +END_TEST + +START_TEST (getdns_general_sync_8) +{ + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); +} +END_TEST + +START_TEST (getdns_general_sync_9) +{ + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_AAAA + * expect: NOERROR response with AAAA records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of AAAA records ("type": 28) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, FALSE, TRUE); +} +END_TEST + +START_TEST (getdns_general_sync_10) +{ + /* + * name = "thisdomainsurelydoesntexist.com" + * request_type = GETDNS_RRTYPE_TXT` + * expect: NXDOMAIN response with SOA record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 3 + * ancount = 0 (number of records in ANSWER section) + * nscount = 1 (number of records in AUTHORITY section) + * and SOA record ("type": 6) present in "authority" list + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "thisdomainsurelydoesntexist.com"; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_TXT, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); +} +END_TEST + +START_TEST (getdns_general_sync_11) +{ + /* + * name = "hampster.com" need to replace this with domain from unbound zone + * request_type = GETDNS_RRTYPE_MX + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_nodata(&ex_response); +} +END_TEST + +START_TEST (getdns_general_sync_12) +{ + /* + * name = "google.com" need to swap this out for max domain name length with max lable length` + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); +} +END_TEST + +START_TEST (getdns_general_sync_13) +{ + /* + * name = "75.101.146.66" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); +} +END_TEST + +START_TEST (getdns_general_sync_14) +{ + /* + * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); +} +END_TEST + +Suite * +getdns_general_sync_suite (void) +{ + Suite *s = suite_create ("getdns_general_sync()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_general_sync_1); + tcase_add_test(tc_neg, getdns_general_sync_2); + tcase_add_test(tc_neg, getdns_general_sync_3); + tcase_add_test(tc_neg, getdns_general_sync_4); + tcase_add_test(tc_neg, getdns_general_sync_5); + suite_add_tcase(s, tc_neg); + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + + tcase_add_test(tc_pos, getdns_general_sync_6); + tcase_add_test(tc_pos, getdns_general_sync_7); + tcase_add_test(tc_pos, getdns_general_sync_8); + tcase_add_test(tc_pos, getdns_general_sync_9); + tcase_add_test(tc_pos, getdns_general_sync_10); + tcase_add_test(tc_pos, getdns_general_sync_11); + tcase_add_test(tc_pos, getdns_general_sync_12); + tcase_add_test(tc_pos, getdns_general_sync_13); + tcase_add_test(tc_pos, getdns_general_sync_14); + suite_add_tcase(s, tc_pos); + + return s; +} + +/* + * extract_response extracts all of the various information + * a test may want to look at from the response. + */ +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + + ck_assert_msg(response != NULL, "Response should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); + + ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); + + ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), + GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); + ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); + ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); + ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); + + ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); + ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), + GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); + ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); + ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); + ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); + + ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), + GETDNS_RETURN_GOOD, "Failed to extract \"header\""); + ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), + GETDNS_RETURN_GOOD, "Failed to extract \"question\""); + ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), + GETDNS_RETURN_GOOD, "Failed to extract \"status\""); +} + +/* + * assert_noerror asserts that the rcode is 0 + */ +void assert_noerror(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_nodata asserts that ancount in the header and the + * of the answer section (list) are both zero. + */ +void assert_nodata(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); +} + +/* + * assert_address_records_in_answer asserts that ancount in the header + * is >= 1, ancount is equal to the length of "answer", and that all of + * the records in the answer section are A and/or AAAA resource records + * based on the value of the a/aaaa arguments. + */ +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t address_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + switch (type) + { + case GETDNS_RRTYPE_A: + if(a && type == GETDNS_RRTYPE_A) + address_records++; + case GETDNS_RRTYPE_AAAA: + if(aaaa && type == GETDNS_RRTYPE_AAAA) + address_records++; + } + } + ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", + ancount, address_records); +} + +/* + * assert_nxdomain asserts that an NXDOMAIN response was + * was returned for the DNS query meaning: + * rcode == 3 + */ +void assert_nxdomain(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_soa_in_authority asserts that a SOA record was + * returned in the authority sections. + */ +void assert_soa_in_authority(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t nscount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t soa_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); + + ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); + ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); + if(type == GETDNS_RRTYPE_SOA) + soa_records++; + } + + ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); +} + +/* + * assert_ptr_in_answer asserts that a PTR record was + * returned in the answer sections. + */ +void assert_ptr_in_answer(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t ptr_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + if(type == GETDNS_RRTYPE_PTR) + ptr_records++; + } + + ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); +} + +int +main (void) +{ + int number_failed; + Suite *s = getdns_general_sync_suite(); + SRunner *sr = srunner_create(s); + srunner_set_log(sr, "getdns_general_sync_test.log"); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} From ae3b661ed9e43b34024286aa5a2786d2111a863a Mon Sep 17 00:00:00 2001 From: Bryan Graham Date: Tue, 17 Dec 2013 19:50:40 -0500 Subject: [PATCH 02/35] added check_getdns_address_sync.c --- src/test/Makefile.in | 4 +- src/test/check_getdns_address_sync.c | 566 +++++++++++++++++++++++++++ 2 files changed, 569 insertions(+), 1 deletion(-) create mode 100644 src/test/check_getdns_address_sync.c diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 67890798..a993923b 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -19,7 +19,7 @@ CC=gcc CFLAGS=@CFLAGS@ -Wall -I$(srcdir)/ -I$(srcdir)/../ -I/usr/local/include -std=c99 $(cflags) LDFLAGS=@LDFLAGS@ -L. -L.. -L/usr/local/lib LDLIBS=-lgetdns @LIBS@ -lcheck -PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns_general_sync +PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns_general_sync check_getdns_address_sync .SUFFIXES: .c .o .a .lo .h @@ -45,6 +45,8 @@ tests_stub_sync: tests_stub_sync.o check_getdns_general_sync: check_getdns_general_sync.o $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_general_sync.o +check_getdns_address_sync: check_getdns_address_sync.o + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_address_sync.o test: all diff --git a/src/test/check_getdns_address_sync.c b/src/test/check_getdns_address_sync.c new file mode 100644 index 00000000..1e1ffab9 --- /dev/null +++ b/src/test/check_getdns_address_sync.c @@ -0,0 +1,566 @@ +#include +#include +#include +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 +#define MAXLEN 200 + +struct extracted_response { + uint32_t top_answer_type; + struct getdns_bindata *top_canonical_name; + struct getdns_list *just_address_answers; + struct getdns_list *replies_full; + struct getdns_list *replies_tree; + struct getdns_dict *replies_tree_sub_dict; + struct getdns_list *additional; + struct getdns_list *answer; + uint32_t answer_type; + struct getdns_list *authority; + struct getdns_bindata *canonical_name; + struct getdns_dict *header; + struct getdns_dict *question; + uint32_t status; +}; + +/* + * The STANDARD_TEST_DECLARATIONS macro defines + * the standard variable definitions most tests + * will need. + * + */ +#define STANDARD_TEST_DECLARATIONS \ + struct getdns_context *context = NULL; \ + struct getdns_dict *response = NULL; \ + size_t buflen = MAXLEN; \ + char error_string[MAXLEN]; + +/* + * The ASSERT_RC macro is used to assert + * whether the return code from the last + * getdns API call is what was expected. + */ +#define ASSERT_RC(rc, expected_rc, prefix) \ + getdns_strerror(rc, error_string, buflen); \ + ck_assert_msg(rc == expected_rc, \ + "%s: expecting %s: %d, but received: %d: %s", \ + prefix, #expected_rc, expected_rc, rc, error_string); + +/* + * The CONTEXT_CREATE macro is used to \ + * create a context and assert the proper \ + * return code is returned. \ + */ \ +#define CONTEXT_CREATE \ + ASSERT_RC(getdns_context_create(&context, TRUE), \ + GETDNS_RETURN_GOOD, \ + "Return code from getdns_context_create()"); + +/* \ + * The process_response macro declares the \ + * variables needed to house the response and \ + * calls the function that extracts it. \ + */ \ +#define EXTRACT_RESPONSE \ + struct extracted_response ex_response; \ + extract_response(response, &ex_response); + +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); +void assert_noerror(struct extracted_response *ex_response); +void assert_nodata(struct extracted_response *ex_response); +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); +void assert_nxdomain(struct extracted_response *ex_response); +void assert_soa_in_authority(struct extracted_response *ex_response); +void assert_ptr_in_answer(struct extracted_response *ex_response); + +START_TEST (getdns_address_sync_1) +{ + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + STANDARD_TEST_DECLARATIONS; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_address_sync()"); +} +END_TEST + +START_TEST (getdns_address_sync_2) +{ + /* + * name = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); +} +END_TEST + +START_TEST (getdns_address_sync_3) +{ + /* + * name = invalid domain (too many octets) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, name, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); +} +END_TEST + +START_TEST (getdns_address_sync_4) +{ + /* + * name = invalid domain (label too long) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, name, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); +} +END_TEST + +START_TEST (getdns_address_sync_5) +{ + /* + * response = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); +} +END_TEST + +START_TEST (getdns_address_sync_6) +{ + /* + * name = "google.com" + * expect: NOERROR response: + * status = GETDNS_RETURN_GOOD + * rcode = 0 + todo: create zonefile with exact count + * ancount = tbd (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); +} +END_TEST + +START_TEST (getdns_address_sync_7) +{ + /* + * name = "localhost" + * expect: NOERROR response: + * expect: GETDNS_RETURN_GOOD + * rcode = 0 + todo: investigate that proper search order is set for resolution (is local being checked) + todo: create zonefile with exact count + * ancount = tbd (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); +} +END_TEST + +START_TEST (getdns_address_sync_8) +{ + /* + * name = "google.joe" + * status = GETDNS_RETURN_GOOD for NXDOMAIN + * expect: NXDOMAIN response with SOA record + * rcode = 0 + todo: investigate that proper search order is set for resolution (is local being checked) + todo: create host file with exact count + * ancount >= 1 (number of records in ANSWER section) + * and one SOA record ("type": 6) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.joe", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + //assert_address_in_answer(&ex_response, TRUE, FALSE); +} +END_TEST + + + +START_TEST (getdns_address_sync_9) +{ + /* + * name = "hampster.com" need to replace this with domain from unbound zone + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "hampster.com", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); +} +END_TEST + +START_TEST (getdns_address_sync_10) +{ + /* + * name = "google.com" need to swap this out for max domain name length with max lable length` + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 11 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); +} +END_TEST + +START_TEST (getdns_address_sync_11) +{ + /* + * name = "75.101.146.66" need to change this to local unbound data + * status = GETDNS_RETURN_GOOD for NXDOMAIN + * expect: NXDOMAIN response with SOA record for NUMERICAL data + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and one SOA record ("type": 6) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "75.101.146.66", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); +} +END_TEST + +START_TEST (getdns_address_sync_12) +{ + /* + * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data + * status = GETDNS_RETURN_GOOD for NXDOMAIN + * expect: NXDOMAIN response with SOA record for NUMERICAL data + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and one SOA record ("type": 6) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "2607:f8b0:4006:802::1007", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); +} +END_TEST + +Suite * +getdns_address_sync_suite (void) +{ + Suite *s = suite_create ("getdns_address_sync()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_address_sync_1); + tcase_add_test(tc_neg, getdns_address_sync_2); + tcase_add_test(tc_neg, getdns_address_sync_3); + tcase_add_test(tc_neg, getdns_address_sync_4); + tcase_add_test(tc_neg, getdns_address_sync_5); + suite_add_tcase(s, tc_neg); + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + + tcase_add_test(tc_pos, getdns_address_sync_6); + tcase_add_test(tc_pos, getdns_address_sync_7); + tcase_add_test(tc_pos, getdns_address_sync_8); + tcase_add_test(tc_pos, getdns_address_sync_9); + tcase_add_test(tc_pos, getdns_address_sync_10); + tcase_add_test(tc_pos, getdns_address_sync_11); + tcase_add_test(tc_pos, getdns_address_sync_12); + suite_add_tcase(s, tc_pos); + + return s; +} + +/* + * extract_response extracts all of the various information + * a test may want to look at from the response. + */ +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + + ck_assert_msg(response != NULL, "Response should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); + + ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); + + ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), + GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); + ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); + ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); + ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); + + ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); + ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), + GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); + ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); + ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); + ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); + + ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), + GETDNS_RETURN_GOOD, "Failed to extract \"header\""); + ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), + GETDNS_RETURN_GOOD, "Failed to extract \"question\""); + ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), + GETDNS_RETURN_GOOD, "Failed to extract \"status\""); +} + +/* + * assert_noerror asserts that the rcode is 0 + */ +void assert_noerror(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_nodata asserts that ancount in the header and the + * of the answer section (list) are both zero. + */ +void assert_nodata(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); +} + +/* + * assert_address_records_in_answer asserts that ancount in the header + * is >= 1, ancount is equal to the length of "answer", and that all of + * the records in the answer section are A and/or AAAA resource records + * based on the value of the a/aaaa arguments. + */ +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t address_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + switch (type) + { + case GETDNS_RRTYPE_A: + if(a && type == GETDNS_RRTYPE_A) + address_records++; + case GETDNS_RRTYPE_AAAA: + if(aaaa && type == GETDNS_RRTYPE_AAAA) + address_records++; + } + } + ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", + ancount, address_records); +} + +/* + * assert_nxdomain asserts that an NXDOMAIN response was + * was returned for the DNS query meaning: + * rcode == 3 + */ +void assert_nxdomain(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_soa_in_authority asserts that a SOA record was + * returned in the authority sections. + */ +void assert_soa_in_authority(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t nscount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t soa_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); + + ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); + ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); + if(type == GETDNS_RRTYPE_SOA) + soa_records++; + } + + ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); +} + +/* + * assert_ptr_in_answer asserts that a PTR record was + * returned in the answer sections. + */ +void assert_ptr_in_answer(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t ptr_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + if(type == GETDNS_RRTYPE_PTR) + ptr_records++; + } + + ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); +} + +int +main (void) +{ + int number_failed; + Suite *s = getdns_address_sync_suite(); + SRunner *sr = srunner_create(s); + srunner_set_log(sr, "getdns_address_sync_test.log"); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} From 09631e038be255ad81992d141844cf76ba1e6533 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Wed, 18 Dec 2013 16:23:07 -0500 Subject: [PATCH 03/35] New source file for getdns_general and updates to getdns_general_sync. --- src/test/Makefile.in | 5 +- src/test/check_getdns_general.c | 717 +++++++++++++++++++++++++++ src/test/check_getdns_general_sync.c | 5 +- 3 files changed, 722 insertions(+), 5 deletions(-) create mode 100644 src/test/check_getdns_general.c diff --git a/src/test/Makefile.in b/src/test/Makefile.in index a993923b..2722dde0 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -19,7 +19,7 @@ CC=gcc CFLAGS=@CFLAGS@ -Wall -I$(srcdir)/ -I$(srcdir)/../ -I/usr/local/include -std=c99 $(cflags) LDFLAGS=@LDFLAGS@ -L. -L.. -L/usr/local/lib LDLIBS=-lgetdns @LIBS@ -lcheck -PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns_general_sync check_getdns_address_sync +PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns_general check_getdns_general_sync check_getdns_address_sync .SUFFIXES: .c .o .a .lo .h @@ -42,6 +42,9 @@ tests_stub_async: tests_stub_async.o testmessages.o tests_stub_sync: tests_stub_sync.o $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_stub_sync.o +check_getdns_general: check_getdns_general.o + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_general.o + check_getdns_general_sync: check_getdns_general_sync.o $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_general_sync.o diff --git a/src/test/check_getdns_general.c b/src/test/check_getdns_general.c new file mode 100644 index 00000000..5f05a92a --- /dev/null +++ b/src/test/check_getdns_general.c @@ -0,0 +1,717 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 +#define MAXLEN 200 + +struct extracted_response { + uint32_t top_answer_type; + struct getdns_bindata *top_canonical_name; + struct getdns_list *just_address_answers; + struct getdns_list *replies_full; + struct getdns_list *replies_tree; + struct getdns_dict *replies_tree_sub_dict; + struct getdns_list *additional; + struct getdns_list *answer; + uint32_t answer_type; + struct getdns_list *authority; + struct getdns_bindata *canonical_name; + struct getdns_dict *header; + struct getdns_dict *question; + uint32_t status; +}; + +/* + * The STANDARD_TEST_DECLARATIONS macro defines + * ithe standard variable definitions most tests + * will need. + * + */ +#define STANDARD_TEST_DECLARATIONS \ + struct getdns_context *context = NULL; \ + struct getdns_dict *response = NULL; \ + struct event_base *event_base; \ + getdns_transaction_t transaction_id = 0; \ + size_t buflen = MAXLEN; \ + char error_string[MAXLEN]; + +/* + * The ASSERT_RC macro is used to assert + * whether the return code from the last + * getdns API call is what was expected. + */ +#define ASSERT_RC(rc, expected_rc, prefix) \ + getdns_strerror(rc, error_string, buflen); \ + ck_assert_msg(rc == expected_rc, \ + "%s: expecting %s: %d, but received: %d: %s", \ + prefix, #expected_rc, expected_rc, rc, error_string); + +/* + * The CONTEXT_CREATE macro is used to + * create a context and assert the proper + * return code is returned. + */ +#define CONTEXT_CREATE \ + ASSERT_RC(getdns_context_create(&context, TRUE), \ + GETDNS_RETURN_GOOD, \ + "Return code from getdns_context_create()"); + +/* + * The EVENT_BASE_CREATE macro is used to + * create an event base and put it in the + * context. + */ +#define EVENT_BASE_CREATE \ + event_base = event_base_new(); \ + ck_assert_msg(event_base != NULL, "Event base creation failed"); \ + ASSERT_RC(getdns_extension_set_libevent_base(context, event_base), \ + GETDNS_RETURN_GOOD, \ + "Return code from getdns_extension_set_libevent_base()"); + +/* + * The EVENT_LOOP macro calls the event loop. + */ +#define EVENT_LOOP \ + int dispatch_return = event_base_dispatch(event_base); + +/* + * The process_response macro declares the + * variables needed to house the response and + * calls the function that extracts it. + */ +#define EXTRACT_RESPONSE \ + struct extracted_response ex_response; \ + extract_response(response, &ex_response); + +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); +void assert_noerror(struct extracted_response *ex_response); +void assert_nodata(struct extracted_response *ex_response); +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); +void assert_nxdomain(struct extracted_response *ex_response); +void assert_soa_in_authority(struct extracted_response *ex_response); +void assert_ptr_in_answer(struct extracted_response *ex_response); +void negative_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id +); +void positive_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id +); + +START_TEST (getdns_general_1) +{ + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + STANDARD_TEST_DECLARATIONS; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_1", &transaction_id, negative_callbackfn), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general()"); +} +END_TEST + +START_TEST (getdns_general_2) +{ + /* + * name = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, + "getdns_general_2", &transaction_id, negative_callbackfn), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_3) +{ + /* + * name = invalid domain (too many octets) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, + "getdns_general_3", &transaction_id, negative_callbackfn), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_4) +{ + /* + * name = invalid domain (label too long) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, + "getdns_general_4", &transaction_id, negative_callbackfn), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_5) +{ + /* + * callbackfn = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_5", &transaction_id, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_6) +{ + /* + * name = "google.com" + * request_type = 0 (minimum valid RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", 0, NULL, + "getdns_general_6", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_7) +{ + /* + * name = "google.com" + * request_type = 65279 (maximum unassigned RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, + "getdns_general_7", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_8) +{ + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_8", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_9) +{ + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_AAAA + * expect: NOERROR response with AAAA records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of AAAA records ("type": 28) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, + "getdns_general_9", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_10) +{ + /* + * name = "thisdomainsurelydoesntexist.com" + * request_type = GETDNS_RRTYPE_TXT` + * expect: NXDOMAIN response with SOA record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 3 + * ancount = 0 (number of records in ANSWER section) + * nscount = 1 (number of records in AUTHORITY section) + * and SOA record ("type": 6) present in "authority" list + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "thisdomainsurelydoesntexist.com"; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, + "getdns_general_10", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_11) +{ + /* + * name = "hampster.com" need to replace this with domain from unbound zone + * request_type = GETDNS_RRTYPE_MX + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, + "getdns_general_11", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_12) +{ + /* + * name = "google.com" need to swap this out for max domain name length with max lable length` + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_12", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_13) +{ + /* + * name = "75.101.146.66" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, + "getdns_general_13", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +START_TEST (getdns_general_14) +{ + /* + * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, + "getdns_general_14", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; +} +END_TEST + +Suite * +getdns_general_suite (void) +{ + Suite *s = suite_create ("getdns_general()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_general_1); + tcase_add_test(tc_neg, getdns_general_2); + tcase_add_test(tc_neg, getdns_general_3); + tcase_add_test(tc_neg, getdns_general_4); + tcase_add_test(tc_neg, getdns_general_5); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_general_6); + tcase_add_test(tc_pos, getdns_general_7); + tcase_add_test(tc_pos, getdns_general_8); + tcase_add_test(tc_pos, getdns_general_9); + tcase_add_test(tc_pos, getdns_general_10); + tcase_add_test(tc_pos, getdns_general_11); + tcase_add_test(tc_pos, getdns_general_12); + tcase_add_test(tc_pos, getdns_general_13); + tcase_add_test(tc_pos, getdns_general_14); + suite_add_tcase(s, tc_pos); + + return s; +} + +/* + * extract_response extracts all of the various information + * a test may want to look at from the response. + */ +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + + ck_assert_msg(response != NULL, "Response should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); + + ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); + + ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), + GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); + ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); + ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); + ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); + + ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); + ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), + GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); + ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); + ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); + ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); + + ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), + GETDNS_RETURN_GOOD, "Failed to extract \"header\""); + ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), + GETDNS_RETURN_GOOD, "Failed to extract \"question\""); + ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), + GETDNS_RETURN_GOOD, "Failed to extract \"status\""); +} + +/* + * assert_noerror asserts that the rcode is 0 + */ +void assert_noerror(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_nodata asserts that ancount in the header and the + * of the answer section (list) are both zero. + */ +void assert_nodata(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); +} + +/* + * assert_address_records_in_answer asserts that ancount in the header + * is >= 1, ancount is equal to the length of "answer", and that all of + * the records in the answer section are A and/or AAAA resource records + * based on the value of the a/aaaa arguments. + */ +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t address_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + switch (type) + { + case GETDNS_RRTYPE_A: + if(a && type == GETDNS_RRTYPE_A) + address_records++; + case GETDNS_RRTYPE_AAAA: + if(aaaa && type == GETDNS_RRTYPE_AAAA) + address_records++; + } + } + ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", + ancount, address_records); +} + +/* + * assert_nxdomain asserts that an NXDOMAIN response was + * was returned for the DNS query meaning: + * rcode == 3 + */ +void assert_nxdomain(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_soa_in_authority asserts that a SOA record was + * returned in the authority sections. + */ +void assert_soa_in_authority(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t nscount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t soa_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); + + ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); + ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); + if(type == GETDNS_RRTYPE_SOA) + soa_records++; + } + + ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); +} + +/* + * assert_ptr_in_answer asserts that a PTR record was + * returned in the answer sections. + */ +void assert_ptr_in_answer(struct extracted_response *ex_response) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t ptr_records = 0; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(size_t i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + if(type == GETDNS_RRTYPE_PTR) + ptr_records++; + } + + ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); +} + +void negative_callbackfn(struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id) +{ + ck_abort_msg("Callback should never occur for negative test cases"); +} + +void positive_callbackfn(struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id) +{ + size_t buflen = MAXLEN; + char error_string[MAXLEN]; + + ASSERT_RC(callback_type, GETDNS_CALLBACK_COMPLETE, "Callback type"); + EXTRACT_RESPONSE; + + if(strcmp(userarg, "getdns_general_6") == 0 || + strcmp(userarg, "getdns_general_7") == 0 || + strcmp(userarg, "getdns_general_11") == 0) + { + assert_noerror(&ex_response); + assert_nodata(&ex_response); + } + else if(strcmp(userarg, "getdns_general_8") == 0 || + strcmp(userarg, "getdns_general_12") == 0) + { + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); + } + else if(strcmp(userarg, "getdns_general_9") == 0) + { + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, FALSE, TRUE); + } + else if(strcmp(userarg, "getdns_general_10") == 0) + { + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + } + else if(strcmp(userarg, "getdns_general_13") == 0 || + strcmp(userarg, "getdns_general_14") == 0) + { + printf("DICT:%s\n", getdns_pretty_print_dict(response)); + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); + } + else + { + ck_abort_msg("Unexpected value in userarg: %s", userarg); + } +} + +int +main (void) +{ + int number_failed; + Suite *s = getdns_general_suite(); + SRunner *sr = srunner_create(s); + srunner_set_log(sr, "getdns_general_test.log"); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/test/check_getdns_general_sync.c b/src/test/check_getdns_general_sync.c index 43171873..c474596f 100644 --- a/src/test/check_getdns_general_sync.c +++ b/src/test/check_getdns_general_sync.c @@ -31,7 +31,6 @@ struct extracted_response { * The STANDARD_TEST_DECLARATIONS macro defines * ithe standard variable definitions most tests * will need. - * */ #define STANDARD_TEST_DECLARATIONS \ struct getdns_context *context = NULL; \ @@ -292,7 +291,6 @@ START_TEST (getdns_general_sync_12) ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); EXTRACT_RESPONSE; - printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); } @@ -315,7 +313,6 @@ START_TEST (getdns_general_sync_13) ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); EXTRACT_RESPONSE; - printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); assert_noerror(&ex_response); assert_ptr_in_answer(&ex_response); } @@ -356,9 +353,9 @@ getdns_general_sync_suite (void) tcase_add_test(tc_neg, getdns_general_sync_4); tcase_add_test(tc_neg, getdns_general_sync_5); suite_add_tcase(s, tc_neg); + /* Positive test cases */ TCase *tc_pos = tcase_create("Positive"); - tcase_add_test(tc_pos, getdns_general_sync_6); tcase_add_test(tc_pos, getdns_general_sync_7); tcase_add_test(tc_pos, getdns_general_sync_8); From 5e08bbc347aa15645694976b0f78bc407f843dad Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Thu, 19 Dec 2013 09:42:36 -0500 Subject: [PATCH 04/35] Removed debug related printf. --- src/test/check_getdns_general.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/check_getdns_general.c b/src/test/check_getdns_general.c index 5f05a92a..ccf85310 100644 --- a/src/test/check_getdns_general.c +++ b/src/test/check_getdns_general.c @@ -693,7 +693,6 @@ void positive_callbackfn(struct getdns_context *context, else if(strcmp(userarg, "getdns_general_13") == 0 || strcmp(userarg, "getdns_general_14") == 0) { - printf("DICT:%s\n", getdns_pretty_print_dict(response)); assert_noerror(&ex_response); assert_ptr_in_answer(&ex_response); } From 01c70b73c9d5005d491d4d86c3aeb4b41e176991 Mon Sep 17 00:00:00 2001 From: Bryan Graham Date: Thu, 19 Dec 2013 19:36:41 -0500 Subject: [PATCH 05/35] refactoring: check_getdns_common.h check_getdns_common.c check_getdns.c, tests are now in header files --- .gitignore | 2 + src/test/Makefile.in | 14 +- src/test/check_getdns.c | 32 ++ src/test/check_getdns_address_sync.h | 252 ++++++++++ src/test/check_getdns_common.c | 282 +++++++++++ src/test/check_getdns_common.h | 111 +++++ src/test/check_getdns_general.c | 716 --------------------------- src/test/check_getdns_general.h | 310 ++++++++++++ src/test/check_getdns_general_sync.h | 298 +++++++++++ 9 files changed, 1292 insertions(+), 725 deletions(-) create mode 100644 src/test/check_getdns.c create mode 100644 src/test/check_getdns_address_sync.h create mode 100644 src/test/check_getdns_common.c create mode 100644 src/test/check_getdns_common.h delete mode 100644 src/test/check_getdns_general.c create mode 100644 src/test/check_getdns_general.h create mode 100644 src/test/check_getdns_general_sync.h diff --git a/.gitignore b/.gitignore index f9fc4958..dad7cf06 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ tests_list tests_stub_async tests_stub_sync +src/example/example-reverse +src/test/check_getdns.log diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 2722dde0..9dbdbe55 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -19,7 +19,7 @@ CC=gcc CFLAGS=@CFLAGS@ -Wall -I$(srcdir)/ -I$(srcdir)/../ -I/usr/local/include -std=c99 $(cflags) LDFLAGS=@LDFLAGS@ -L. -L.. -L/usr/local/lib LDLIBS=-lgetdns @LIBS@ -lcheck -PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns_general check_getdns_general_sync check_getdns_address_sync +PROGRAMS=tests_dict tests_list tests_stub_async tests_stub_sync check_getdns .SUFFIXES: .c .o .a .lo .h @@ -42,15 +42,11 @@ tests_stub_async: tests_stub_async.o testmessages.o tests_stub_sync: tests_stub_sync.o $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ tests_stub_sync.o -check_getdns_general: check_getdns_general.o - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_general.o - -check_getdns_general_sync: check_getdns_general_sync.o - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_general_sync.o - -check_getdns_address_sync: check_getdns_address_sync.o - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_address_sync.o +check_getdns_common: check_getdns_common.o + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_common.o +check_getdns: check_getdns.o check_getdns_common.o + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ $^ test: all ./testscript.sh diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c new file mode 100644 index 00000000..0fea027e --- /dev/null +++ b/src/test/check_getdns.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include +#include "check_getdns_common.h" +#include "check_getdns_address_sync.h" +#include "check_getdns_general_sync.h" +#include "check_getdns_general.h" + +int +main (void) +{ + int number_failed; + SRunner *sr ; + + Suite *getdns_address_sync_suite (void); + Suite *getdns_general_sync_suite (void); + Suite *getdns_general_suite (void); + + sr = srunner_create (getdns_address_sync_suite()); + srunner_add_suite (sr, getdns_general_sync_suite ()); + srunner_add_suite (sr, getdns_general_suite()); + + srunner_set_log(sr, "check_getdns.log"); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h new file mode 100644 index 00000000..6d7ff79c --- /dev/null +++ b/src/test/check_getdns_address_sync.h @@ -0,0 +1,252 @@ + +#ifndef _check_getdns_address_h_ +#define _check_getdns_address_h_ + + START_TEST (getdns_address_sync_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + STANDARD_TEST_DECLARATIONS; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_address_sync()"); + } + END_TEST + + START_TEST (getdns_address_sync_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); + } + END_TEST + + START_TEST (getdns_address_sync_3) + { + /* + * name = invalid domain (too many octets) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, name, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); + } + END_TEST + + START_TEST (getdns_address_sync_4) + { + /* + * name = invalid domain (label too long) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, name, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); + } + END_TEST + + START_TEST (getdns_address_sync_5) + { + /* + * response = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); + } + END_TEST + + START_TEST (getdns_address_sync_6) + { + /* + * name = "google.com" + * expect: NOERROR response: + * status = GETDNS_RETURN_GOOD + * rcode = 0 + todo: create zonefile with exact count + * ancount = tbd (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + } + END_TEST + + START_TEST (getdns_address_sync_7) + { + /* + * name = "localhost" + * expect: NOERROR response: + * expect: GETDNS_RETURN_GOOD + * rcode = 0 + todo: investigate that proper search order is set for resolution (is local being checked) + todo: create zonefile with exact count + * ancount = tbd (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + } + END_TEST + + START_TEST (getdns_address_sync_8) + { + /* + * name = "google.joe" + * status = GETDNS_RETURN_GOOD for NXDOMAIN + * expect: NXDOMAIN response with SOA record + * rcode = 0 + todo: investigate that proper search order is set for resolution (is local being checked) + todo: create host file with exact count + * ancount >= 1 (number of records in ANSWER section) + * and one SOA record ("type": 6) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.joe", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + //assert_address_in_answer(&ex_response, TRUE, FALSE); + } + END_TEST + + + + START_TEST (getdns_address_sync_9) + { + /* + * name = "hampster.com" need to replace this with domain from unbound zone + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "hampster.com", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + } + END_TEST + + START_TEST (getdns_address_sync_10) + { + /* + * name = "google.com" need to swap this out for max domain name length with max lable length` + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 11 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); + } + END_TEST + + START_TEST (getdns_address_sync_11) + { + /* + * name = "75.101.146.66" need to change this to local unbound data + * status = GETDNS_RETURN_GOOD for NXDOMAIN + * expect: NXDOMAIN response with SOA record for NUMERICAL data + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and one SOA record ("type": 6) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "75.101.146.66", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + } + END_TEST + + START_TEST (getdns_address_sync_12) + { + /* + * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data + * status = GETDNS_RETURN_GOOD for NXDOMAIN + * expect: NXDOMAIN response with SOA record for NUMERICAL data + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and one SOA record ("type": 6) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "2607:f8b0:4006:802::1007", NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + } + END_TEST + + Suite * + getdns_address_sync_suite (void) + { + Suite *s = suite_create ("getdns_address_sync()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_address_sync_1); + tcase_add_test(tc_neg, getdns_address_sync_2); + tcase_add_test(tc_neg, getdns_address_sync_3); + tcase_add_test(tc_neg, getdns_address_sync_4); + tcase_add_test(tc_neg, getdns_address_sync_5); + suite_add_tcase(s, tc_neg); + /* Positive test cases */ + + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_address_sync_6); + tcase_add_test(tc_pos, getdns_address_sync_7); + tcase_add_test(tc_pos, getdns_address_sync_8); + tcase_add_test(tc_pos, getdns_address_sync_9); + tcase_add_test(tc_pos, getdns_address_sync_10); + tcase_add_test(tc_pos, getdns_address_sync_11); + tcase_add_test(tc_pos, getdns_address_sync_12); + suite_add_tcase(s, tc_pos); + + return s; + } + + + +#endif diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c new file mode 100644 index 00000000..b5f2d8a9 --- /dev/null +++ b/src/test/check_getdns_common.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include +#include +#include +#include "check_getdns_common.h" +#include + + +/* + * extract_response extracts all of the various information + * a test may want to look at from the response. + */ +void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) +{ + + ck_assert_msg(response != NULL, "Response should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); + + ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); + + ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), + GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); + ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); + ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); + ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); + + ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); + ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), + GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); + ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); + ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), + GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); + + ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); + ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); + + ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), + GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), + GETDNS_RETURN_GOOD, "Failed to extract \"header\""); + ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); + + ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), + GETDNS_RETURN_GOOD, "Failed to extract \"question\""); + ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); + + ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), + GETDNS_RETURN_GOOD, "Failed to extract \"status\""); +} + +/* + * assert_noerror asserts that the rcode is 0 + */ +void assert_noerror(struct extracted_response *ex_response) +{ + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_nodata asserts that ancount in the header and the + * of the answer section (list) are both zero. + */ +void assert_nodata(struct extracted_response *ex_response) +{ + uint32_t ancount; + size_t length; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); +} + +/* + * assert_address_records_in_answer asserts that ancount in the header + * is >= 1, ancount is equal to the length of "answer", and that all of + * the records in the answer section are A and/or AAAA resource records + * based on the value of the a/aaaa arguments. + */ +void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) +{ + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t address_records = 0; + size_t i; + + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + switch (type) + { + case GETDNS_RRTYPE_A: + if(a && type == GETDNS_RRTYPE_A) + address_records++; + case GETDNS_RRTYPE_AAAA: + if(aaaa && type == GETDNS_RRTYPE_AAAA) + address_records++; + } + } + ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", + ancount, address_records); +} + +/* + * assert_nxdomain asserts that an NXDOMAIN response was + * was returned for the DNS query meaning: + * rcode == 3 + */ +void assert_nxdomain(struct extracted_response *ex_response) +{ + uint32_t rcode; + + ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); + ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); + ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); +} + +/* + * assert_soa_in_authority asserts that a SOA record was + * returned in the authority sections. + */ +void assert_soa_in_authority(struct extracted_response *ex_response) +{ + uint32_t nscount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t soa_records = 0; + size_t i; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); + + ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); + ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); + + for(i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); + if(type == GETDNS_RRTYPE_SOA) + soa_records++; + } + + ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); +} + +/* + * assert_ptr_in_answer asserts that a PTR record was + * returned in the answer sections. + */ +void assert_ptr_in_answer(struct extracted_response *ex_response) +{ + uint32_t ancount; + size_t length; + struct getdns_dict *rr_dict; + uint32_t type; + uint32_t ptr_records = 0; + size_t i; + + ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), + GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); + ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); + + ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); + ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); + + for(i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), + GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); + ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), + GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); + if(type == GETDNS_RRTYPE_PTR) + ptr_records++; + } + + ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); +} + +void negative_callbackfn(struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id) +{ + ck_abort_msg("Callback should never occur for negative test cases"); +} + +void positive_callbackfn(struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id) +{ + + ASSERT_RC(callback_type, GETDNS_CALLBACK_COMPLETE, "Callback type"); + EXTRACT_RESPONSE; + + if(strcmp(userarg, "getdns_general_6") == 0 || + strcmp(userarg, "getdns_general_7") == 0 || + strcmp(userarg, "getdns_general_11") == 0) + { + assert_noerror(&ex_response); + assert_nodata(&ex_response); + } + else if(strcmp(userarg, "getdns_general_8") == 0 || + strcmp(userarg, "getdns_general_12") == 0) + { + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); + } + else if(strcmp(userarg, "getdns_general_9") == 0) + { + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, FALSE, TRUE); + } + else if(strcmp(userarg, "getdns_general_10") == 0) + { + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + } + else if(strcmp(userarg, "getdns_general_13") == 0 || + strcmp(userarg, "getdns_general_14") == 0) + { + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); + } + else + { + ck_abort_msg("Unexpected value in userarg: %s", userarg); + } +} diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h new file mode 100644 index 00000000..75ced3f0 --- /dev/null +++ b/src/test/check_getdns_common.h @@ -0,0 +1,111 @@ +#ifndef _check_getdns_common_h_ +#define _check_getdns_common_h_ + + #define TRUE 1 + #define FALSE 0 + #define MAXLEN 200 + + struct extracted_response { + uint32_t top_answer_type; + struct getdns_bindata *top_canonical_name; + struct getdns_list *just_address_answers; + struct getdns_list *replies_full; + struct getdns_list *replies_tree; + struct getdns_dict *replies_tree_sub_dict; + struct getdns_list *additional; + struct getdns_list *answer; + uint32_t answer_type; + struct getdns_list *authority; + struct getdns_bindata *canonical_name; + struct getdns_dict *header; + struct getdns_dict *question; + uint32_t status; + }; + + /* + * The STANDARD_TEST_DECLARATIONS macro defines + * the standard variable definitions most tests + * will need. + * + */ + #define STANDARD_TEST_DECLARATIONS \ + struct getdns_context *context = NULL; \ + struct getdns_dict *response = NULL; \ + struct event_base *event_base; \ + getdns_transaction_t transaction_id = 0; \ + + /* + * The ASSERT_RC macro is used to assert + * whether the return code from the last + * getdns API call is what was expected. + */ + #define ASSERT_RC(rc, expected_rc, prefix) \ + { \ + size_t buflen = MAXLEN; \ + char error_string[MAXLEN]; \ + getdns_strerror(rc, error_string, buflen); \ + ck_assert_msg(rc == expected_rc, \ + "%s: expecting %s: %d, but received: %d: %s", \ + prefix, #expected_rc, expected_rc, rc, error_string); \ + } + + /* + * The CONTEXT_CREATE macro is used to + * create a context and assert the proper + * return code is returned. + */ + #define CONTEXT_CREATE \ + ASSERT_RC(getdns_context_create(&context, TRUE), \ + GETDNS_RETURN_GOOD, \ + "Return code from getdns_context_create()"); + + /* + * The EVENT_BASE_CREATE macro is used to + * create an event base and put it in the + * context. + */ + #define EVENT_BASE_CREATE \ + event_base = event_base_new(); \ + ck_assert_msg(event_base != NULL, "Event base creation failed"); \ + ASSERT_RC(getdns_extension_set_libevent_base(context, event_base), \ + GETDNS_RETURN_GOOD, \ + "Return code from getdns_extension_set_libevent_base()"); + + /* + * The EVENT_LOOP macro calls the event loop. + */ + #define EVENT_LOOP \ + int dispatch_return = event_base_dispatch(event_base); + + /* + * The process_response macro declares the + * variables needed to house the response and + * calls the function that extracts it. + */ + #define EXTRACT_RESPONSE \ + struct extracted_response ex_response; \ + extract_response(response, &ex_response); + + void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); + void assert_noerror(struct extracted_response *ex_response); + void assert_nodata(struct extracted_response *ex_response); + void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); + void assert_nxdomain(struct extracted_response *ex_response); + void assert_soa_in_authority(struct extracted_response *ex_response); + void assert_ptr_in_answer(struct extracted_response *ex_response); + void negative_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id + ); + void positive_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id + ); + +#endif diff --git a/src/test/check_getdns_general.c b/src/test/check_getdns_general.c deleted file mode 100644 index ccf85310..00000000 --- a/src/test/check_getdns_general.c +++ /dev/null @@ -1,716 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define TRUE 1 -#define FALSE 0 -#define MAXLEN 200 - -struct extracted_response { - uint32_t top_answer_type; - struct getdns_bindata *top_canonical_name; - struct getdns_list *just_address_answers; - struct getdns_list *replies_full; - struct getdns_list *replies_tree; - struct getdns_dict *replies_tree_sub_dict; - struct getdns_list *additional; - struct getdns_list *answer; - uint32_t answer_type; - struct getdns_list *authority; - struct getdns_bindata *canonical_name; - struct getdns_dict *header; - struct getdns_dict *question; - uint32_t status; -}; - -/* - * The STANDARD_TEST_DECLARATIONS macro defines - * ithe standard variable definitions most tests - * will need. - * - */ -#define STANDARD_TEST_DECLARATIONS \ - struct getdns_context *context = NULL; \ - struct getdns_dict *response = NULL; \ - struct event_base *event_base; \ - getdns_transaction_t transaction_id = 0; \ - size_t buflen = MAXLEN; \ - char error_string[MAXLEN]; - -/* - * The ASSERT_RC macro is used to assert - * whether the return code from the last - * getdns API call is what was expected. - */ -#define ASSERT_RC(rc, expected_rc, prefix) \ - getdns_strerror(rc, error_string, buflen); \ - ck_assert_msg(rc == expected_rc, \ - "%s: expecting %s: %d, but received: %d: %s", \ - prefix, #expected_rc, expected_rc, rc, error_string); - -/* - * The CONTEXT_CREATE macro is used to - * create a context and assert the proper - * return code is returned. - */ -#define CONTEXT_CREATE \ - ASSERT_RC(getdns_context_create(&context, TRUE), \ - GETDNS_RETURN_GOOD, \ - "Return code from getdns_context_create()"); - -/* - * The EVENT_BASE_CREATE macro is used to - * create an event base and put it in the - * context. - */ -#define EVENT_BASE_CREATE \ - event_base = event_base_new(); \ - ck_assert_msg(event_base != NULL, "Event base creation failed"); \ - ASSERT_RC(getdns_extension_set_libevent_base(context, event_base), \ - GETDNS_RETURN_GOOD, \ - "Return code from getdns_extension_set_libevent_base()"); - -/* - * The EVENT_LOOP macro calls the event loop. - */ -#define EVENT_LOOP \ - int dispatch_return = event_base_dispatch(event_base); - -/* - * The process_response macro declares the - * variables needed to house the response and - * calls the function that extracts it. - */ -#define EXTRACT_RESPONSE \ - struct extracted_response ex_response; \ - extract_response(response, &ex_response); - -void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); -void assert_noerror(struct extracted_response *ex_response); -void assert_nodata(struct extracted_response *ex_response); -void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); -void assert_nxdomain(struct extracted_response *ex_response); -void assert_soa_in_authority(struct extracted_response *ex_response); -void assert_ptr_in_answer(struct extracted_response *ex_response); -void negative_callbackfn( - struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id -); -void positive_callbackfn( - struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id -); - -START_TEST (getdns_general_1) -{ - /* - * context = NULL - * expect: GETDNS_RETURN_BAD_CONTEXT - */ - STANDARD_TEST_DECLARATIONS; - ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_1", &transaction_id, negative_callbackfn), - GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general()"); -} -END_TEST - -START_TEST (getdns_general_2) -{ - /* - * name = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR - */ - STANDARD_TEST_DECLARATIONS; - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, - "getdns_general_2", &transaction_id, negative_callbackfn), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_3) -{ - /* - * name = invalid domain (too many octets) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, - "getdns_general_3", &transaction_id, negative_callbackfn), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_4) -{ - /* - * name = invalid domain (label too long) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, - "getdns_general_4", &transaction_id, negative_callbackfn), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_5) -{ - /* - * callbackfn = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR - */ - STANDARD_TEST_DECLARATIONS; - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_5", &transaction_id, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_6) -{ - /* - * name = "google.com" - * request_type = 0 (minimum valid RRTYPE) - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "google.com", 0, NULL, - "getdns_general_6", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_7) -{ - /* - * name = "google.com" - * request_type = 65279 (maximum unassigned RRTYPE) - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, - "getdns_general_7", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_8) -{ - /* - * name = "google.com" - * request_type = GETDNS_RRTYPE_A - * expect: NOERROR response with A records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and equals number of A records ("type": 1) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_8", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_9) -{ - /* - * name = "google.com" - * request_type = GETDNS_RRTYPE_AAAA - * expect: NOERROR response with AAAA records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and equals number of AAAA records ("type": 28) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, - "getdns_general_9", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_10) -{ - /* - * name = "thisdomainsurelydoesntexist.com" - * request_type = GETDNS_RRTYPE_TXT` - * expect: NXDOMAIN response with SOA record - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 3 - * ancount = 0 (number of records in ANSWER section) - * nscount = 1 (number of records in AUTHORITY section) - * and SOA record ("type": 6) present in "authority" list - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "thisdomainsurelydoesntexist.com"; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, - "getdns_general_10", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_11) -{ - /* - * name = "hampster.com" need to replace this with domain from unbound zone - * request_type = GETDNS_RRTYPE_MX - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, - "getdns_general_11", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_12) -{ - /* - * name = "google.com" need to swap this out for max domain name length with max lable length` - * request_type = GETDNS_RRTYPE_A - * expect: NOERROR response with A records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and equals number of A records ("type": 1) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_12", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_13) -{ - /* - * name = "75.101.146.66" need to change this to local unbound data - * request_type = GETDNS_RRTYPE_PTR - * expect: NOERROR response with PTR record - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount == 1 (number of records in ANSWER section) - * and PTR record found ("type": 12) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, - "getdns_general_13", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -START_TEST (getdns_general_14) -{ - /* - * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data - * request_type = GETDNS_RRTYPE_PTR - * expect: NOERROR response with PTR record - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount == 1 (number of records in ANSWER section) - * and PTR record found ("type": 12) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - EVENT_BASE_CREATE; - ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, - "getdns_general_14", &transaction_id, positive_callbackfn), - GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; -} -END_TEST - -Suite * -getdns_general_suite (void) -{ - Suite *s = suite_create ("getdns_general()"); - - /* Negative test caseis */ - TCase *tc_neg = tcase_create("Negative"); - tcase_add_test(tc_neg, getdns_general_1); - tcase_add_test(tc_neg, getdns_general_2); - tcase_add_test(tc_neg, getdns_general_3); - tcase_add_test(tc_neg, getdns_general_4); - tcase_add_test(tc_neg, getdns_general_5); - suite_add_tcase(s, tc_neg); - - /* Positive test cases */ - TCase *tc_pos = tcase_create("Positive"); - tcase_add_test(tc_pos, getdns_general_6); - tcase_add_test(tc_pos, getdns_general_7); - tcase_add_test(tc_pos, getdns_general_8); - tcase_add_test(tc_pos, getdns_general_9); - tcase_add_test(tc_pos, getdns_general_10); - tcase_add_test(tc_pos, getdns_general_11); - tcase_add_test(tc_pos, getdns_general_12); - tcase_add_test(tc_pos, getdns_general_13); - tcase_add_test(tc_pos, getdns_general_14); - suite_add_tcase(s, tc_pos); - - return s; -} - -/* - * extract_response extracts all of the various information - * a test may want to look at from the response. - */ -void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - - ck_assert_msg(response != NULL, "Response should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), - GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); - - ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), - GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); - - ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), - GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); - ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); - ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); - ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); - - ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); - ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), - GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); - ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); - ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), - GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); - ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); - - ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), - GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); - - ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), - GETDNS_RETURN_GOOD, "Failed to extract \"header\""); - ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); - - ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), - GETDNS_RETURN_GOOD, "Failed to extract \"question\""); - ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), - GETDNS_RETURN_GOOD, "Failed to extract \"status\""); -} - -/* - * assert_noerror asserts that the rcode is 0 - */ -void assert_noerror(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t rcode; - - ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); - ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); - ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); -} - -/* - * assert_nodata asserts that ancount in the header and the - * of the answer section (list) are both zero. - */ -void assert_nodata(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); - ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); -} - -/* - * assert_address_records_in_answer asserts that ancount in the header - * is >= 1, ancount is equal to the length of "answer", and that all of - * the records in the answer section are A and/or AAAA resource records - * based on the value of the a/aaaa arguments. - */ -void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t address_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); - ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); - switch (type) - { - case GETDNS_RRTYPE_A: - if(a && type == GETDNS_RRTYPE_A) - address_records++; - case GETDNS_RRTYPE_AAAA: - if(aaaa && type == GETDNS_RRTYPE_AAAA) - address_records++; - } - } - ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", - ancount, address_records); -} - -/* - * assert_nxdomain asserts that an NXDOMAIN response was - * was returned for the DNS query meaning: - * rcode == 3 - */ -void assert_nxdomain(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t rcode; - - ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); - ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); - ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); -} - -/* - * assert_soa_in_authority asserts that a SOA record was - * returned in the authority sections. - */ -void assert_soa_in_authority(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t nscount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t soa_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), - GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); - ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); - - ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); - ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); - if(type == GETDNS_RRTYPE_SOA) - soa_records++; - } - - ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); -} - -/* - * assert_ptr_in_answer asserts that a PTR record was - * returned in the answer sections. - */ -void assert_ptr_in_answer(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t ptr_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); - ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); - if(type == GETDNS_RRTYPE_PTR) - ptr_records++; - } - - ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); -} - -void negative_callbackfn(struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id) -{ - ck_abort_msg("Callback should never occur for negative test cases"); -} - -void positive_callbackfn(struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - - ASSERT_RC(callback_type, GETDNS_CALLBACK_COMPLETE, "Callback type"); - EXTRACT_RESPONSE; - - if(strcmp(userarg, "getdns_general_6") == 0 || - strcmp(userarg, "getdns_general_7") == 0 || - strcmp(userarg, "getdns_general_11") == 0) - { - assert_noerror(&ex_response); - assert_nodata(&ex_response); - } - else if(strcmp(userarg, "getdns_general_8") == 0 || - strcmp(userarg, "getdns_general_12") == 0) - { - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, TRUE, FALSE); - } - else if(strcmp(userarg, "getdns_general_9") == 0) - { - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, FALSE, TRUE); - } - else if(strcmp(userarg, "getdns_general_10") == 0) - { - assert_nxdomain(&ex_response); - assert_nodata(&ex_response); - assert_soa_in_authority(&ex_response); - } - else if(strcmp(userarg, "getdns_general_13") == 0 || - strcmp(userarg, "getdns_general_14") == 0) - { - assert_noerror(&ex_response); - assert_ptr_in_answer(&ex_response); - } - else - { - ck_abort_msg("Unexpected value in userarg: %s", userarg); - } -} - -int -main (void) -{ - int number_failed; - Suite *s = getdns_general_suite(); - SRunner *sr = srunner_create(s); - srunner_set_log(sr, "getdns_general_test.log"); - srunner_run_all(sr, CK_NORMAL); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h new file mode 100644 index 00000000..92b30b2e --- /dev/null +++ b/src/test/check_getdns_general.h @@ -0,0 +1,310 @@ +#ifndef _check_getdns_general_h_ +#define _check_getdns_general_h_ + + START_TEST (getdns_general_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + STANDARD_TEST_DECLARATIONS; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_1", &transaction_id, negative_callbackfn), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general()"); + } + END_TEST + + START_TEST (getdns_general_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, + "getdns_general_2", &transaction_id, negative_callbackfn), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_3) + { + /* + * name = invalid domain (too many octets) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, + "getdns_general_3", &transaction_id, negative_callbackfn), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_4) + { + /* + * name = invalid domain (label too long) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, + "getdns_general_4", &transaction_id, negative_callbackfn), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_5) + { + /* + * callbackfn = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_5", &transaction_id, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_6) + { + /* + * name = "google.com" + * request_type = 0 (minimum valid RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", 0, NULL, + "getdns_general_6", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_7) + { + /* + * name = "google.com" + * request_type = 65279 (maximum unassigned RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, + "getdns_general_7", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_8) + { + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_8", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_9) + { + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_AAAA + * expect: NOERROR response with AAAA records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of AAAA records ("type": 28) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, + "getdns_general_9", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_10) + { + /* + * name = "thisdomainsurelydoesntexist.com" + * request_type = GETDNS_RRTYPE_TXT` + * expect: NXDOMAIN response with SOA record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 3 + * ancount = 0 (number of records in ANSWER section) + * nscount = 1 (number of records in AUTHORITY section) + * and SOA record ("type": 6) present in "authority" list + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "thisdomainsurelydoesntexist.com"; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, + "getdns_general_10", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_11) + { + /* + * name = "hampster.com" need to replace this with domain from unbound zone + * request_type = GETDNS_RRTYPE_MX + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, + "getdns_general_11", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_12) + { + /* + * name = "google.com" need to swap this out for max domain name length with max lable length` + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + "getdns_general_12", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_13) + { + /* + * name = "75.101.146.66" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, + "getdns_general_13", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + START_TEST (getdns_general_14) + { + /* + * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, + "getdns_general_14", &transaction_id, positive_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + EVENT_LOOP; + } + END_TEST + + Suite * + getdns_general_suite (void) + { + Suite *s = suite_create ("getdns_general()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_general_1); + tcase_add_test(tc_neg, getdns_general_2); + tcase_add_test(tc_neg, getdns_general_3); + tcase_add_test(tc_neg, getdns_general_4); + tcase_add_test(tc_neg, getdns_general_5); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_general_6); + tcase_add_test(tc_pos, getdns_general_7); + tcase_add_test(tc_pos, getdns_general_8); + tcase_add_test(tc_pos, getdns_general_9); + tcase_add_test(tc_pos, getdns_general_10); + tcase_add_test(tc_pos, getdns_general_11); + tcase_add_test(tc_pos, getdns_general_12); + tcase_add_test(tc_pos, getdns_general_13); + tcase_add_test(tc_pos, getdns_general_14); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif diff --git a/src/test/check_getdns_general_sync.h b/src/test/check_getdns_general_sync.h new file mode 100644 index 00000000..a55531d2 --- /dev/null +++ b/src/test/check_getdns_general_sync.h @@ -0,0 +1,298 @@ +#ifndef _check_getdns_general_sync_h_ +#define _check_getdns_general_sync_h_ + + START_TEST (getdns_general_sync_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + STANDARD_TEST_DECLARATIONS; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general_sync()"); + } + END_TEST + + START_TEST (getdns_general_sync_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); + } + END_TEST + + START_TEST (getdns_general_sync_3) + { + /* + * name = invalid domain (too many octets) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); + } + END_TEST + + START_TEST (getdns_general_sync_4) + { + /* + * name = invalid domain (label too long) + * expect: GETDNS_RETURN_BAD_DOMAIN_NAME + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); + } + END_TEST + + START_TEST (getdns_general_sync_5) + { + /* + * response = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + STANDARD_TEST_DECLARATIONS; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); + } + END_TEST + + START_TEST (getdns_general_sync_6) + { + /* + * name = "google.com" + * request_type = 0 (minimum valid RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", 0, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_nodata(&ex_response); + } + END_TEST + + START_TEST (getdns_general_sync_7) + { + /* + * name = "google.com" + * request_type = 65279 (maximum unassigned RRTYPE) + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", 65279, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_nodata(&ex_response); + } + END_TEST + + START_TEST (getdns_general_sync_8) + { + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); + } + END_TEST + + START_TEST (getdns_general_sync_9) + { + /* + * name = "google.com" + * request_type = GETDNS_RRTYPE_AAAA + * expect: NOERROR response with AAAA records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of AAAA records ("type": 28) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, FALSE, TRUE); + } + END_TEST + + START_TEST (getdns_general_sync_10) + { + /* + * name = "thisdomainsurelydoesntexist.com" + * request_type = GETDNS_RRTYPE_TXT` + * expect: NXDOMAIN response with SOA record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 3 + * ancount = 0 (number of records in ANSWER section) + * nscount = 1 (number of records in AUTHORITY section) + * and SOA record ("type": 6) present in "authority" list + */ + STANDARD_TEST_DECLARATIONS; + const char *name = "thisdomainsurelydoesntexist.com"; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_TXT, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + } + END_TEST + + START_TEST (getdns_general_sync_11) + { + /* + * name = "hampster.com" need to replace this with domain from unbound zone + * request_type = GETDNS_RRTYPE_MX + * expect: NOERROR/NODATA response: + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount = 0 (number of records in ANSWER section) + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_nodata(&ex_response); + } + END_TEST + + START_TEST (getdns_general_sync_12) + { + /* + * name = "google.com" need to swap this out for max domain name length with max lable length` + * request_type = GETDNS_RRTYPE_A + * expect: NOERROR response with A records + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount >= 1 (number of records in ANSWER section) + * and equals number of A records ("type": 1) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_address_in_answer(&ex_response, TRUE, FALSE); + } + END_TEST + + START_TEST (getdns_general_sync_13) + { + /* + * name = "75.101.146.66" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); + } + END_TEST + + START_TEST (getdns_general_sync_14) + { + /* + * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data + * request_type = GETDNS_RRTYPE_PTR + * expect: NOERROR response with PTR record + * status = GETDNS_RESPSTATUS_GOOD + * rcode = 0 + * ancount == 1 (number of records in ANSWER section) + * and PTR record found ("type": 12) in "answer" list + */ + STANDARD_TEST_DECLARATIONS; + + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); + } + END_TEST + + Suite * + getdns_general_sync_suite (void) + { + Suite *s = suite_create ("getdns_general_sync()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_general_sync_1); + tcase_add_test(tc_neg, getdns_general_sync_2); + tcase_add_test(tc_neg, getdns_general_sync_3); + tcase_add_test(tc_neg, getdns_general_sync_4); + tcase_add_test(tc_neg, getdns_general_sync_5); + suite_add_tcase(s, tc_neg); + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + + tcase_add_test(tc_pos, getdns_general_sync_6); + tcase_add_test(tc_pos, getdns_general_sync_7); + tcase_add_test(tc_pos, getdns_general_sync_8); + tcase_add_test(tc_pos, getdns_general_sync_9); + tcase_add_test(tc_pos, getdns_general_sync_10); + tcase_add_test(tc_pos, getdns_general_sync_11); + tcase_add_test(tc_pos, getdns_general_sync_12); + tcase_add_test(tc_pos, getdns_general_sync_13); + tcase_add_test(tc_pos, getdns_general_sync_14); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 181111fa693175cff409f34d786716cb9de74081 Mon Sep 17 00:00:00 2001 From: Bryan Graham Date: Thu, 19 Dec 2013 19:44:54 -0500 Subject: [PATCH 06/35] delete check_getdns_address_sync.c check_getdns_general_sync.c --- src/test/check_getdns_address_sync.c | 566 ------------------------- src/test/check_getdns_general_sync.c | 611 --------------------------- 2 files changed, 1177 deletions(-) delete mode 100644 src/test/check_getdns_address_sync.c delete mode 100644 src/test/check_getdns_general_sync.c diff --git a/src/test/check_getdns_address_sync.c b/src/test/check_getdns_address_sync.c deleted file mode 100644 index 1e1ffab9..00000000 --- a/src/test/check_getdns_address_sync.c +++ /dev/null @@ -1,566 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define TRUE 1 -#define FALSE 0 -#define MAXLEN 200 - -struct extracted_response { - uint32_t top_answer_type; - struct getdns_bindata *top_canonical_name; - struct getdns_list *just_address_answers; - struct getdns_list *replies_full; - struct getdns_list *replies_tree; - struct getdns_dict *replies_tree_sub_dict; - struct getdns_list *additional; - struct getdns_list *answer; - uint32_t answer_type; - struct getdns_list *authority; - struct getdns_bindata *canonical_name; - struct getdns_dict *header; - struct getdns_dict *question; - uint32_t status; -}; - -/* - * The STANDARD_TEST_DECLARATIONS macro defines - * the standard variable definitions most tests - * will need. - * - */ -#define STANDARD_TEST_DECLARATIONS \ - struct getdns_context *context = NULL; \ - struct getdns_dict *response = NULL; \ - size_t buflen = MAXLEN; \ - char error_string[MAXLEN]; - -/* - * The ASSERT_RC macro is used to assert - * whether the return code from the last - * getdns API call is what was expected. - */ -#define ASSERT_RC(rc, expected_rc, prefix) \ - getdns_strerror(rc, error_string, buflen); \ - ck_assert_msg(rc == expected_rc, \ - "%s: expecting %s: %d, but received: %d: %s", \ - prefix, #expected_rc, expected_rc, rc, error_string); - -/* - * The CONTEXT_CREATE macro is used to \ - * create a context and assert the proper \ - * return code is returned. \ - */ \ -#define CONTEXT_CREATE \ - ASSERT_RC(getdns_context_create(&context, TRUE), \ - GETDNS_RETURN_GOOD, \ - "Return code from getdns_context_create()"); - -/* \ - * The process_response macro declares the \ - * variables needed to house the response and \ - * calls the function that extracts it. \ - */ \ -#define EXTRACT_RESPONSE \ - struct extracted_response ex_response; \ - extract_response(response, &ex_response); - -void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); -void assert_noerror(struct extracted_response *ex_response); -void assert_nodata(struct extracted_response *ex_response); -void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); -void assert_nxdomain(struct extracted_response *ex_response); -void assert_soa_in_authority(struct extracted_response *ex_response); -void assert_ptr_in_answer(struct extracted_response *ex_response); - -START_TEST (getdns_address_sync_1) -{ - /* - * context = NULL - * expect: GETDNS_RETURN_BAD_CONTEXT - */ - STANDARD_TEST_DECLARATIONS; - ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), - GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_address_sync()"); -} -END_TEST - -START_TEST (getdns_address_sync_2) -{ - /* - * name = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR - */ - STANDARD_TEST_DECLARATIONS; - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); -} -END_TEST - -START_TEST (getdns_address_sync_3) -{ - /* - * name = invalid domain (too many octets) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, name, NULL, &response), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); -} -END_TEST - -START_TEST (getdns_address_sync_4) -{ - /* - * name = invalid domain (label too long) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, name, NULL, &response), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); -} -END_TEST - -START_TEST (getdns_address_sync_5) -{ - /* - * response = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR - */ - STANDARD_TEST_DECLARATIONS; - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); -} -END_TEST - -START_TEST (getdns_address_sync_6) -{ - /* - * name = "google.com" - * expect: NOERROR response: - * status = GETDNS_RETURN_GOOD - * rcode = 0 - todo: create zonefile with exact count - * ancount = tbd (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); -} -END_TEST - -START_TEST (getdns_address_sync_7) -{ - /* - * name = "localhost" - * expect: NOERROR response: - * expect: GETDNS_RETURN_GOOD - * rcode = 0 - todo: investigate that proper search order is set for resolution (is local being checked) - todo: create zonefile with exact count - * ancount = tbd (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); -} -END_TEST - -START_TEST (getdns_address_sync_8) -{ - /* - * name = "google.joe" - * status = GETDNS_RETURN_GOOD for NXDOMAIN - * expect: NXDOMAIN response with SOA record - * rcode = 0 - todo: investigate that proper search order is set for resolution (is local being checked) - todo: create host file with exact count - * ancount >= 1 (number of records in ANSWER section) - * and one SOA record ("type": 6) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "google.joe", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - assert_nxdomain(&ex_response); - assert_nodata(&ex_response); - assert_soa_in_authority(&ex_response); - //assert_address_in_answer(&ex_response, TRUE, FALSE); -} -END_TEST - - - -START_TEST (getdns_address_sync_9) -{ - /* - * name = "hampster.com" need to replace this with domain from unbound zone - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "hampster.com", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); -} -END_TEST - -START_TEST (getdns_address_sync_10) -{ - /* - * name = "google.com" need to swap this out for max domain name length with max lable length` - * expect: NOERROR response with A records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 11 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, TRUE, FALSE); -} -END_TEST - -START_TEST (getdns_address_sync_11) -{ - /* - * name = "75.101.146.66" need to change this to local unbound data - * status = GETDNS_RETURN_GOOD for NXDOMAIN - * expect: NXDOMAIN response with SOA record for NUMERICAL data - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and one SOA record ("type": 6) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "75.101.146.66", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); - assert_nxdomain(&ex_response); - assert_nodata(&ex_response); - assert_soa_in_authority(&ex_response); -} -END_TEST - -START_TEST (getdns_address_sync_12) -{ - /* - * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data - * status = GETDNS_RETURN_GOOD for NXDOMAIN - * expect: NXDOMAIN response with SOA record for NUMERICAL data - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and one SOA record ("type": 6) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_address_sync(context, "2607:f8b0:4006:802::1007", NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); - EXTRACT_RESPONSE; - printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); - assert_nxdomain(&ex_response); - assert_nodata(&ex_response); - assert_soa_in_authority(&ex_response); -} -END_TEST - -Suite * -getdns_address_sync_suite (void) -{ - Suite *s = suite_create ("getdns_address_sync()"); - - /* Negative test caseis */ - TCase *tc_neg = tcase_create("Negative"); - tcase_add_test(tc_neg, getdns_address_sync_1); - tcase_add_test(tc_neg, getdns_address_sync_2); - tcase_add_test(tc_neg, getdns_address_sync_3); - tcase_add_test(tc_neg, getdns_address_sync_4); - tcase_add_test(tc_neg, getdns_address_sync_5); - suite_add_tcase(s, tc_neg); - /* Positive test cases */ - TCase *tc_pos = tcase_create("Positive"); - - tcase_add_test(tc_pos, getdns_address_sync_6); - tcase_add_test(tc_pos, getdns_address_sync_7); - tcase_add_test(tc_pos, getdns_address_sync_8); - tcase_add_test(tc_pos, getdns_address_sync_9); - tcase_add_test(tc_pos, getdns_address_sync_10); - tcase_add_test(tc_pos, getdns_address_sync_11); - tcase_add_test(tc_pos, getdns_address_sync_12); - suite_add_tcase(s, tc_pos); - - return s; -} - -/* - * extract_response extracts all of the various information - * a test may want to look at from the response. - */ -void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - - ck_assert_msg(response != NULL, "Response should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), - GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); - - ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), - GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); - - ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), - GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); - ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); - ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); - ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); - - ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); - ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), - GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); - ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); - ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), - GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); - ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); - - ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), - GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); - - ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), - GETDNS_RETURN_GOOD, "Failed to extract \"header\""); - ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); - - ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), - GETDNS_RETURN_GOOD, "Failed to extract \"question\""); - ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), - GETDNS_RETURN_GOOD, "Failed to extract \"status\""); -} - -/* - * assert_noerror asserts that the rcode is 0 - */ -void assert_noerror(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t rcode; - - ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); - ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); - ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); -} - -/* - * assert_nodata asserts that ancount in the header and the - * of the answer section (list) are both zero. - */ -void assert_nodata(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); - ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); -} - -/* - * assert_address_records_in_answer asserts that ancount in the header - * is >= 1, ancount is equal to the length of "answer", and that all of - * the records in the answer section are A and/or AAAA resource records - * based on the value of the a/aaaa arguments. - */ -void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t address_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); - ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); - switch (type) - { - case GETDNS_RRTYPE_A: - if(a && type == GETDNS_RRTYPE_A) - address_records++; - case GETDNS_RRTYPE_AAAA: - if(aaaa && type == GETDNS_RRTYPE_AAAA) - address_records++; - } - } - ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", - ancount, address_records); -} - -/* - * assert_nxdomain asserts that an NXDOMAIN response was - * was returned for the DNS query meaning: - * rcode == 3 - */ -void assert_nxdomain(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t rcode; - - ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); - ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); - ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); -} - -/* - * assert_soa_in_authority asserts that a SOA record was - * returned in the authority sections. - */ -void assert_soa_in_authority(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t nscount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t soa_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), - GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); - ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); - - ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); - ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); - if(type == GETDNS_RRTYPE_SOA) - soa_records++; - } - - ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); -} - -/* - * assert_ptr_in_answer asserts that a PTR record was - * returned in the answer sections. - */ -void assert_ptr_in_answer(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t ptr_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); - ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); - if(type == GETDNS_RRTYPE_PTR) - ptr_records++; - } - - ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); -} - -int -main (void) -{ - int number_failed; - Suite *s = getdns_address_sync_suite(); - SRunner *sr = srunner_create(s); - srunner_set_log(sr, "getdns_address_sync_test.log"); - srunner_run_all(sr, CK_NORMAL); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/src/test/check_getdns_general_sync.c b/src/test/check_getdns_general_sync.c deleted file mode 100644 index c474596f..00000000 --- a/src/test/check_getdns_general_sync.c +++ /dev/null @@ -1,611 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define TRUE 1 -#define FALSE 0 -#define MAXLEN 200 - -struct extracted_response { - uint32_t top_answer_type; - struct getdns_bindata *top_canonical_name; - struct getdns_list *just_address_answers; - struct getdns_list *replies_full; - struct getdns_list *replies_tree; - struct getdns_dict *replies_tree_sub_dict; - struct getdns_list *additional; - struct getdns_list *answer; - uint32_t answer_type; - struct getdns_list *authority; - struct getdns_bindata *canonical_name; - struct getdns_dict *header; - struct getdns_dict *question; - uint32_t status; -}; - -/* - * The STANDARD_TEST_DECLARATIONS macro defines - * ithe standard variable definitions most tests - * will need. - */ -#define STANDARD_TEST_DECLARATIONS \ - struct getdns_context *context = NULL; \ - struct getdns_dict *response = NULL; \ - size_t buflen = MAXLEN; \ - char error_string[MAXLEN]; - -/* - * The ASSERT_RC macro is used to assert - * whether the return code from the last - * getdns API call is what was expected. - */ -#define ASSERT_RC(rc, expected_rc, prefix) \ - getdns_strerror(rc, error_string, buflen); \ - ck_assert_msg(rc == expected_rc, \ - "%s: expecting %s: %d, but received: %d: %s", \ - prefix, #expected_rc, expected_rc, rc, error_string); - -/* - * The CONTEXT_CREATE macro is used to \ - * create a context and assert the proper \ - * return code is returned. \ - */ \ -#define CONTEXT_CREATE \ - ASSERT_RC(getdns_context_create(&context, TRUE), \ - GETDNS_RETURN_GOOD, \ - "Return code from getdns_context_create()"); - -/* \ - * The process_response macro declares the \ - * variables needed to house the response and \ - * calls the function that extracts it. \ - */ \ -#define EXTRACT_RESPONSE \ - struct extracted_response ex_response; \ - extract_response(response, &ex_response); - -void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); -void assert_noerror(struct extracted_response *ex_response); -void assert_nodata(struct extracted_response *ex_response); -void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); -void assert_nxdomain(struct extracted_response *ex_response); -void assert_soa_in_authority(struct extracted_response *ex_response); -void assert_ptr_in_answer(struct extracted_response *ex_response); - -START_TEST (getdns_general_sync_1) -{ - /* - * context = NULL - * expect: GETDNS_RETURN_BAD_CONTEXT - */ - STANDARD_TEST_DECLARATIONS; - ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general_sync()"); -} -END_TEST - -START_TEST (getdns_general_sync_2) -{ - /* - * name = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR - */ - STANDARD_TEST_DECLARATIONS; - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); -} -END_TEST - -START_TEST (getdns_general_sync_3) -{ - /* - * name = invalid domain (too many octets) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); -} -END_TEST - -START_TEST (getdns_general_sync_4) -{ - /* - * name = invalid domain (label too long) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); -} -END_TEST - -START_TEST (getdns_general_sync_5) -{ - /* - * response = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR - */ - STANDARD_TEST_DECLARATIONS; - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); -} -END_TEST - -START_TEST (getdns_general_sync_6) -{ - /* - * name = "google.com" - * request_type = 0 (minimum valid RRTYPE) - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "google.com", 0, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_nodata(&ex_response); -} -END_TEST - -START_TEST (getdns_general_sync_7) -{ - /* - * name = "google.com" - * request_type = 65279 (maximum unassigned RRTYPE) - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "google.com", 65279, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_nodata(&ex_response); -} -END_TEST - -START_TEST (getdns_general_sync_8) -{ - /* - * name = "google.com" - * request_type = GETDNS_RRTYPE_A - * expect: NOERROR response with A records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and equals number of A records ("type": 1) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, TRUE, FALSE); -} -END_TEST - -START_TEST (getdns_general_sync_9) -{ - /* - * name = "google.com" - * request_type = GETDNS_RRTYPE_AAAA - * expect: NOERROR response with AAAA records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and equals number of AAAA records ("type": 28) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, FALSE, TRUE); -} -END_TEST - -START_TEST (getdns_general_sync_10) -{ - /* - * name = "thisdomainsurelydoesntexist.com" - * request_type = GETDNS_RRTYPE_TXT` - * expect: NXDOMAIN response with SOA record - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 3 - * ancount = 0 (number of records in ANSWER section) - * nscount = 1 (number of records in AUTHORITY section) - * and SOA record ("type": 6) present in "authority" list - */ - STANDARD_TEST_DECLARATIONS; - const char *name = "thisdomainsurelydoesntexist.com"; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_TXT, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_nxdomain(&ex_response); - assert_nodata(&ex_response); - assert_soa_in_authority(&ex_response); -} -END_TEST - -START_TEST (getdns_general_sync_11) -{ - /* - * name = "hampster.com" need to replace this with domain from unbound zone - * request_type = GETDNS_RRTYPE_MX - * expect: NOERROR/NODATA response: - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount = 0 (number of records in ANSWER section) - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_nodata(&ex_response); -} -END_TEST - -START_TEST (getdns_general_sync_12) -{ - /* - * name = "google.com" need to swap this out for max domain name length with max lable length` - * request_type = GETDNS_RRTYPE_A - * expect: NOERROR response with A records - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount >= 1 (number of records in ANSWER section) - * and equals number of A records ("type": 1) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, TRUE, FALSE); -} -END_TEST - -START_TEST (getdns_general_sync_13) -{ - /* - * name = "75.101.146.66" need to change this to local unbound data - * request_type = GETDNS_RRTYPE_PTR - * expect: NOERROR response with PTR record - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount == 1 (number of records in ANSWER section) - * and PTR record found ("type": 12) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_ptr_in_answer(&ex_response); -} -END_TEST - -START_TEST (getdns_general_sync_14) -{ - /* - * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data - * request_type = GETDNS_RRTYPE_PTR - * expect: NOERROR response with PTR record - * status = GETDNS_RESPSTATUS_GOOD - * rcode = 0 - * ancount == 1 (number of records in ANSWER section) - * and PTR record found ("type": 12) in "answer" list - */ - STANDARD_TEST_DECLARATIONS; - - CONTEXT_CREATE; - ASSERT_RC(getdns_general_sync(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, &response), - GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - EXTRACT_RESPONSE; - assert_noerror(&ex_response); - assert_ptr_in_answer(&ex_response); -} -END_TEST - -Suite * -getdns_general_sync_suite (void) -{ - Suite *s = suite_create ("getdns_general_sync()"); - - /* Negative test caseis */ - TCase *tc_neg = tcase_create("Negative"); - tcase_add_test(tc_neg, getdns_general_sync_1); - tcase_add_test(tc_neg, getdns_general_sync_2); - tcase_add_test(tc_neg, getdns_general_sync_3); - tcase_add_test(tc_neg, getdns_general_sync_4); - tcase_add_test(tc_neg, getdns_general_sync_5); - suite_add_tcase(s, tc_neg); - - /* Positive test cases */ - TCase *tc_pos = tcase_create("Positive"); - tcase_add_test(tc_pos, getdns_general_sync_6); - tcase_add_test(tc_pos, getdns_general_sync_7); - tcase_add_test(tc_pos, getdns_general_sync_8); - tcase_add_test(tc_pos, getdns_general_sync_9); - tcase_add_test(tc_pos, getdns_general_sync_10); - tcase_add_test(tc_pos, getdns_general_sync_11); - tcase_add_test(tc_pos, getdns_general_sync_12); - tcase_add_test(tc_pos, getdns_general_sync_13); - tcase_add_test(tc_pos, getdns_general_sync_14); - suite_add_tcase(s, tc_pos); - - return s; -} - -/* - * extract_response extracts all of the various information - * a test may want to look at from the response. - */ -void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - - ck_assert_msg(response != NULL, "Response should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), - GETDNS_RETURN_GOOD, "Failed to extract \"top answer_type\""); - - ASSERT_RC(getdns_dict_get_bindata(response, "canonical_name", &ex_response->top_canonical_name), - GETDNS_RETURN_GOOD, "Failed to extract \"top canonical_name\""); - - ASSERT_RC(getdns_dict_get_list(response, "just_address_answers", &ex_response->just_address_answers), - GETDNS_RETURN_GOOD, "Failed to extract \"just_address_answers\""); - ck_assert_msg(ex_response->just_address_answers != NULL, "just_address_answers should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(response, "replies_full", &ex_response->replies_full), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_full\""); - ck_assert_msg(ex_response->replies_full != NULL, "replies_full should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(response, "replies_tree", &ex_response->replies_tree), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree\""); - ck_assert_msg(ex_response->replies_tree != NULL, "replies_tree should not be NULL"); - - ASSERT_RC(getdns_list_get_dict(ex_response->replies_tree, 0, &ex_response->replies_tree_sub_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"replies_tree[0]\""); - ck_assert_msg(ex_response->replies_tree_sub_dict != NULL, "replies_tree[0] dict should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "additional", &ex_response->additional), - GETDNS_RETURN_GOOD, "Failed to extract \"additional\""); - ck_assert_msg(ex_response->additional != NULL, "additional should not be NULL"); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "answer", &ex_response->answer), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\""); - ck_assert_msg(ex_response->answer != NULL, "answer should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(ex_response->replies_tree_sub_dict, "answer_type", &ex_response->answer_type), - GETDNS_RETURN_GOOD, "Failed to extract \"answer_type\""); - - ASSERT_RC(getdns_dict_get_list(ex_response->replies_tree_sub_dict, "authority", &ex_response->authority), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\""); - ck_assert_msg(ex_response->authority != NULL, "authority should not be NULL"); - - ASSERT_RC(getdns_dict_get_bindata(ex_response->replies_tree_sub_dict, "canonical_name", &ex_response->canonical_name), - GETDNS_RETURN_GOOD, "Failed to extract \"canonical_name\""); - - ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "header", &ex_response->header), - GETDNS_RETURN_GOOD, "Failed to extract \"header\""); - ck_assert_msg(ex_response->header != NULL, "header should not be NULL"); - - ASSERT_RC(getdns_dict_get_dict(ex_response->replies_tree_sub_dict, "question", &ex_response->question), - GETDNS_RETURN_GOOD, "Failed to extract \"question\""); - ck_assert_msg(ex_response->question != NULL, "question should not be NULL"); - - ASSERT_RC(getdns_dict_get_int(response, "status", &ex_response->status), - GETDNS_RETURN_GOOD, "Failed to extract \"status\""); -} - -/* - * assert_noerror asserts that the rcode is 0 - */ -void assert_noerror(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t rcode; - - ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); - ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); - ck_assert_msg(rcode == 0, "Expected rcode == 0, got %d", rcode); -} - -/* - * assert_nodata asserts that ancount in the header and the - * of the answer section (list) are both zero. - */ -void assert_nodata(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); - ck_assert_msg(ancount == 0, "Expected ancount == 0, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == 0, "Expected \"answer\" length == 0, got %d", length); -} - -/* - * assert_address_records_in_answer asserts that ancount in the header - * is >= 1, ancount is equal to the length of "answer", and that all of - * the records in the answer section are A and/or AAAA resource records - * based on the value of the a/aaaa arguments. - */ -void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t address_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); - ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); - switch (type) - { - case GETDNS_RRTYPE_A: - if(a && type == GETDNS_RRTYPE_A) - address_records++; - case GETDNS_RRTYPE_AAAA: - if(aaaa && type == GETDNS_RRTYPE_AAAA) - address_records++; - } - } - ck_assert_msg(ancount == address_records, "ancount: %d address records mismatch: %d", - ancount, address_records); -} - -/* - * assert_nxdomain asserts that an NXDOMAIN response was - * was returned for the DNS query meaning: - * rcode == 3 - */ -void assert_nxdomain(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t rcode; - - ASSERT_RC(ex_response->status, GETDNS_RESPSTATUS_GOOD, "Unexpected value for \"status\""); - ASSERT_RC(getdns_dict_get_int(ex_response->header, "rcode", &rcode), GETDNS_RETURN_GOOD, "Failed to extract \"rcode\""); - ck_assert_msg(rcode == 3, "Expected rcode == 0, got %d", rcode); -} - -/* - * assert_soa_in_authority asserts that a SOA record was - * returned in the authority sections. - */ -void assert_soa_in_authority(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t nscount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t soa_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "nscount", &nscount), - GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); - ck_assert_msg(nscount >= 1, "Expected nscount >= 1, got %d", nscount); - - ASSERT_RC(getdns_list_get_length(ex_response->authority, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\" length"); - ck_assert_msg(length == nscount, "Expected \"authority\" length == nscount: %d, got %d", nscount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->authority, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"authority\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from authority record"); - if(type == GETDNS_RRTYPE_SOA) - soa_records++; - } - - ck_assert_msg(soa_records == 1, "Expected to find one SOA record in authority section, got %d", soa_records); -} - -/* - * assert_ptr_in_answer asserts that a PTR record was - * returned in the answer sections. - */ -void assert_ptr_in_answer(struct extracted_response *ex_response) -{ - size_t buflen = MAXLEN; - char error_string[MAXLEN]; - uint32_t ancount; - size_t length; - struct getdns_dict *rr_dict; - uint32_t type; - uint32_t ptr_records = 0; - - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), - GETDNS_RETURN_GOOD, "Failed to extract \"nscount\""); - ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); - - ASSERT_RC(getdns_list_get_length(ex_response->answer, &length), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" length"); - ck_assert_msg(length == ancount, "Expected \"answer\" length == ancount: %d, got %d", ancount, length); - - for(size_t i = 0; i < length; i++) - { - ASSERT_RC(getdns_list_get_dict(ex_response->answer, i, &rr_dict), - GETDNS_RETURN_GOOD, "Failed to extract \"answer\" record"); - ASSERT_RC(getdns_dict_get_int(rr_dict, "type", &type), - GETDNS_RETURN_GOOD, "Failed to extract \"type\" from answer record"); - if(type == GETDNS_RRTYPE_PTR) - ptr_records++; - } - - ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); -} - -int -main (void) -{ - int number_failed; - Suite *s = getdns_general_sync_suite(); - SRunner *sr = srunner_create(s); - srunner_set_log(sr, "getdns_general_sync_test.log"); - srunner_run_all(sr, CK_NORMAL); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} From b35f533ce313b9734e557d5e383e7abad6168504 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 20 Dec 2013 00:00:41 -0500 Subject: [PATCH 07/35] A little cleanup to eliminate some compile warnings. --- src/test/check_getdns.c | 11 +++--- src/test/check_getdns_address_sync.h | 24 ++++++------ src/test/check_getdns_common.c | 4 -- src/test/check_getdns_common.h | 56 ++++++++++++++++------------ src/test/check_getdns_general.h | 54 +++++++++++++-------------- src/test/check_getdns_general_sync.h | 28 +++++++------- src/test/check_getdns_libevent.h | 5 +++ 7 files changed, 96 insertions(+), 86 deletions(-) create mode 100644 src/test/check_getdns_libevent.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 0fea027e..de090cc8 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -5,10 +5,11 @@ #include #include #include +#include "check_getdns_libevent.h" #include "check_getdns_common.h" -#include "check_getdns_address_sync.h" -#include "check_getdns_general_sync.h" #include "check_getdns_general.h" +#include "check_getdns_general_sync.h" +#include "check_getdns_address_sync.h" int main (void) @@ -20,9 +21,9 @@ main (void) Suite *getdns_general_sync_suite (void); Suite *getdns_general_suite (void); - sr = srunner_create (getdns_address_sync_suite()); - srunner_add_suite (sr, getdns_general_sync_suite ()); - srunner_add_suite (sr, getdns_general_suite()); + sr = srunner_create(getdns_general_suite()); + srunner_add_suite(sr, getdns_general_sync_suite()); + srunner_add_suite(sr, getdns_address_sync_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h index 6d7ff79c..c1361348 100644 --- a/src/test/check_getdns_address_sync.h +++ b/src/test/check_getdns_address_sync.h @@ -8,7 +8,7 @@ * context = NULL * expect: GETDNS_RETURN_BAD_CONTEXT */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_address_sync()"); } @@ -20,7 +20,7 @@ * name = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); @@ -33,7 +33,7 @@ * name = invalid domain (too many octets) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, name, NULL, &response), @@ -47,7 +47,7 @@ * name = invalid domain (label too long) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, name, NULL, &response), @@ -61,7 +61,7 @@ * response = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); @@ -78,7 +78,7 @@ todo: create zonefile with exact count * ancount = tbd (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), @@ -99,7 +99,7 @@ todo: create zonefile with exact count * ancount = tbd (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), @@ -121,7 +121,7 @@ * ancount >= 1 (number of records in ANSWER section) * and one SOA record ("type": 6) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "google.joe", NULL, &response), @@ -145,7 +145,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "hampster.com", NULL, &response), @@ -164,7 +164,7 @@ * rcode = 0 * ancount >= 11 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), @@ -185,7 +185,7 @@ * ancount >= 1 (number of records in ANSWER section) * and one SOA record ("type": 6) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "75.101.146.66", NULL, &response), @@ -207,7 +207,7 @@ * ancount >= 1 (number of records in ANSWER section) * and one SOA record ("type": 6) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_address_sync(context, "2607:f8b0:4006:802::1007", NULL, &response), diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index b5f2d8a9..9ba6e7c4 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -6,8 +6,6 @@ #include #include #include "check_getdns_common.h" -#include - /* * extract_response extracts all of the various information @@ -15,7 +13,6 @@ */ void extract_response(struct getdns_dict *response, struct extracted_response *ex_response) { - ck_assert_msg(response != NULL, "Response should not be NULL"); ASSERT_RC(getdns_dict_get_int(response, "answer_type", &ex_response->top_answer_type), @@ -115,7 +112,6 @@ void assert_address_in_answer(struct extracted_response *ex_response, int a, int uint32_t address_records = 0; size_t i; - ASSERT_RC(getdns_dict_get_int(ex_response->header, "ancount", &ancount), GETDNS_RETURN_GOOD, "Failed to extract \"ancount\""); ck_assert_msg(ancount >= 1, "Expected ancount >= 1, got %d", ancount); diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index 75ced3f0..699fd0a2 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -23,30 +23,39 @@ }; /* - * The STANDARD_TEST_DECLARATIONS macro defines - * the standard variable definitions most tests - * will need. + * The SYNCHRONOUS_TEST_DECLARATIONS macro + * defines the standard variable definitions + * that synchronous will need. * */ - #define STANDARD_TEST_DECLARATIONS \ + #define SYNCHRONOUS_TEST_DECLARATIONS \ struct getdns_context *context = NULL; \ - struct getdns_dict *response = NULL; \ - struct event_base *event_base; \ - getdns_transaction_t transaction_id = 0; \ + struct getdns_dict *response = NULL; + + /* + * The ASYNCHRONOUS_TEST_DECLARATIONS macro + * defines the standard variable definitions + * that asynchronous tests will will need. + * + */ + #define ASYNCHRONOUS_TEST_DECLARATIONS \ + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; /* * The ASSERT_RC macro is used to assert * whether the return code from the last * getdns API call is what was expected. */ - #define ASSERT_RC(rc, expected_rc, prefix) \ - { \ - size_t buflen = MAXLEN; \ - char error_string[MAXLEN]; \ + #define ASSERT_RC(rc, expected_rc, prefix) \ + { \ + size_t buflen = MAXLEN; \ + char error_string[MAXLEN]; \ getdns_strerror(rc, error_string, buflen); \ - ck_assert_msg(rc == expected_rc, \ - "%s: expecting %s: %d, but received: %d: %s", \ - prefix, #expected_rc, expected_rc, rc, error_string); \ + ck_assert_msg(rc == expected_rc, \ + "%s: expecting %s: %d, but received: %d: %s", \ + prefix, #expected_rc, expected_rc, rc, error_string); \ } /* @@ -55,8 +64,8 @@ * return code is returned. */ #define CONTEXT_CREATE \ - ASSERT_RC(getdns_context_create(&context, TRUE), \ - GETDNS_RETURN_GOOD, \ + ASSERT_RC(getdns_context_create(&context, TRUE), \ + GETDNS_RETURN_GOOD, \ "Return code from getdns_context_create()"); /* @@ -64,26 +73,25 @@ * create an event base and put it in the * context. */ - #define EVENT_BASE_CREATE \ - event_base = event_base_new(); \ - ck_assert_msg(event_base != NULL, "Event base creation failed"); \ + #define EVENT_BASE_CREATE \ + event_base = event_base_new(); \ + ck_assert_msg(event_base != NULL, "Event base creation failed"); \ ASSERT_RC(getdns_extension_set_libevent_base(context, event_base), \ GETDNS_RETURN_GOOD, \ "Return code from getdns_extension_set_libevent_base()"); /* - * The EVENT_LOOP macro calls the event loop. + * The RUN_EVENT_LOOP macro calls the event loop. */ - #define EVENT_LOOP \ - int dispatch_return = event_base_dispatch(event_base); + #define RUN_EVENT_LOOP event_base_dispatch(event_base); /* * The process_response macro declares the * variables needed to house the response and * calls the function that extracts it. */ - #define EXTRACT_RESPONSE \ - struct extracted_response ex_response; \ + #define EXTRACT_RESPONSE \ + struct extracted_response ex_response; \ extract_response(response, &ex_response); void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index 92b30b2e..e9e51f13 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -7,7 +7,7 @@ * context = NULL * expect: GETDNS_RETURN_BAD_CONTEXT */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_1", &transaction_id, negative_callbackfn), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general()"); @@ -20,13 +20,13 @@ * name = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, "getdns_general_2", &transaction_id, negative_callbackfn), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -36,14 +36,14 @@ * name = invalid domain (too many octets) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, "getdns_general_3", &transaction_id, negative_callbackfn), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -53,14 +53,14 @@ * name = invalid domain (label too long) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, "getdns_general_4", &transaction_id, negative_callbackfn), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -70,13 +70,13 @@ * callbackfn = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_5", &transaction_id, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -90,14 +90,14 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", 0, NULL, "getdns_general_6", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -111,14 +111,14 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, "getdns_general_7", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -133,14 +133,14 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_8", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -155,14 +155,14 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of AAAA records ("type": 28) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, "getdns_general_9", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -178,7 +178,7 @@ * nscount = 1 (number of records in AUTHORITY section) * and SOA record ("type": 6) present in "authority" list */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; const char *name = "thisdomainsurelydoesntexist.com"; CONTEXT_CREATE; @@ -186,7 +186,7 @@ ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, "getdns_general_10", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -200,14 +200,14 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, "getdns_general_11", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -222,14 +222,14 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_12", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -244,14 +244,14 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, "getdns_general_13", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST @@ -266,14 +266,14 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + ASYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, "getdns_general_14", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); - EVENT_LOOP; + RUN_EVENT_LOOP; } END_TEST diff --git a/src/test/check_getdns_general_sync.h b/src/test/check_getdns_general_sync.h index a55531d2..0ad949f4 100644 --- a/src/test/check_getdns_general_sync.h +++ b/src/test/check_getdns_general_sync.h @@ -7,7 +7,7 @@ * context = NULL * expect: GETDNS_RETURN_BAD_CONTEXT */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general_sync()"); } @@ -19,7 +19,7 @@ * name = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); @@ -32,7 +32,7 @@ * name = invalid domain (too many octets) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), @@ -46,7 +46,7 @@ * name = invalid domain (label too long) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), @@ -60,7 +60,7 @@ * response = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); @@ -77,7 +77,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "google.com", 0, NULL, &response), @@ -98,7 +98,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "google.com", 65279, NULL, &response), @@ -120,7 +120,7 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), @@ -142,7 +142,7 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of AAAA records ("type": 28) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, &response), @@ -165,7 +165,7 @@ * nscount = 1 (number of records in AUTHORITY section) * and SOA record ("type": 6) present in "authority" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; const char *name = "thisdomainsurelydoesntexist.com"; CONTEXT_CREATE; @@ -188,7 +188,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, &response), @@ -210,7 +210,7 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), @@ -232,7 +232,7 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), @@ -254,7 +254,7 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - STANDARD_TEST_DECLARATIONS; + SYNCHRONOUS_TEST_DECLARATIONS; CONTEXT_CREATE; ASSERT_RC(getdns_general_sync(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, &response), diff --git a/src/test/check_getdns_libevent.h b/src/test/check_getdns_libevent.h new file mode 100644 index 00000000..3dbcaf75 --- /dev/null +++ b/src/test/check_getdns_libevent.h @@ -0,0 +1,5 @@ +#ifdef HAVE_EVENT2_EVENT_H +#include +#else +#include +#endif From d9c3df6ce8bdfca48002c7bf721466536acdaa78 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 20 Dec 2013 11:20:57 -0500 Subject: [PATCH 08/35] Added test suites for getdns_list_get_length() and getdns_list_get_data_type(). Removed any macros that performed variable declarations. --- src/test/check_getdns.c | 12 +- src/test/check_getdns_address_sync.h | 70 +++++-- src/test/check_getdns_common.h | 43 ++-- src/test/check_getdns_general.h | 88 +++++++-- src/test/check_getdns_general_sync.h | 77 ++++++-- src/test/check_getdns_list_get_data_type.h | 216 +++++++++++++++++++++ src/test/check_getdns_list_get_length.h | 102 ++++++++++ 7 files changed, 537 insertions(+), 71 deletions(-) create mode 100644 src/test/check_getdns_list_get_data_type.h create mode 100644 src/test/check_getdns_list_get_length.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index de090cc8..62c0b20a 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -10,6 +10,8 @@ #include "check_getdns_general.h" #include "check_getdns_general_sync.h" #include "check_getdns_address_sync.h" +#include "check_getdns_list_get_length.h" +#include "check_getdns_list_get_data_type.h" int main (void) @@ -17,13 +19,17 @@ main (void) int number_failed; SRunner *sr ; - Suite *getdns_address_sync_suite (void); - Suite *getdns_general_sync_suite (void); - Suite *getdns_general_suite (void); + Suite *getdns_address_sync_suite(void); + Suite *getdns_general_sync_suite(void); + Suite *getdns_general_suite(void); + Suite *getdns_list_get_length_suite(void); + Suite *getdns_list_get_data_type_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); srunner_add_suite(sr, getdns_address_sync_suite()); + srunner_add_suite(sr, getdns_list_get_length_suite()); + srunner_add_suite(sr, getdns_list_get_data_type_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h index c1361348..b5170c91 100644 --- a/src/test/check_getdns_address_sync.h +++ b/src/test/check_getdns_address_sync.h @@ -8,7 +8,9 @@ * context = NULL * expect: GETDNS_RETURN_BAD_CONTEXT */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_address_sync()"); } @@ -20,8 +22,11 @@ * name = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); } @@ -33,9 +38,12 @@ * name = invalid domain (too many octets) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, name, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); } @@ -47,9 +55,12 @@ * name = invalid domain (label too long) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, name, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); } @@ -61,8 +72,10 @@ * response = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); } @@ -78,12 +91,16 @@ todo: create zonefile with exact count * ancount = tbd (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); } END_TEST @@ -99,12 +116,16 @@ todo: create zonefile with exact count * ancount = tbd (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); } END_TEST @@ -121,21 +142,22 @@ * ancount >= 1 (number of records in ANSWER section) * and one SOA record ("type": 6) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.joe", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); - //assert_address_in_answer(&ex_response, TRUE, FALSE); } END_TEST - - START_TEST (getdns_address_sync_9) { /* @@ -145,12 +167,16 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "hampster.com", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); } END_TEST @@ -164,12 +190,16 @@ * rcode = 0 * ancount >= 11 (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); } @@ -185,12 +215,16 @@ * ancount >= 1 (number of records in ANSWER section) * and one SOA record ("type": 6) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "75.101.146.66", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); @@ -207,12 +241,16 @@ * ancount >= 1 (number of records in ANSWER section) * and one SOA record ("type": 6) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_address_sync(context, "2607:f8b0:4006:802::1007", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); @@ -247,6 +285,4 @@ return s; } - - #endif diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index 699fd0a2..d6c8f354 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -22,27 +22,6 @@ uint32_t status; }; - /* - * The SYNCHRONOUS_TEST_DECLARATIONS macro - * defines the standard variable definitions - * that synchronous will need. - * - */ - #define SYNCHRONOUS_TEST_DECLARATIONS \ - struct getdns_context *context = NULL; \ - struct getdns_dict *response = NULL; - - /* - * The ASYNCHRONOUS_TEST_DECLARATIONS macro - * defines the standard variable definitions - * that asynchronous tests will will need. - * - */ - #define ASYNCHRONOUS_TEST_DECLARATIONS \ - struct getdns_context *context = NULL; \ - struct event_base *event_base = NULL; \ - getdns_transaction_t transaction_id = 0; - /* * The ASSERT_RC macro is used to assert * whether the return code from the last @@ -67,7 +46,7 @@ ASSERT_RC(getdns_context_create(&context, TRUE), \ GETDNS_RETURN_GOOD, \ "Return code from getdns_context_create()"); - + /* * The EVENT_BASE_CREATE macro is used to * create an event base and put it in the @@ -84,6 +63,26 @@ * The RUN_EVENT_LOOP macro calls the event loop. */ #define RUN_EVENT_LOOP event_base_dispatch(event_base); + + /* + * The LIST_CREATE macro simply creates a + * list and verifies the returned pointer + * is not NULL. + */ + #define LIST_CREATE(list) \ + list = getdns_list_create(); \ + ck_assert_msg(list != NULL, \ + "NULL pointer returned by getdns_list_create()"); + + /* + * The DICT_CREATE macro simply creates a + * dict and verifies the returned pointer + * is not NULL. + */ + #define DICT_CREATE(dict) \ + dict = getdns_dict_create(); \ + ck_assert_msg(dict != NULL, \ + "NULL pointer returned by getdns_dict_create()"); /* * The process_response macro declares the diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index e9e51f13..90d86602 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -7,7 +7,9 @@ * context = NULL * expect: GETDNS_RETURN_BAD_CONTEXT */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + getdns_transaction_t transaction_id = 0; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_1", &transaction_id, negative_callbackfn), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general()"); @@ -20,12 +22,17 @@ * name = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; + CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, "getdns_general_2", &transaction_id, negative_callbackfn), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -36,13 +43,18 @@ * name = invalid domain (too many octets) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, "getdns_general_3", &transaction_id, negative_callbackfn), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -53,13 +65,18 @@ * name = invalid domain (label too long) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, "getdns_general_4", &transaction_id, negative_callbackfn), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -70,12 +87,17 @@ * callbackfn = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; + CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_5", &transaction_id, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -90,13 +112,17 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", 0, NULL, "getdns_general_6", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -111,13 +137,17 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, "getdns_general_7", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -133,13 +163,17 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_8", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -155,13 +189,17 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of AAAA records ("type": 28) in "answer" list */ - ASYNCHRONOUS_TEST_DECLARATIONS; - + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; + CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, "getdns_general_9", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -178,14 +216,18 @@ * nscount = 1 (number of records in AUTHORITY section) * and SOA record ("type": 6) present in "authority" list */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; const char *name = "thisdomainsurelydoesntexist.com"; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, "getdns_general_10", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -200,13 +242,17 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, "getdns_general_11", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -222,13 +268,17 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, "getdns_general_12", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -244,13 +294,17 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, "getdns_general_13", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST @@ -266,13 +320,17 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - ASYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; \ + struct event_base *event_base = NULL; \ + getdns_transaction_t transaction_id = 0; CONTEXT_CREATE; EVENT_BASE_CREATE; + ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, "getdns_general_14", &transaction_id, positive_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + RUN_EVENT_LOOP; } END_TEST diff --git a/src/test/check_getdns_general_sync.h b/src/test/check_getdns_general_sync.h index 0ad949f4..6df9b7bc 100644 --- a/src/test/check_getdns_general_sync.h +++ b/src/test/check_getdns_general_sync.h @@ -7,7 +7,9 @@ * context = NULL * expect: GETDNS_RETURN_BAD_CONTEXT */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general_sync()"); } @@ -19,8 +21,11 @@ * name = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); } @@ -32,9 +37,12 @@ * name = invalid domain (too many octets) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); } @@ -46,9 +54,12 @@ * name = invalid domain (label too long) * expect: GETDNS_RETURN_BAD_DOMAIN_NAME */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); } @@ -60,8 +71,10 @@ * response = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); } @@ -77,12 +90,16 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", 0, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_nodata(&ex_response); } @@ -98,12 +115,16 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", 65279, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_nodata(&ex_response); } @@ -120,12 +141,16 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); } @@ -142,12 +167,16 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of AAAA records ("type": 28) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_address_in_answer(&ex_response, FALSE, TRUE); } @@ -165,13 +194,17 @@ * nscount = 1 (number of records in AUTHORITY section) * and SOA record ("type": 6) present in "authority" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; const char *name = "thisdomainsurelydoesntexist.com"; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_TXT, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); @@ -188,12 +221,16 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_nodata(&ex_response); } @@ -210,12 +247,16 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); } @@ -232,12 +273,16 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_ptr_in_answer(&ex_response); } @@ -254,12 +299,16 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ - SYNCHRONOUS_TEST_DECLARATIONS; + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; CONTEXT_CREATE; + ASSERT_RC(getdns_general_sync(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); + EXTRACT_RESPONSE; + assert_noerror(&ex_response); assert_ptr_in_answer(&ex_response); } diff --git a/src/test/check_getdns_list_get_data_type.h b/src/test/check_getdns_list_get_data_type.h new file mode 100644 index 00000000..7c8c378a --- /dev/null +++ b/src/test/check_getdns_list_get_data_type.h @@ -0,0 +1,216 @@ +#ifndef _check_getdns_list_get_data_type_h_ +#define _check_getdns_list_get_data_type_h_ + + START_TEST (getdns_list_get_data_type_1) + { + /* + * list = NULL + * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_list *list = NULL; + size_t index = 0; + getdns_data_type answer; + + ASSERT_RC(getdns_list_get_data_type(list, index, &answer), + GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_data_type()"); + } + END_TEST + + START_TEST (getdns_list_get_data_type_2) + { + /* + * index is out of range + * Create a list, add an int to it, and then attempt + * to get the data type at index 1 + * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_list *list = NULL; + size_t index = 0; + getdns_data_type answer; + + ASSERT_RC(getdns_list_set_int(list, index, 1), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_int()"); + + index++; + ASSERT_RC(getdns_list_get_data_type(list, index, &answer), + GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_data_type()"); + + } + END_TEST + + START_TEST (getdns_list_get_data_type_3) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_list *list = NULL; + size_t index = 0; + + LIST_CREATE(list); + + ASSERT_RC(getdns_list_set_int(list, index, 1), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_int()"); + + ASSERT_RC(getdns_list_get_data_type(list, index, NULL), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_list_get_data_type()"); + + } + END_TEST + + START_TEST (getdns_list_get_data_type_4) + { + /* + * Create a list (empty) and attempt to get the + * data type at index 0. + * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_list *list = NULL; + size_t index = 0; + getdns_data_type answer; + + LIST_CREATE(list); + + ASSERT_RC(getdns_list_get_data_type(list, index, &answer), + GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_data_type()"); + + } + END_TEST + + START_TEST (getdns_list_get_data_type_5) + { + /* + * Create a list, create a dict, set list value at index 0 + * to the dict, and then get the data type at index 0. + * data type at index 0. + * expect: GETDNS_RETURN_GOOD + * answer = t_dict (retrieved data type) + */ + struct getdns_list *list = NULL; + struct getdns_dict *dict = NULL; + size_t index = 0; + getdns_data_type answer; + + LIST_CREATE(list); + DICT_CREATE(dict); + + ASSERT_RC(getdns_list_set_dict(list, index, dict), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_dict()"); + + ASSERT_RC(getdns_list_get_data_type(list, index, &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_data_type()"); + + ck_assert_msg(answer == t_dict, + "Wrong data type, expected t_dict: %d, got %d", t_dict, answer); + + } + END_TEST + + START_TEST (getdns_list_get_data_type_6) + { + /* + * Create a list, create a second list, set list value at + * index 0 to the second list, and then get the data type + * at index 0. + * expect: GETDNS_RETURN_GOOD + * answer = t_list (retrieved data type) + */ + struct getdns_list *list1 = NULL; + struct getdns_list *list2 = NULL; + size_t index = 0; + getdns_data_type answer; + + LIST_CREATE(list1); + LIST_CREATE(list2); + + ASSERT_RC(getdns_list_set_list(list1, index, list2), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_list()"); + + ASSERT_RC(getdns_list_get_data_type(list1, index, &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_data_type()"); + + ck_assert_msg(answer == t_list, + "Wrong data type, expected t_list: %d, got %d", t_list, answer); + + } + END_TEST + + START_TEST (getdns_list_get_data_type_7) + { + /* + * Create a list, create some bindata, set list value at + * index 0 to the bindata, and then get the data type at + * index 0. + * expect: GETDNS_RETURN_GOOD + * answer = t_bindata (retrieved data type) + */ + struct getdns_list *list = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + size_t index = 0; + getdns_data_type answer; + + LIST_CREATE(list); + + ASSERT_RC(getdns_list_set_bindata(list, index, &bindata), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_bindata()"); + + ASSERT_RC(getdns_list_get_data_type(list, index, &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_data_type()"); + + ck_assert_msg(answer == t_bindata, + "Wrong data type, expected t_bindata: %d, got %d", t_bindata, answer); + + } + END_TEST + + START_TEST (getdns_list_get_data_type_8) + { + /* + * Create a list, set list value at index 0 to 100 (int), + * and then get the data type at index 0. + * expect: GETDNS_RETURN_GOOD + * answer = t_int (retrieved data type) + */ + struct getdns_list *list = NULL; + size_t index = 0; + getdns_data_type answer; + + LIST_CREATE(list); + + ASSERT_RC(getdns_list_set_int(list, index, 100), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_int()"); + + ASSERT_RC(getdns_list_get_data_type(list, index, &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_data_type()"); + + ck_assert_msg(answer == t_int, + "Wrong data type, expected t_int: %d, got %d", t_int, answer); + + } + END_TEST + + Suite * + getdns_list_get_data_type_suite (void) + { + Suite *s = suite_create ("getdns_list_get_data_type()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_list_get_data_type_1); + tcase_add_test(tc_neg, getdns_list_get_data_type_2); + tcase_add_test(tc_neg, getdns_list_get_data_type_3); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_list_get_data_type_4); + tcase_add_test(tc_pos, getdns_list_get_data_type_5); + tcase_add_test(tc_pos, getdns_list_get_data_type_6); + tcase_add_test(tc_pos, getdns_list_get_data_type_7); + tcase_add_test(tc_pos, getdns_list_get_data_type_8); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif diff --git a/src/test/check_getdns_list_get_length.h b/src/test/check_getdns_list_get_length.h new file mode 100644 index 00000000..46657f04 --- /dev/null +++ b/src/test/check_getdns_list_get_length.h @@ -0,0 +1,102 @@ +#ifndef _check_getdns_list_get_length_h_ +#define _check_getdns_list_get_length_h_ + + START_TEST (getdns_list_get_length_1) + { + /* + * list = NULL + * expect = GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_list *list = NULL; + size_t length; + + ASSERT_RC(getdns_list_get_length(list, &length), + GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_length()"); + + } + END_TEST + + START_TEST (getdns_list_get_length_2) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_list *list = NULL; + + LIST_CREATE(list); + + ASSERT_RC(getdns_list_get_length(list, NULL), + GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_length()"); + + } + END_TEST + + START_TEST (getdns_list_get_length_3) + { + /* + * Create a list, add 3 ints to it, get the length. + * expect: GETDNS_RETURN_GOOD + * length = 3 + */ + struct getdns_list *list = NULL; + size_t i; + size_t length; + + LIST_CREATE(list); + + for(i = 0; i < 3; i++) + { + ASSERT_RC(getdns_list_set_int(list, i, i), GETDNS_RETURN_GOOD, + "Return code from getdns_list_set_int()"); + } + + ASSERT_RC(getdns_list_get_length(list, &length), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); + + ck_assert_msg(length == 3, "Expected length == 3, got %d", length); + + } + END_TEST + + START_TEST (getdns_list_get_length_4) + { + /* + * Create a list (empty) and get the length + * expect: GETDNS_RETURN_GOOD + * length = 3 + */ + struct getdns_list *list = NULL; + size_t length; + + LIST_CREATE(list); + + ASSERT_RC(getdns_list_get_length(list, &length), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); + + ck_assert_msg(length == 0, "Expected length == 3, got %d", length); + + } + END_TEST + + Suite * + getdns_list_get_length_suite (void) + { + Suite *s = suite_create ("getdns_list_get_length()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_list_get_length_1); + tcase_add_test(tc_neg, getdns_list_get_length_2); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_list_get_length_3); + tcase_add_test(tc_pos, getdns_list_get_length_4); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From c1f7ced032c805b01766ecb9c0d0d425b8e92d9d Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 20 Dec 2013 14:08:19 -0500 Subject: [PATCH 09/35] Implemented most of Neel's review feedback. --- src/test/check_getdns_address_sync.h | 53 ++++++++++++---- src/test/check_getdns_common.c | 10 +++ src/test/check_getdns_common.h | 74 +++++++++++++++++++++- src/test/check_getdns_general.h | 47 ++++++++++---- src/test/check_getdns_general_sync.h | 62 ++++++++++++++---- src/test/check_getdns_list_get_data_type.h | 19 ++++++ src/test/check_getdns_list_get_length.h | 13 +++- 7 files changed, 235 insertions(+), 43 deletions(-) diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h index b5170c91..46e053dc 100644 --- a/src/test/check_getdns_address_sync.h +++ b/src/test/check_getdns_address_sync.h @@ -1,6 +1,13 @@ - #ifndef _check_getdns_address_h_ #define _check_getdns_address_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ A D D R E S S _ S Y N C * + * * + ************************************************************************** + */ START_TEST (getdns_address_sync_1) { @@ -25,10 +32,12 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -42,10 +51,12 @@ struct getdns_dict *response = NULL; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, name, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -59,10 +70,12 @@ struct getdns_dict *response = NULL; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, name, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -74,10 +87,12 @@ */ struct getdns_context *context = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -94,7 +109,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -102,6 +117,8 @@ EXTRACT_RESPONSE; assert_noerror(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -119,7 +136,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "localhost", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -127,6 +144,8 @@ EXTRACT_RESPONSE; assert_noerror(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -145,7 +164,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "google.joe", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -155,6 +174,8 @@ assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -170,7 +191,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "hampster.com", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -178,6 +199,8 @@ EXTRACT_RESPONSE; assert_noerror(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -193,7 +216,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "google.com", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -202,6 +225,8 @@ assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); + + CONTEXT_DESTROY; } END_TEST @@ -218,7 +243,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "75.101.146.66", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -228,6 +253,8 @@ assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -244,7 +271,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "2607:f8b0:4006:802::1007", NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_address_sync()"); @@ -254,6 +281,8 @@ assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); + + CONTEXT_DESTROY; } END_TEST diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index 9ba6e7c4..23cfc5e7 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -222,6 +222,11 @@ void assert_ptr_in_answer(struct extracted_response *ex_response) ck_assert_msg(ptr_records == 1, "Expected to find one PTR record in answer section, got %d", ptr_records); } +/* + * negative_callbackfn is the callback function given + * to negative asynchronous query tests when no response + * is expected. + */ void negative_callbackfn(struct getdns_context *context, uint16_t callback_type, struct getdns_dict *response, @@ -231,6 +236,11 @@ void negative_callbackfn(struct getdns_context *context, ck_abort_msg("Callback should never occur for negative test cases"); } +/* + * positive_callbackfn is the callback function given + * to positive asynchronous query tests and will validate + * the response that is returned. + */ void positive_callbackfn(struct getdns_context *context, uint16_t callback_type, struct getdns_dict *response, diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index d6c8f354..061f41ab 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -42,11 +42,17 @@ * create a context and assert the proper * return code is returned. */ - #define CONTEXT_CREATE \ - ASSERT_RC(getdns_context_create(&context, TRUE), \ + #define CONTEXT_CREATE(set_from_os) \ + ASSERT_RC(getdns_context_create(&context, set_from_os), \ GETDNS_RETURN_GOOD, \ "Return code from getdns_context_create()"); + /* + * The CONTEXT_FREE macro is used to + * destroy the current context. + */ + #define CONTEXT_DESTROY getdns_context_destroy(context); + /* * The EVENT_BASE_CREATE macro is used to * create an event base and put it in the @@ -74,6 +80,11 @@ ck_assert_msg(list != NULL, \ "NULL pointer returned by getdns_list_create()"); + /* + * The LIST_DESTROY macro destroys a list. + */ + #define LIST_DESTROY(list) getdns_list_destroy(list); + /* * The DICT_CREATE macro simply creates a * dict and verifies the returned pointer @@ -83,6 +94,11 @@ dict = getdns_dict_create(); \ ck_assert_msg(dict != NULL, \ "NULL pointer returned by getdns_dict_create()"); + + /* + * The DICT_DESTROY macro destroys a dict. + */ + #define DICT_DESTROY(dict) getdns_dict_destroy(dict); /* * The process_response macro declares the @@ -92,14 +108,60 @@ #define EXTRACT_RESPONSE \ struct extracted_response ex_response; \ extract_response(response, &ex_response); - + + // + // FUNCTION DECLARATIONS + // + + /* + * extract_response extracts all of the various information + * a test may want to look at from the response. + */ void extract_response(struct getdns_dict *response, struct extracted_response *ex_response); + + /* + * assert_noerror asserts that the rcode is 0. + */ void assert_noerror(struct extracted_response *ex_response); + + /* + * assert_nodata asserts that ancount in the header and the + * of the answer section (list) are both zero. + */ void assert_nodata(struct extracted_response *ex_response); + + /* + * assert_address_records_in_answer asserts that ancount in + * the header * is >= 1, ancount is equal to the length + * of "answer", and that all of * the records in the + * answer section are A and/or AAAA resource records based + * on the value of the a/aaaa arguments. + */ void assert_address_in_answer(struct extracted_response *ex_response, int a, int aaaa); + + /* + * assert_nxdomain asserts that an NXDOMAIN response was + * was returned for the DNS query meaning rcode == 3. + */ void assert_nxdomain(struct extracted_response *ex_response); + + /* + * assert_soa_in_authority asserts that a SOA record was + * returned in the authority sections. + */ void assert_soa_in_authority(struct extracted_response *ex_response); + + /* + * assert_ptr_in_answer asserts that a PTR record was + * returned in the answer sections. + */ void assert_ptr_in_answer(struct extracted_response *ex_response); + + /* + * negative_callbackfn is the callback function given + * to negative asynchronous query tests when no response + * is expected. + */ void negative_callbackfn( struct getdns_context *context, uint16_t callback_type, @@ -107,6 +169,12 @@ void *userarg, getdns_transaction_t transaction_id ); + + /* + * positive_callbackfn is the callback function given + * to positive asynchronous query tests and will validate + * the response that is returned. + */ void positive_callbackfn( struct getdns_context *context, uint16_t callback_type, diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index 90d86602..a1f32b42 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -1,5 +1,13 @@ #ifndef _check_getdns_general_h_ #define _check_getdns_general_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ G E M E R A L * + * * + ************************************************************************** + */ START_TEST (getdns_general_1) { @@ -26,7 +34,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, @@ -34,6 +42,7 @@ GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -48,7 +57,7 @@ getdns_transaction_t transaction_id = 0; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, @@ -56,6 +65,7 @@ GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -70,7 +80,7 @@ getdns_transaction_t transaction_id = 0; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, @@ -78,6 +88,7 @@ GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -91,7 +102,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, @@ -99,6 +110,7 @@ GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -116,7 +128,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", 0, NULL, @@ -124,6 +136,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -141,7 +154,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, @@ -149,6 +162,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -167,7 +181,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, @@ -175,6 +189,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -193,7 +208,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, @@ -201,6 +216,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -221,7 +237,7 @@ getdns_transaction_t transaction_id = 0; const char *name = "thisdomainsurelydoesntexist.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, @@ -229,6 +245,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -246,7 +263,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, @@ -254,6 +271,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -272,7 +290,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, @@ -280,6 +298,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -298,7 +317,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, @@ -306,6 +325,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST @@ -324,7 +344,7 @@ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, @@ -332,6 +352,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; + CONTEXT_DESTROY; } END_TEST diff --git a/src/test/check_getdns_general_sync.h b/src/test/check_getdns_general_sync.h index 6df9b7bc..21d98988 100644 --- a/src/test/check_getdns_general_sync.h +++ b/src/test/check_getdns_general_sync.h @@ -1,6 +1,14 @@ #ifndef _check_getdns_general_sync_h_ #define _check_getdns_general_sync_h_ + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ G E N E R A L _ S Y N C * + * * + ************************************************************************** + */ + START_TEST (getdns_general_sync_1) { /* @@ -24,10 +32,12 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -41,10 +51,12 @@ struct getdns_dict *response = NULL; const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -58,10 +70,12 @@ struct getdns_dict *response = NULL; const char *name = "this.domain.hasalabelwhichexceedsthemaximumdnslabelsizeofsixtythreecharacters.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -73,10 +87,12 @@ */ struct getdns_context *context = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); + + CONTEXT_DESTROY; } END_TEST @@ -93,7 +109,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", 0, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -102,6 +118,8 @@ assert_noerror(&ex_response); assert_nodata(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -118,7 +136,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", 65279, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -127,6 +145,8 @@ assert_noerror(&ex_response); assert_nodata(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -144,7 +164,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -153,6 +173,8 @@ assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); + + CONTEXT_DESTROY; } END_TEST @@ -170,7 +192,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -179,6 +201,8 @@ assert_noerror(&ex_response); assert_address_in_answer(&ex_response, FALSE, TRUE); + + CONTEXT_DESTROY; } END_TEST @@ -198,7 +222,7 @@ struct getdns_dict *response = NULL; const char *name = "thisdomainsurelydoesntexist.com"; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, name, GETDNS_RRTYPE_TXT, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -208,6 +232,8 @@ assert_nxdomain(&ex_response); assert_nodata(&ex_response); assert_soa_in_authority(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -224,7 +250,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -233,6 +259,8 @@ assert_noerror(&ex_response); assert_nodata(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -250,7 +278,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -259,6 +287,8 @@ assert_noerror(&ex_response); assert_address_in_answer(&ex_response, TRUE, FALSE); + + CONTEXT_DESTROY; } END_TEST @@ -276,7 +306,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -285,6 +315,8 @@ assert_noerror(&ex_response); assert_ptr_in_answer(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -302,7 +334,7 @@ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; - CONTEXT_CREATE; + CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); @@ -311,6 +343,8 @@ assert_noerror(&ex_response); assert_ptr_in_answer(&ex_response); + + CONTEXT_DESTROY; } END_TEST @@ -328,8 +362,8 @@ tcase_add_test(tc_neg, getdns_general_sync_5); suite_add_tcase(s, tc_neg); /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); - tcase_add_test(tc_pos, getdns_general_sync_6); tcase_add_test(tc_pos, getdns_general_sync_7); tcase_add_test(tc_pos, getdns_general_sync_8); diff --git a/src/test/check_getdns_list_get_data_type.h b/src/test/check_getdns_list_get_data_type.h index 7c8c378a..d92d7162 100644 --- a/src/test/check_getdns_list_get_data_type.h +++ b/src/test/check_getdns_list_get_data_type.h @@ -1,6 +1,14 @@ #ifndef _check_getdns_list_get_data_type_h_ #define _check_getdns_list_get_data_type_h_ + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ L I S T _ G E T _ D A T A _ T Y P E * + * * + ************************************************************************** + */ + START_TEST (getdns_list_get_data_type_1) { /* @@ -28,6 +36,8 @@ size_t index = 0; getdns_data_type answer; + LIST_CREATE(list); + ASSERT_RC(getdns_list_set_int(list, index, 1), GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); @@ -35,6 +45,7 @@ ASSERT_RC(getdns_list_get_data_type(list, index, &answer), GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_data_type()"); + LIST_DESTROY(list); } END_TEST @@ -55,6 +66,7 @@ ASSERT_RC(getdns_list_get_data_type(list, index, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_list_get_data_type()"); + LIST_DESTROY(list); } END_TEST @@ -74,6 +86,7 @@ ASSERT_RC(getdns_list_get_data_type(list, index, &answer), GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_data_type()"); + LIST_DESTROY(list); } END_TEST @@ -103,6 +116,8 @@ ck_assert_msg(answer == t_dict, "Wrong data type, expected t_dict: %d, got %d", t_dict, answer); + LIST_DESTROY(list); + DICT_DESTROY(dict); } END_TEST @@ -132,6 +147,8 @@ ck_assert_msg(answer == t_list, "Wrong data type, expected t_list: %d, got %d", t_list, answer); + LIST_DESTROY(list1); + LIST_DESTROY(list2); } END_TEST @@ -160,6 +177,7 @@ ck_assert_msg(answer == t_bindata, "Wrong data type, expected t_bindata: %d, got %d", t_bindata, answer); + LIST_DESTROY(list); } END_TEST @@ -186,6 +204,7 @@ ck_assert_msg(answer == t_int, "Wrong data type, expected t_int: %d, got %d", t_int, answer); + LIST_DESTROY(list); } END_TEST diff --git a/src/test/check_getdns_list_get_length.h b/src/test/check_getdns_list_get_length.h index 46657f04..f43b980c 100644 --- a/src/test/check_getdns_list_get_length.h +++ b/src/test/check_getdns_list_get_length.h @@ -1,6 +1,14 @@ #ifndef _check_getdns_list_get_length_h_ #define _check_getdns_list_get_length_h_ + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ L I S T _ G E T _ L E N G T H * + * * + ************************************************************************** + */ + START_TEST (getdns_list_get_length_1) { /* @@ -29,6 +37,7 @@ ASSERT_RC(getdns_list_get_length(list, NULL), GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_length()"); + LIST_DESTROY(list); } END_TEST @@ -56,6 +65,7 @@ ck_assert_msg(length == 3, "Expected length == 3, got %d", length); + LIST_DESTROY(list); } END_TEST @@ -75,7 +85,8 @@ GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); ck_assert_msg(length == 0, "Expected length == 3, got %d", length); - + + LIST_DESTROY(list); } END_TEST From c18d406389e7aa281b929df6f98a5f08947db9c3 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 20 Dec 2013 16:47:59 -0500 Subject: [PATCH 10/35] Implemented the rest of Neel's review feedback. --- src/test/check_getdns_common.c | 88 +++++++++++-------------------- src/test/check_getdns_common.h | 24 +++------ src/test/check_getdns_general.h | 92 ++++++++++++++++++++++++++++----- 3 files changed, 115 insertions(+), 89 deletions(-) diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index 23cfc5e7..17e2392e 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -223,66 +223,40 @@ void assert_ptr_in_answer(struct extracted_response *ex_response) } /* - * negative_callbackfn is the callback function given - * to negative asynchronous query tests when no response - * is expected. + * callbackfn is the callback function given to all + * asynchronous query tests. It is expected to only + * be called for positive tests and will verify the + * response that is returned. */ -void negative_callbackfn(struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id) -{ - ck_abort_msg("Callback should never occur for negative test cases"); -} - -/* - * positive_callbackfn is the callback function given - * to positive asynchronous query tests and will validate - * the response that is returned. - */ -void positive_callbackfn(struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id) +void callbackfn(struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *(userarg)(struct extracted_response *ex_response), + getdns_transaction_t transaction_id) { + /* + * If userarg is NULL, either a negative test case + * erroneously reached the query state, or the value + * in userarg (verification function) was somehow + * lost in transit. + */ + ck_assert_msg(userarg != NULL, "Callback called with NULL userarg"); + + /* + * We expect the callback type to be COMPLETE. + */ ASSERT_RC(callback_type, GETDNS_CALLBACK_COMPLETE, "Callback type"); + + /* + * Extract the response. + */ EXTRACT_RESPONSE; - - if(strcmp(userarg, "getdns_general_6") == 0 || - strcmp(userarg, "getdns_general_7") == 0 || - strcmp(userarg, "getdns_general_11") == 0) - { - assert_noerror(&ex_response); - assert_nodata(&ex_response); - } - else if(strcmp(userarg, "getdns_general_8") == 0 || - strcmp(userarg, "getdns_general_12") == 0) - { - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, TRUE, FALSE); - } - else if(strcmp(userarg, "getdns_general_9") == 0) - { - assert_noerror(&ex_response); - assert_address_in_answer(&ex_response, FALSE, TRUE); - } - else if(strcmp(userarg, "getdns_general_10") == 0) - { - assert_nxdomain(&ex_response); - assert_nodata(&ex_response); - assert_soa_in_authority(&ex_response); - } - else if(strcmp(userarg, "getdns_general_13") == 0 || - strcmp(userarg, "getdns_general_14") == 0) - { - assert_noerror(&ex_response); - assert_ptr_in_answer(&ex_response); - } - else - { - ck_abort_msg("Unexpected value in userarg: %s", userarg); - } + + /* + * Call the response verification function that + * was passed via userarg. + */ + userarg(&ex_response); + } diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index 061f41ab..5ff3d866 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -158,28 +158,16 @@ void assert_ptr_in_answer(struct extracted_response *ex_response); /* - * negative_callbackfn is the callback function given - * to negative asynchronous query tests when no response - * is expected. + * callbackfn is the callback function given to all + * asynchronous query tests. It is expected to only + * be called for positive tests and will verify the + * response that is returned. */ - void negative_callbackfn( - struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *userarg, - getdns_transaction_t transaction_id - ); - - /* - * positive_callbackfn is the callback function given - * to positive asynchronous query tests and will validate - * the response that is returned. - */ - void positive_callbackfn( + void callbackfn( struct getdns_context *context, uint16_t callback_type, struct getdns_dict *response, - void *userarg, + void *(userarg)(struct extracted_response *ex_response), getdns_transaction_t transaction_id ); diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index a1f32b42..5ccd7fd7 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -19,7 +19,7 @@ getdns_transaction_t transaction_id = 0; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_1", &transaction_id, negative_callbackfn), + NULL, &transaction_id, callbackfn), GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_general()"); } END_TEST @@ -38,7 +38,7 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, - "getdns_general_2", &transaction_id, negative_callbackfn), + NULL, &transaction_id, callbackfn), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); RUN_EVENT_LOOP; @@ -61,7 +61,7 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, - "getdns_general_3", &transaction_id, negative_callbackfn), + NULL, &transaction_id, callbackfn), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); RUN_EVENT_LOOP; @@ -84,7 +84,7 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_A, NULL, - "getdns_general_4", &transaction_id, negative_callbackfn), + NULL, &transaction_id, callbackfn), GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_general()"); RUN_EVENT_LOOP; @@ -106,7 +106,7 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_5", &transaction_id, NULL), + NULL, &transaction_id, NULL), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); RUN_EVENT_LOOP; @@ -124,6 +124,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ + void verify_getdns_general_6(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -132,13 +133,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", 0, NULL, - "getdns_general_6", &transaction_id, positive_callbackfn), + verify_getdns_general_6, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_6(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_nodata(ex_response); + } START_TEST (getdns_general_7) { @@ -150,6 +157,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ + void verify_getdns_general_7(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -158,13 +166,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", 65279, NULL, - "getdns_general_7", &transaction_id, positive_callbackfn), + verify_getdns_general_7, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_7(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_nodata(ex_response); + } START_TEST (getdns_general_8) { @@ -177,6 +191,7 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ + void verify_getdns_general_8(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -185,13 +200,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_8", &transaction_id, positive_callbackfn), + verify_getdns_general_8, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_8(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_address_in_answer(ex_response, TRUE, FALSE); + } START_TEST (getdns_general_9) { @@ -204,6 +225,7 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of AAAA records ("type": 28) in "answer" list */ + void verify_getdns_general_9(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -212,13 +234,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_AAAA, NULL, - "getdns_general_9", &transaction_id, positive_callbackfn), + verify_getdns_general_9, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_9(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_address_in_answer(ex_response, FALSE, TRUE); + } START_TEST (getdns_general_10) { @@ -232,6 +260,7 @@ * nscount = 1 (number of records in AUTHORITY section) * and SOA record ("type": 6) present in "authority" list */ + void verify_getdns_general_10(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -241,13 +270,20 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, name, GETDNS_RRTYPE_TXT, NULL, - "getdns_general_10", &transaction_id, positive_callbackfn), + verify_getdns_general_10, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_10(struct extracted_response *ex_response) + { + assert_nxdomain(ex_response); + assert_nodata(ex_response); + assert_soa_in_authority(ex_response); + } START_TEST (getdns_general_11) { @@ -259,6 +295,7 @@ * rcode = 0 * ancount = 0 (number of records in ANSWER section) */ + void verify_getdns_general_11(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -267,13 +304,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "hampster.com", GETDNS_RRTYPE_MX, NULL, - "getdns_general_11", &transaction_id, positive_callbackfn), + verify_getdns_general_11, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_11(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_nodata(ex_response); + } START_TEST (getdns_general_12) { @@ -286,6 +329,7 @@ * ancount >= 1 (number of records in ANSWER section) * and equals number of A records ("type": 1) in "answer" list */ + void verify_getdns_general_12(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -294,13 +338,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, - "getdns_general_12", &transaction_id, positive_callbackfn), + verify_getdns_general_12, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_12(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_address_in_answer(ex_response, TRUE, FALSE); + } START_TEST (getdns_general_13) { @@ -313,6 +363,7 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ + void verify_getdns_general_13(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -321,13 +372,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "75.101.146.66", GETDNS_RRTYPE_PTR, NULL, - "getdns_general_13", &transaction_id, positive_callbackfn), + verify_getdns_general_13, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_13(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_ptr_in_answer(ex_response); + } START_TEST (getdns_general_14) { @@ -340,6 +397,7 @@ * ancount == 1 (number of records in ANSWER section) * and PTR record found ("type": 12) in "answer" list */ + void verify_getdns_general_14(struct extracted_response *ex_response); struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ getdns_transaction_t transaction_id = 0; @@ -348,13 +406,19 @@ EVENT_BASE_CREATE; ASSERT_RC(getdns_general(context, "2607:f8b0:4006:802::1007", GETDNS_RRTYPE_PTR, NULL, - "getdns_general_14", &transaction_id, positive_callbackfn), + verify_getdns_general_14, &transaction_id, callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; } END_TEST + + void verify_getdns_general_14(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_ptr_in_answer(ex_response); + } Suite * getdns_general_suite (void) From 6ae6ce3bbb45ca7c76d7e22cb821b0d4efb34dba Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Thu, 2 Jan 2014 13:45:48 -0500 Subject: [PATCH 11/35] GIT should ignore check_getdns --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dad7cf06..21672842 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,6 @@ tests_dict tests_list tests_stub_async tests_stub_sync - src/example/example-reverse src/test/check_getdns.log +check_getdns From c8a7180a3adc62d6bf12e86316b7fceeca62e205 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Thu, 2 Jan 2014 13:46:23 -0500 Subject: [PATCH 12/35] Added tests for context create and destroy --- src/test/check_getdns.c | 11 +- src/test/check_getdns_common.c | 12 +- src/test/check_getdns_common.h | 14 +- src/test/check_getdns_context_create.h | 73 ++++++++++ src/test/check_getdns_context_destroy.h | 181 ++++++++++++++++++++++++ 5 files changed, 280 insertions(+), 11 deletions(-) create mode 100644 src/test/check_getdns_context_create.h create mode 100644 src/test/check_getdns_context_destroy.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 62c0b20a..cc3787b3 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -3,12 +3,15 @@ #include #include #include +#include #include #include #include "check_getdns_libevent.h" #include "check_getdns_common.h" #include "check_getdns_general.h" #include "check_getdns_general_sync.h" +#include "check_getdns_context_create.h" +#include "check_getdns_context_destroy.h" #include "check_getdns_address_sync.h" #include "check_getdns_list_get_length.h" #include "check_getdns_list_get_data_type.h" @@ -19,15 +22,19 @@ main (void) int number_failed; SRunner *sr ; - Suite *getdns_address_sync_suite(void); - Suite *getdns_general_sync_suite(void); Suite *getdns_general_suite(void); + Suite *getdns_general_sync_suite(void); + Suite *getdns_address_sync_suite(void); + Suite *getdns_context_create_suite(void); + Suite *getdns_context_destroy_suite(void); Suite *getdns_list_get_length_suite(void); Suite *getdns_list_get_data_type_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); srunner_add_suite(sr, getdns_address_sync_suite()); + srunner_add_suite(sr, getdns_context_create_suite()); + srunner_add_suite(sr, getdns_context_destroy_suite()); srunner_add_suite(sr, getdns_list_get_length_suite()); srunner_add_suite(sr, getdns_list_get_data_type_suite()); diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index 17e2392e..5d1bcb87 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -7,6 +7,8 @@ #include #include "check_getdns_common.h" +int callback_called = 0; + /* * extract_response extracts all of the various information * a test may want to look at from the response. @@ -231,9 +233,11 @@ void assert_ptr_in_answer(struct extracted_response *ex_response) void callbackfn(struct getdns_context *context, uint16_t callback_type, struct getdns_dict *response, - void *(userarg)(struct extracted_response *ex_response), + void *userarg, getdns_transaction_t transaction_id) { + typedef void (*fn_ptr)(struct extracted_response *ex_response); + fn_ptr fn = userarg; /* * If userarg is NULL, either a negative test case @@ -248,6 +252,10 @@ void callbackfn(struct getdns_context *context, */ ASSERT_RC(callback_type, GETDNS_CALLBACK_COMPLETE, "Callback type"); + /* + printf("DICT:\n%s\n", getdns_pretty_print_dict(response)); + */ + /* * Extract the response. */ @@ -257,6 +265,6 @@ void callbackfn(struct getdns_context *context, * Call the response verification function that * was passed via userarg. */ - userarg(&ex_response); + fn(&ex_response); } diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index 5ff3d866..619082d8 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -4,6 +4,8 @@ #define TRUE 1 #define FALSE 0 #define MAXLEN 200 + + extern int callback_called; struct extracted_response { uint32_t top_answer_type; @@ -163,12 +165,10 @@ * be called for positive tests and will verify the * response that is returned. */ - void callbackfn( - struct getdns_context *context, - uint16_t callback_type, - struct getdns_dict *response, - void *(userarg)(struct extracted_response *ex_response), - getdns_transaction_t transaction_id - ); + void callbackfn(struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); #endif diff --git a/src/test/check_getdns_context_create.h b/src/test/check_getdns_context_create.h new file mode 100644 index 00000000..5f35d4fb --- /dev/null +++ b/src/test/check_getdns_context_create.h @@ -0,0 +1,73 @@ +#ifndef _check_getdns_context_create_h_ +#define _check_getdns_context_create_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ C O N T E X T _ C R E A T E * + * * + ************************************************************************** + */ + + START_TEST (getdns_context_create_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + + ASSERT_RC(getdns_context_create(NULL, TRUE), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_context_create()"); + } + END_TEST + + START_TEST (getdns_context_create_2) + { + /* + * set_from_os = TRUE + * expect: context initialized with operating system info + * GETDNS_RETURN_GOOD + */ + struct getdns_context *context = NULL; + + CONTEXT_CREATE(TRUE); + // TODO: Do something here to verify set_from_os = TRUE + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_context_create_3) + { + /* + * set_from_os = FALSE + * expect: context is not initialized with operating system info + * GETDNS_RETURN_GOOD + */ + struct getdns_context *context = NULL; + + CONTEXT_CREATE(FALSE); + // TODO: Do something here to verify set_from_os = TRUE + CONTEXT_DESTROY; + } + END_TEST + + Suite * + getdns_context_create_suite (void) + { + Suite *s = suite_create ("getdns_context_create()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_context_create_1); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_context_create_2); + tcase_add_test(tc_pos, getdns_context_create_3); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif diff --git a/src/test/check_getdns_context_destroy.h b/src/test/check_getdns_context_destroy.h new file mode 100644 index 00000000..fdb9b0e1 --- /dev/null +++ b/src/test/check_getdns_context_destroy.h @@ -0,0 +1,181 @@ +#ifndef _check_getdns_context_destroy_h_ +#define _check_getdns_context_destroy_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ C O N T E X T _ D E S T R O Y * + * * + ************************************************************************** + */ + + START_TEST (getdns_context_destroy_1) + { + /* + * context = NULL + * expect: nothing, no segmentation fault + */ + + getdns_context_destroy(NULL); + } + END_TEST + + START_TEST (getdns_context_destroy_2) + { + /* + * destroy called with valid context and no outstanding transactions + * expect: nothing, context is freed + */ + struct getdns_context *context = NULL; + + CONTEXT_CREATE(TRUE); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_context_destroy_3) + { + /* + * destroy called immediately following getdns_general + * expect: callback should be called before getdns_context_destroy() returns + */ + void verify_getdns_context_destroy(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + verify_getdns_context_destroy, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + + RUN_EVENT_LOOP; + CONTEXT_DESTROY; + + ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); + } + END_TEST + + START_TEST (getdns_context_destroy_4) + { + /* + * destroy called immediately following getdns_address + * expect: callback should be called before getdns_context_destroy() returns + */ + void verify_getdns_context_destroy(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_address(context, "8.8.8.8", NULL, + verify_getdns_context_destroy, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_address()"); + + RUN_EVENT_LOOP; + CONTEXT_DESTROY; + + ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); + } + END_TEST + + START_TEST (getdns_context_destroy_5) + { + /* + * destroy called immediately following getdns_address + * expect: callback should be called before getdns_context_destroy() returns + */ + void verify_getdns_context_destroy(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct getdns_dict *address = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata"); + + ASSERT_RC(getdns_hostname(context, address, NULL, + verify_getdns_context_destroy, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_address()"); + + RUN_EVENT_LOOP; + CONTEXT_DESTROY; + + ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); + } + END_TEST + + START_TEST (getdns_context_destroy_6) + { + /* + * destroy called immediately following getdns_address + * expect: callback should be called before getdns_context_destroy() returns + */ + void verify_getdns_context_destroy(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_service(context, "google.com", NULL, + verify_getdns_context_destroy, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_service()"); + + RUN_EVENT_LOOP; + CONTEXT_DESTROY; + + ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); + } + END_TEST + + void verify_getdns_context_destroy(struct extracted_response *ex_response) + { + /* + * Sleep for a second to make getdns_context_destroy() wait. + */ + sleep(1); + + /* + * callback_called is a global and we increment it + * here to show that the callback was called. + */ + callback_called++; + } + + Suite * + getdns_context_destroy_suite (void) + { + Suite *s = suite_create ("getdns_context_destroy()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_context_destroy_1); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_context_destroy_2); + tcase_add_test(tc_pos, getdns_context_destroy_3); + tcase_add_test(tc_pos, getdns_context_destroy_4); + tcase_add_test(tc_pos, getdns_context_destroy_5); + tcase_add_test(tc_pos, getdns_context_destroy_6); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From c736df8a896d6028aff5495a7c4217449b5e268c Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Mon, 6 Jan 2014 12:59:43 -0500 Subject: [PATCH 13/35] Added globals to support getdns_cancel_callback() tests. Fixed macro evaluation problem in ASSERT_RC. --- src/test/check_getdns_common.c | 2 ++ src/test/check_getdns_common.h | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index 5d1bcb87..5e5e6281 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -8,6 +8,8 @@ #include "check_getdns_common.h" int callback_called = 0; +int callback_completed = 0; +int callback_canceled = 0; /* * extract_response extracts all of the various information diff --git a/src/test/check_getdns_common.h b/src/test/check_getdns_common.h index 619082d8..5b64d223 100644 --- a/src/test/check_getdns_common.h +++ b/src/test/check_getdns_common.h @@ -6,6 +6,8 @@ #define MAXLEN 200 extern int callback_called; + extern int callback_completed; + extern int callback_canceled; struct extracted_response { uint32_t top_answer_type; @@ -29,14 +31,15 @@ * whether the return code from the last * getdns API call is what was expected. */ - #define ASSERT_RC(rc, expected_rc, prefix) \ - { \ - size_t buflen = MAXLEN; \ - char error_string[MAXLEN]; \ - getdns_strerror(rc, error_string, buflen); \ - ck_assert_msg(rc == expected_rc, \ - "%s: expecting %s: %d, but received: %d: %s", \ - prefix, #expected_rc, expected_rc, rc, error_string); \ + #define ASSERT_RC(rc, expected_rc, prefix) \ + { \ + size_t buflen = MAXLEN; \ + char error_string[MAXLEN]; \ + getdns_return_t evaluated_rc = rc; \ + getdns_strerror(evaluated_rc, error_string, buflen); \ + ck_assert_msg(evaluated_rc == expected_rc, \ + "%s: expecting %s: %d, but received: %d: %s", \ + prefix, #expected_rc, expected_rc, evaluated_rc, error_string); \ } /* From db507121cf58c4dee917378e94d6aa90ea537cf2 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Mon, 6 Jan 2014 14:31:01 -0500 Subject: [PATCH 14/35] Added tests for getdns_cancel_callback(). --- src/test/check_getdns.c | 3 + src/test/check_getdns_cancel_callback.h | 455 ++++++++++++++++++++++++ 2 files changed, 458 insertions(+) create mode 100644 src/test/check_getdns_cancel_callback.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index cc3787b3..6798bbfc 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -12,6 +12,7 @@ #include "check_getdns_general_sync.h" #include "check_getdns_context_create.h" #include "check_getdns_context_destroy.h" +#include "check_getdns_cancel_callback.h" #include "check_getdns_address_sync.h" #include "check_getdns_list_get_length.h" #include "check_getdns_list_get_data_type.h" @@ -27,6 +28,7 @@ main (void) Suite *getdns_address_sync_suite(void); Suite *getdns_context_create_suite(void); Suite *getdns_context_destroy_suite(void); + Suite *getdns_cancel_callback_suite(void); Suite *getdns_list_get_length_suite(void); Suite *getdns_list_get_data_type_suite(void); @@ -35,6 +37,7 @@ main (void) srunner_add_suite(sr, getdns_address_sync_suite()); srunner_add_suite(sr, getdns_context_create_suite()); srunner_add_suite(sr, getdns_context_destroy_suite()); + srunner_add_suite(sr, getdns_cancel_callback_suite()); srunner_add_suite(sr, getdns_list_get_length_suite()); srunner_add_suite(sr, getdns_list_get_data_type_suite()); diff --git a/src/test/check_getdns_cancel_callback.h b/src/test/check_getdns_cancel_callback.h new file mode 100644 index 00000000..631096ea --- /dev/null +++ b/src/test/check_getdns_cancel_callback.h @@ -0,0 +1,455 @@ +#ifndef _check_getdns_cancel_callback_h_ +#define _check_getdns_cancel_callback_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ C A N C E L _ C A L L B A C K * + * * + ************************************************************************** + */ + + START_TEST (getdns_cancel_callback_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + getdns_transaction_t transaction_id = 0; + + ASSERT_RC(getdns_cancel_callback(NULL, transaction_id), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_cancel_callback()"); + } + END_TEST + + START_TEST (getdns_cancel_callback_2) + { + /* + * transaction_id corresponds to callback that has already been called + * expect: GETDNS_RETURN_UNKNOWN_TRANSACTION + */ + void verify_getdns_cancel_callback(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + verify_getdns_cancel_callback, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + + RUN_EVENT_LOOP; + + ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); + + ASSERT_RC(getdns_cancel_callback(context, transaction_id), + GETDNS_RETURN_UNKNOWN_TRANSACTION, "Return code from getdns_cancel_callback()"); + + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_cancel_callback_3) + { + /* + * transaction_id is unknown + * expect: GETDNS_RETURN_UNKNOWN_TRANSACTION + */ + void verify_getdns_cancel_callback(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + verify_getdns_cancel_callback, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + + RUN_EVENT_LOOP; + + ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); + + transaction_id++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id), + GETDNS_RETURN_UNKNOWN_TRANSACTION, "Return code from getdns_cancel_callback()"); + + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_cancel_callback_4) + { + /* + * getdns_cancel_callback() called with transaction_id returned from getdns_general() + * + * if transaction_id is odd, callback is canceled before event loop + * expect: GETDNS_RETURN_GOOD + * if transaction_id is even, callback is canceled after event loop + * expect: GETDNS_RETURN_UNKNOWN_TRANSACTION + * + * expect: callback to be called with GETDNS_CALLBACK_CANCELED (if canceled) + * or GETDNS_CALLBACK_COMPLETE (if not canceled). + */ + void cancel_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + getdns_transaction_t transaction_id_array[10] = {}; + int i; + int odd = 0; + int even = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + for(i = 0; i < 10; i++) + { + ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, + NULL, &transaction_id, cancel_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_general()"); + + transaction_id_array[i] = transaction_id; + + /* + * Cancel callback if transaction_id is odd which should be accepted + */ + if(transaction_id % 2) + { + odd++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id), + GETDNS_RETURN_GOOD, "Return code from getdns_cancel_callback()"); + } + } + + RUN_EVENT_LOOP; + + /* + * Cancel the callback for even transaction_ids which should be complete + */ + for(i = 0; i < 10; i++) + { + if((transaction_id_array[i] % 2) == 0) + { + even++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id_array[i]), + GETDNS_RETURN_UNKNOWN_TRANSACTION, "Return code from getdns_cancel_callback()"); + } + } + + ck_assert_msg(callback_called == 10, "callback_called should == 10, got: %d", callback_called); + ck_assert_msg(callback_completed == even, "callback_completed should == %d, got: %d", even, callback_completed); + ck_assert_msg(callback_canceled == odd, "callback_canceled should == %d, got: %d", odd, callback_canceled); + + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_cancel_callback_5) + { + /* + * getdns_cancel_callback() called with transaction_id returned from getdns_address() + * + * if transaction_id is odd, callback is canceled before event loop + * expect: GETDNS_RETURN_GOOD + * if transaction_id is even, callback is canceled after event loop + * expect: GETDNS_RETURN_UNKNOWN_TRANSACTION + * + * expect: callback to be called with GETDNS_CALLBACK_CANCELED (if canceled) + * or GETDNS_CALLBACK_COMPLETE (if not canceled). + */ + void cancel_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + getdns_transaction_t transaction_id_array[10] = {}; + int i; + int odd = 0; + int even = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + for(i = 0; i < 10; i++) + { + ASSERT_RC(getdns_address(context, "8.8.8.8", NULL, + NULL, &transaction_id, cancel_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_address()"); + + transaction_id_array[i] = transaction_id; + + /* + * Cancel callback if transaction_id is odd which should be accepted + */ + if(transaction_id % 2) + { + odd++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id), + GETDNS_RETURN_GOOD, "Return code from getdns_cancel_callback()"); + } + } + + RUN_EVENT_LOOP; + + /* + * Cancel the callback for even transaction_ids which should be complete + */ + for(i = 0; i < 10; i++) + { + if((transaction_id_array[i] % 2) == 0) + { + even++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id_array[i]), + GETDNS_RETURN_UNKNOWN_TRANSACTION, "Return code from getdns_cancel_callback()"); + } + } + + ck_assert_msg(callback_called == 10, "callback_called should == 10, got: %d", callback_called); + ck_assert_msg(callback_completed == even, "callback_completed should == %d, got: %d", even, callback_completed); + ck_assert_msg(callback_canceled == odd, "callback_canceled should == %d, got: %d", odd, callback_canceled); + + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_cancel_callback_6) + { + /* + * getdns_cancel_callback() called with transaction_id returned from getdns_hostname() + * + * if transaction_id is odd, callback is canceled before event loop + * expect: GETDNS_RETURN_GOOD + * if transaction_id is even, callback is canceled after event loop + * expect: GETDNS_RETURN_UNKNOWN_TRANSACTION + * + * expect: callback to be called with GETDNS_CALLBACK_CANCELED (if canceled) + * or GETDNS_CALLBACK_COMPLETE (if not canceled). + */ + void cancel_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct getdns_dict *address = NULL; + getdns_transaction_t transaction_id = 0; + getdns_transaction_t transaction_id_array[10] = {}; + int i; + int odd = 0; + int even = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata"); + + for(i = 0; i < 10; i++) + { + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, cancel_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_address()"); + + transaction_id_array[i] = transaction_id; + + /* + * Cancel callback if transaction_id is odd which should be accepted + */ + if(transaction_id % 2) + { + odd++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id), + GETDNS_RETURN_GOOD, "Return code from getdns_cancel_callback()"); + } + } + + RUN_EVENT_LOOP; + + /* + * Cancel the callback for even transaction_ids which should be complete + */ + for(i = 0; i < 10; i++) + { + if((transaction_id_array[i] % 2) == 0) + { + even++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id_array[i]), + GETDNS_RETURN_UNKNOWN_TRANSACTION, "Return code from getdns_cancel_callback()"); + } + } + + ck_assert_msg(callback_called == 10, "callback_called should == 10, got: %d", callback_called); + ck_assert_msg(callback_completed == even, "callback_completed should == %d, got: %d", even, callback_completed); + ck_assert_msg(callback_canceled == odd, "callback_canceled should == %d, got: %d", odd, callback_canceled); + + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_cancel_callback_7) + { + /* + * getdns_cancel_callback() called with transaction_id returned from getdns_service() + * + * if transaction_id is odd, callback is canceled before event loop + * expect: GETDNS_RETURN_GOOD + * if transaction_id is even, callback is canceled after event loop + * expect: GETDNS_RETURN_UNKNOWN_TRANSACTION + * + * expect: callback to be called with GETDNS_CALLBACK_CANCELED (if canceled) + * or GETDNS_CALLBACK_COMPLETE (if not canceled). + */ + void cancel_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + getdns_transaction_t transaction_id_array[10] = {}; + int i; + int odd = 0; + int even = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + for(i = 0; i < 10; i++) + { + ASSERT_RC(getdns_service(context, "google.com", NULL, + NULL, &transaction_id, cancel_callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_service()"); + + transaction_id_array[i] = transaction_id; + + /* + * Cancel callback if transaction_id is odd which should be accepted + */ + if(transaction_id % 2) + { + odd++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id), + GETDNS_RETURN_GOOD, "Return code from getdns_cancel_callback()"); + } + } + + RUN_EVENT_LOOP; + + /* + * Cancel the callback for even transaction_ids which should be complete + */ + for(i = 0; i < 10; i++) + { + if((transaction_id_array[i] % 2) == 0) + { + even++; + ASSERT_RC(getdns_cancel_callback(context, transaction_id_array[i]), + GETDNS_RETURN_UNKNOWN_TRANSACTION, "Return code from getdns_cancel_callback()"); + } + } + + ck_assert_msg(callback_called == 10, "callback_called should == 10, got: %d", callback_called); + ck_assert_msg(callback_completed == even, "callback_completed should == %d, got: %d", even, callback_completed); + ck_assert_msg(callback_canceled == odd, "callback_canceled should == %d, got: %d", odd, callback_canceled); + + CONTEXT_DESTROY; + } + END_TEST + + /* + * Callback function for getdns_cancel_callback() tests + * + * callback_type should be GETDNS_CALLBACK_CANCEL for odd transaction_ids + * should be GETDNS_CALLBACK_COMPLETE for even transaction_ids + */ + void cancel_callbackfn( + struct getdns_context *context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id) + { + callback_called++; + + if(callback_type == GETDNS_CALLBACK_CANCEL) + { + callback_canceled++; + ck_assert_msg(transaction_id % 2, + "Only callbacks with odd transaction_ids were canceled, this one is even: %d", + transaction_id); + } + else if(callback_type == GETDNS_CALLBACK_COMPLETE) + { + callback_completed++; + ck_assert_msg((transaction_id % 2) == 0, + "One callbacks with even transaction_ids should complete, this one is odd: %d", + transaction_id); + } + else + { + if(transaction_id % 2) + ck_abort_msg("callback_type should == GETDNS_CALLBACK_CANCEL for odd transaction_id (%d), got: %d", + transaction_id, callback_type); + else + ck_abort_msg("callback_type should == GETDNS_CALLBACK_COMPLETE for even transaction_id (%d), got %d", + transaction_id, callback_type); + } + } + + /* + * Function passed via userarg to async functions for cancel callback tests + */ + void verify_getdns_cancel_callback(struct extracted_response *ex_response) + { + /* + * increment callback_called global to prove callback was called. + */ + callback_called++; + } + + Suite * + getdns_cancel_callback_suite (void) + { + Suite *s = suite_create ("getdns_cancel_callback()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_cancel_callback_1); + tcase_add_test(tc_neg, getdns_cancel_callback_2); + tcase_add_test(tc_neg, getdns_cancel_callback_3); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_cancel_callback_4); + tcase_add_test(tc_pos, getdns_cancel_callback_5); + tcase_add_test(tc_pos, getdns_cancel_callback_6); + tcase_add_test(tc_pos, getdns_cancel_callback_7); + + suite_add_tcase(s, tc_pos); + return s; + } + +#endif From 02ebe857735f051235997e87fd6c18621fb9e519 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Mon, 6 Jan 2014 15:51:11 -0500 Subject: [PATCH 15/35] Added tests for getdns_dict_get_names() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_get_names.h | 110 +++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/test/check_getdns_dict_get_names.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 6798bbfc..dd331dcc 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -16,6 +16,7 @@ #include "check_getdns_address_sync.h" #include "check_getdns_list_get_length.h" #include "check_getdns_list_get_data_type.h" +#include "check_getdns_dict_get_names.h" int main (void) @@ -31,6 +32,7 @@ main (void) Suite *getdns_cancel_callback_suite(void); Suite *getdns_list_get_length_suite(void); Suite *getdns_list_get_data_type_suite(void); + Suite *getdns_dict_get_names_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -40,6 +42,7 @@ main (void) srunner_add_suite(sr, getdns_cancel_callback_suite()); srunner_add_suite(sr, getdns_list_get_length_suite()); srunner_add_suite(sr, getdns_list_get_data_type_suite()); + srunner_add_suite(sr, getdns_dict_get_names_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_get_names.h b/src/test/check_getdns_dict_get_names.h new file mode 100644 index 00000000..364d1d1b --- /dev/null +++ b/src/test/check_getdns_dict_get_names.h @@ -0,0 +1,110 @@ +#ifndef _check_getdns_dict_get_names_h_ +#define _check_getdns_dict_get_names_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ G E T _ N A M E S * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_get_names_1) + { + /* + * this_dict = NULL + * expect = GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *answer = NULL; + + ASSERT_RC(getdns_dict_get_names(this_dict, &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + + } + END_TEST + + START_TEST (getdns_dict_get_names_2) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + */ + struct getdns_dict *this_dict = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_get_names(this_dict, NULL), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_names_3) + { + /* + * Create a dict with three keys ("ten" = 10, "eleven" = 11, "twelve" = 12) + * Call getdns_dict_get_names() + * Iterate through list and append names together in a single string + * expect: string == "teneleventwelve" + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *answer = NULL; + char *keys[3] = { "ten", "eleven", "twelve" }; + uint32_t values[3] = { 10, 11, 12 }; + int i; + size_t length; + struct getdns_bindata *key = NULL; + char string_buffer[20]; + + DICT_CREATE(this_dict); + + for(i = 0; i < 3; i++) + { + ASSERT_RC(getdns_dict_set_int(this_dict, keys[i], values[i]), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + } + + ASSERT_RC(getdns_dict_get_names(this_dict, &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_names()"); + + ASSERT_RC(getdns_list_get_length(answer, &length), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); + + ck_assert_msg(length == 3, "Expected length == 3, got %d", length); + + for(i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_bindata(answer, i, &key), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()"); + strcat(string_buffer, (char *)key->data); + } + + ck_assert_msg(strcmp(string_buffer, "elevententwelve") == 0, + "Expected concatenated names to be \"elevententwelve\", got \"%s\"", string_buffer); + + DICT_DESTROY(this_dict); + } + END_TEST + + Suite * + getdns_dict_get_names_suite (void) + { + Suite *s = suite_create ("getdns_dict_get_names()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_get_names_1); + tcase_add_test(tc_neg, getdns_dict_get_names_2); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_get_names_3); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 60d45dc5bccb83de753e914cc0b31ae644a1bda0 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Mon, 6 Jan 2014 17:05:11 -0500 Subject: [PATCH 16/35] Fixed a comment line --- src/test/check_getdns_dict_get_names.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/check_getdns_dict_get_names.h b/src/test/check_getdns_dict_get_names.h index 364d1d1b..f0f82443 100644 --- a/src/test/check_getdns_dict_get_names.h +++ b/src/test/check_getdns_dict_get_names.h @@ -28,7 +28,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME */ struct getdns_dict *this_dict = NULL; From 4fef4094a7d92615f9c040b36f0ff4a3fe69d9f7 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Mon, 6 Jan 2014 17:05:42 -0500 Subject: [PATCH 17/35] Added tests for getdns_dict_get_data_type() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_get_data_type.h | 231 +++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 src/test/check_getdns_dict_get_data_type.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index dd331dcc..65ff321d 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -17,6 +17,7 @@ #include "check_getdns_list_get_length.h" #include "check_getdns_list_get_data_type.h" #include "check_getdns_dict_get_names.h" +#include "check_getdns_dict_get_data_type.h" int main (void) @@ -33,6 +34,7 @@ main (void) Suite *getdns_list_get_length_suite(void); Suite *getdns_list_get_data_type_suite(void); Suite *getdns_dict_get_names_suite(void); + Suite *getdns_dict_get_data_type_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -43,6 +45,7 @@ main (void) srunner_add_suite(sr, getdns_list_get_length_suite()); srunner_add_suite(sr, getdns_list_get_data_type_suite()); srunner_add_suite(sr, getdns_dict_get_names_suite()); + srunner_add_suite(sr, getdns_dict_get_data_type_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_get_data_type.h b/src/test/check_getdns_dict_get_data_type.h new file mode 100644 index 00000000..0f42d84a --- /dev/null +++ b/src/test/check_getdns_dict_get_data_type.h @@ -0,0 +1,231 @@ +#ifndef _check_getdns_dict_get_data_type_h_ +#define _check_getdns_dict_get_data_type_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ G E T _ D A T A _ T Y P E * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_get_data_type_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + getdns_data_type answer; + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "key", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + + } + END_TEST + + START_TEST (getdns_dict_get_data_type_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + getdns_data_type answer; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_data_type(this_dict, NULL, &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + + DICT_DESTROY(this_dict); + + } + END_TEST + + START_TEST (getdns_dict_get_data_type_3) + { + /* + * name does not exist in dict + * Create a dict with three keys ("ten" = 10, "eleven" = 11, "twelve" = 12) + * Call getdns_dict_get_data_type() with name = "nine" + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + char *keys[3] = { "ten", "eleven", "twelve" }; + uint32_t values[3] = { 10, 11, 12 }; + int i; + getdns_data_type answer; + + DICT_CREATE(this_dict); + + for(i = 0; i < 3; i++) + { + ASSERT_RC(getdns_dict_set_int(this_dict, keys[i], values[i]), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + } + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "nine", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_data_type_4) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "ten", NULL), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_data_type_5) + { + /* + * data type is dict + * Create a dict + * Create a second dict and add it to the first as name = "dict" + * Call getdns_dict_get_data_type() for name = "dict" + * expect: GETDNS_RETURN_GOOD + * retrieved answer should = t_dict + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *second_dict = NULL; + getdns_data_type answer; + + DICT_CREATE(this_dict); + DICT_CREATE(second_dict); + ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "dict", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_data_type()"); + + ck_assert_msg(answer == t_dict, "Expected answer = t_dict (%d), got: %d", t_dict, answer); + + DICT_DESTROY(this_dict); + DICT_DESTROY(second_dict); + } + END_TEST + + START_TEST (getdns_dict_get_data_type_6) + { + /* + * data type is list + * Create a dict + * Create a list and add it to the dict as name = "list" + * Call getdns_dict_get_data_type() for name = "list" + * expect: GETDNS_RETURN_GOOD + * retrieved answer should = t_list + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + getdns_data_type answer; + + DICT_CREATE(this_dict); + LIST_CREATE(list); + ASSERT_RC(getdns_dict_set_list(this_dict, "list", list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "list", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_data_type()"); + + ck_assert_msg(answer == t_list, "Expected answer = t_list (%d), got: %d", t_list, answer); + + DICT_DESTROY(this_dict); + LIST_DESTROY(list); + } + END_TEST + + START_TEST (getdns_dict_get_data_type_7) + { + /* + * data type is bindata + * Create a dict + * Create some bindata and add it to the dict as name = "bindata" + * Call getdns_dict_get_data_type() for name = "bindata" + * expect: GETDNS_RETURN_GOOD + * retrieved answer should = t_bindata + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + getdns_data_type answer; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "bindata", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_data_type()"); + + ck_assert_msg(answer == t_bindata, "Expected answer = t_bindata (%d), got: %d", t_bindata, answer); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_data_type_8) + { + /* + * data type is int + * Create a dict + * Add an int to the dict as name = "int" + * Call getdns_dict_get_data_type() for name = "int" + * expect: GETDNS_RETURN_GOOD + * retrieved answer should = t_int + */ + struct getdns_dict *this_dict = NULL; + getdns_data_type answer; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_int(this_dict, "int", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_data_type(this_dict, "int", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_data_type()"); + + ck_assert_msg(answer == t_int, "Expected answer = t_int (%d), got: %d", t_int, answer); + + DICT_DESTROY(this_dict); + } + END_TEST + + Suite * + getdns_dict_get_data_type_suite (void) + { + Suite *s = suite_create ("getdns_dict_get_data_type()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_get_data_type_1); + tcase_add_test(tc_neg, getdns_dict_get_data_type_2); + tcase_add_test(tc_neg, getdns_dict_get_data_type_3); + tcase_add_test(tc_neg, getdns_dict_get_data_type_4); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_get_data_type_5); + tcase_add_test(tc_pos, getdns_dict_get_data_type_6); + tcase_add_test(tc_pos, getdns_dict_get_data_type_7); + tcase_add_test(tc_pos, getdns_dict_get_data_type_8); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From b1abc6e48cd777b6947b68e7887b22b8e16f90ba Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 7 Jan 2014 10:29:26 -0500 Subject: [PATCH 18/35] Added new tests for getdns_dict_get_dict() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_get_dict.h | 220 ++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 src/test/check_getdns_dict_get_dict.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 65ff321d..3d86d889 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -18,6 +18,7 @@ #include "check_getdns_list_get_data_type.h" #include "check_getdns_dict_get_names.h" #include "check_getdns_dict_get_data_type.h" +#include "check_getdns_dict_get_dict.h"; int main (void) @@ -35,6 +36,7 @@ main (void) Suite *getdns_list_get_data_type_suite(void); Suite *getdns_dict_get_names_suite(void); Suite *getdns_dict_get_data_type_suite(void); + Suite *getdns_dict_get_dict_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -46,6 +48,7 @@ main (void) srunner_add_suite(sr, getdns_list_get_data_type_suite()); srunner_add_suite(sr, getdns_dict_get_names_suite()); srunner_add_suite(sr, getdns_dict_get_data_type_suite()); + srunner_add_suite(sr, getdns_dict_get_dict_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_get_dict.h b/src/test/check_getdns_dict_get_dict.h new file mode 100644 index 00000000..fe9326c7 --- /dev/null +++ b/src/test/check_getdns_dict_get_dict.h @@ -0,0 +1,220 @@ +#ifndef _check_getdns_dict_get_dict_h_ +#define _check_getdns_dict_get_dict_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ G E T _ D I C T * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_get_dict_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *answer = NULL; + + ASSERT_RC(getdns_dict_get_dict(this_dict, "key", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + + } + END_TEST + + START_TEST (getdns_dict_get_dict_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *second_dict = NULL; + struct getdns_dict *answer = NULL; + + DICT_CREATE(this_dict); + DICT_CREATE(second_dict); + ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_dict(this_dict, NULL, &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + + DICT_DESTROY(this_dict); + DICT_DESTROY(second_dict); + } + END_TEST + + START_TEST (getdns_dict_get_dict_3) + { + /* + * name does not exist in dict + * Create a dict + * Create a second dict with three ints ("ten" = 10, "eleven" = 11, "twelve" = 12) + * Add the second dict to the first dict as name = "numbers" + * Call getdns_dict_get_dict() against the first dict with name = "letters" + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *second_dict = NULL; + char *keys[3] = { "ten", "eleven", "twelve" }; + uint32_t values[3] = { 10, 11, 12 }; + int i; + struct getdns_dict *answer = NULL; + + DICT_CREATE(this_dict); + DICT_CREATE(second_dict); + + for(i = 0; i < 3; i++) + { + ASSERT_RC(getdns_dict_set_int(second_dict, keys[i], values[i]), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + } + + ASSERT_RC(getdns_dict_set_dict(this_dict, "numbers", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_dict(this_dict, "letters", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); + + DICT_DESTROY(this_dict); + DICT_DESTROY(second_dict); + } + END_TEST + + START_TEST (getdns_dict_get_dict_4) + { + /* + * data type at name is not a dict + * Create a dict with one int (name = "ten", value = 10) + * Call getdns_dict_get_dict() with name = "ten" + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *answer = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_dict(this_dict, "ten", &answer), + GETDNS_RETURN_WRONG_TYPE_REQUESTED, "Return code from getdns_dict_get_dict()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_dict_5) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *second_dict = NULL; + + DICT_CREATE(this_dict); + DICT_CREATE(second_dict); + + ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_dict(this_dict, "dict", NULL), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); + + DICT_DESTROY(this_dict); + DICT_DESTROY(second_dict); + } + END_TEST + + START_TEST (getdns_dict_get_dict_6) + { + /* + * successful get dict + * Create a dict + * Create a second dict with three ints ("ten" = 10, "eleven" = 11, "twelve" = 12) + * Add the second dict to the first dict as name = "numbers" + * Call getdns_dict_get_dict() against the first dict for name = "numbers" + * Call getdns_dict_get_names() against the retrieved "numbers" dict to get a list of names + * Call getdns_list_get_length() against the returned list to set a loop counter + * Iterate through the names in the list and add the int value from each key to sum + * expect: sum == 33 + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *second_dict = NULL; + char *keys[3] = { "ten", "eleven", "twelve" }; + uint32_t values[3] = { 10, 11, 12 }; + size_t i; + uint32_t sum_of_values = 0; + struct getdns_dict *answer = NULL; + struct getdns_list *names = NULL; + size_t length; + struct getdns_bindata *bindata = NULL; + uint32_t value; + uint32_t sum = 0; + + DICT_CREATE(this_dict); + DICT_CREATE(second_dict); + + for(i = 0; i < 3; i++) + { + ASSERT_RC(getdns_dict_set_int(second_dict, keys[i], values[i]), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + sum_of_values += values[i]; + } + + ASSERT_RC(getdns_dict_set_dict(this_dict, "numbers", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_dict(this_dict, "numbers", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_dict()"); + + ASSERT_RC(getdns_dict_get_names(answer, &names), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_names()"); + + ASSERT_RC(getdns_list_get_length(names, &length), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_length()"); + + for(i = 0; i < length; i++) + { + ASSERT_RC(getdns_list_get_bindata(names, i, &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_bindata()"); + ASSERT_RC(getdns_dict_get_int(answer, (char *)bindata->data, &value), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_int()"); + sum += value; + } + + ck_assert_msg(sum == sum_of_values, "Sum of int values in dict should == %d, got: %d", + sum_of_values, sum); + + DICT_DESTROY(this_dict); + DICT_DESTROY(second_dict); + } + END_TEST + + Suite * + getdns_dict_get_dict_suite (void) + { + Suite *s = suite_create ("getdns_dict_get_data_type()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_get_dict_1); + tcase_add_test(tc_neg, getdns_dict_get_dict_2); + tcase_add_test(tc_neg, getdns_dict_get_dict_3); + tcase_add_test(tc_neg, getdns_dict_get_dict_4); + tcase_add_test(tc_neg, getdns_dict_get_dict_5); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_get_dict_6); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 0f93bed1de17647430e15a938f7b87f559884e5a Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 7 Jan 2014 10:32:48 -0500 Subject: [PATCH 19/35] Fixed suite name for getdns_dict_get_dict() tests --- src/test/check_getdns_dict_get_dict.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/check_getdns_dict_get_dict.h b/src/test/check_getdns_dict_get_dict.h index fe9326c7..3091ccd8 100644 --- a/src/test/check_getdns_dict_get_dict.h +++ b/src/test/check_getdns_dict_get_dict.h @@ -198,7 +198,7 @@ Suite * getdns_dict_get_dict_suite (void) { - Suite *s = suite_create ("getdns_dict_get_data_type()"); + Suite *s = suite_create ("getdns_dict_get_dict()"); /* Negative test caseis */ TCase *tc_neg = tcase_create("Negative"); From 4301bb17c40ccf6fb86871dd5ed73f8d655490d7 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 7 Jan 2014 10:36:51 -0500 Subject: [PATCH 20/35] Fix more sloppiness, wrong function names in error messages for getdns_dict_get_dict() tests --- src/test/check_getdns_dict_get_dict.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/check_getdns_dict_get_dict.h b/src/test/check_getdns_dict_get_dict.h index 3091ccd8..92ad6115 100644 --- a/src/test/check_getdns_dict_get_dict.h +++ b/src/test/check_getdns_dict_get_dict.h @@ -19,7 +19,7 @@ struct getdns_dict *answer = NULL; ASSERT_RC(getdns_dict_get_dict(this_dict, "key", &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); } END_TEST @@ -40,7 +40,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); ASSERT_RC(getdns_dict_get_dict(this_dict, NULL, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); DICT_DESTROY(this_dict); DICT_DESTROY(second_dict); From 9aef4f6e80c3b87259c15a11ba6cfd257a7a0b40 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 7 Jan 2014 12:50:44 -0500 Subject: [PATCH 21/35] Added tests for getdns_dict_get_list() --- src/test/check_getdns.c | 5 +- src/test/check_getdns_dict_get_list.h | 185 ++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 src/test/check_getdns_dict_get_list.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 3d86d889..00923caf 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -18,7 +18,8 @@ #include "check_getdns_list_get_data_type.h" #include "check_getdns_dict_get_names.h" #include "check_getdns_dict_get_data_type.h" -#include "check_getdns_dict_get_dict.h"; +#include "check_getdns_dict_get_dict.h" +#include "check_getdns_dict_get_list.h" int main (void) @@ -37,6 +38,7 @@ main (void) Suite *getdns_dict_get_names_suite(void); Suite *getdns_dict_get_data_type_suite(void); Suite *getdns_dict_get_dict_suite(void); + Suite *getdns_dict_get_list_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -49,6 +51,7 @@ main (void) srunner_add_suite(sr, getdns_dict_get_names_suite()); srunner_add_suite(sr, getdns_dict_get_data_type_suite()); srunner_add_suite(sr, getdns_dict_get_dict_suite()); + srunner_add_suite(sr, getdns_dict_get_list_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_get_list.h b/src/test/check_getdns_dict_get_list.h new file mode 100644 index 00000000..828866bb --- /dev/null +++ b/src/test/check_getdns_dict_get_list.h @@ -0,0 +1,185 @@ +#ifndef _check_getdns_dict_get_list_h_ +#define _check_getdns_dict_get_list_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ G E T _ L I S T * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_get_list_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *answer = NULL; + + ASSERT_RC(getdns_dict_get_list(this_dict, "key", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + + } + END_TEST + + START_TEST (getdns_dict_get_list_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + struct getdns_list *answer = NULL; + + DICT_CREATE(this_dict); + LIST_CREATE(list); + ASSERT_RC(getdns_dict_set_list(this_dict, "list", list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + ASSERT_RC(getdns_dict_get_list(this_dict, NULL, &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + + DICT_DESTROY(this_dict); + LIST_DESTROY(list); + } + END_TEST + + START_TEST (getdns_dict_get_list_3) + { + /* + * name does not exist in dict + * Create a dict with three ints ("ten" = 10, "eleven" = 11, "twelve" = 12) + * Call getdns_dict_get_list() against the first dict with name = "nine" + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + char *keys[3] = { "ten", "eleven", "twelve" }; + uint32_t values[3] = { 10, 11, 12 }; + int i; + struct getdns_list *answer = NULL; + + DICT_CREATE(this_dict); + + for(i = 0; i < 3; i++) + { + ASSERT_RC(getdns_dict_set_int(this_dict, keys[i], values[i]), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + } + + ASSERT_RC(getdns_dict_get_list(this_dict, "nine", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_list_4) + { + /* + * data type at name is not a list + * Create a dict with one int (name = "ten", value = 10) + * Call getdns_dict_get_list() with name = "ten" + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *answer = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_list(this_dict, "ten", &answer), + GETDNS_RETURN_WRONG_TYPE_REQUESTED, "Return code from getdns_dict_get_list()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_list_5) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + + DICT_CREATE(this_dict); + LIST_CREATE(list); + + ASSERT_RC(getdns_dict_set_list(this_dict, "list", list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + ASSERT_RC(getdns_dict_get_list(this_dict, "list", NULL), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + + DICT_DESTROY(this_dict); + LIST_DESTROY(list); + } + END_TEST + + START_TEST (getdns_dict_get_list_6) + { + /* + * successful get list + * Create a dict + * Create a list and set index 0 to an int with a value of 100 + * Add the list to the dict as name "list" + * Call getdns_dict_get_list() against the dict for name = "list" + * Call getdns_list_set_int() for index 0 + * expect: int retrieved = 100 + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + struct getdns_list *answer = NULL; + uint32_t value; + + DICT_CREATE(this_dict); + LIST_CREATE(list); + + ASSERT_RC(getdns_list_set_int(list, 0, 100), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + + ASSERT_RC(getdns_dict_set_list(this_dict, "list", list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + ASSERT_RC(getdns_dict_get_list(this_dict, "list", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_list()"); + + ASSERT_RC(getdns_list_get_int(answer, 0, &value), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_int()"); + + ck_assert_msg(value == 100, "Expected int retrieved == 100, got: %d", value); + + DICT_DESTROY(this_dict); + LIST_DESTROY(list); + } + END_TEST + + Suite * + getdns_dict_get_list_suite (void) + { + Suite *s = suite_create ("getdns_dict_get_list()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_get_list_1); + tcase_add_test(tc_neg, getdns_dict_get_list_2); + tcase_add_test(tc_neg, getdns_dict_get_list_3); + tcase_add_test(tc_neg, getdns_dict_get_list_4); + tcase_add_test(tc_neg, getdns_dict_get_list_5); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_get_list_6); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 7807d1ade06cdca55906b728b6d0ebc44af2aeb3 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 7 Jan 2014 13:44:39 -0500 Subject: [PATCH 22/35] Added tests for getdns_dict_get_bindata() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_get_bindata.h | 169 +++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 src/test/check_getdns_dict_get_bindata.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 00923caf..bc472ff3 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -20,6 +20,7 @@ #include "check_getdns_dict_get_data_type.h" #include "check_getdns_dict_get_dict.h" #include "check_getdns_dict_get_list.h" +#include "check_getdns_dict_get_bindata.h" int main (void) @@ -39,6 +40,7 @@ main (void) Suite *getdns_dict_get_data_type_suite(void); Suite *getdns_dict_get_dict_suite(void); Suite *getdns_dict_get_list_suite(void); + Suite *getdns_dict_get_bindata_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -52,6 +54,7 @@ main (void) srunner_add_suite(sr, getdns_dict_get_data_type_suite()); srunner_add_suite(sr, getdns_dict_get_dict_suite()); srunner_add_suite(sr, getdns_dict_get_list_suite()); + srunner_add_suite(sr, getdns_dict_get_bindata_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_get_bindata.h b/src/test/check_getdns_dict_get_bindata.h new file mode 100644 index 00000000..637d7c2d --- /dev/null +++ b/src/test/check_getdns_dict_get_bindata.h @@ -0,0 +1,169 @@ +#ifndef _check_getdns_dict_get_bindata_h_ +#define _check_getdns_dict_get_bindata_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ G E T _ B I N D A T A * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_get_bindata_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata *answer = NULL; + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "key", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + + } + END_TEST + + START_TEST (getdns_dict_get_bindata_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + struct getdns_bindata *answer = NULL; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, NULL, &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_bindata_3) + { + /* + * name does not exist in dict + * Create a dict + * Create some bindata containing "bindata" and add it to the dict with name = "bindata" + * Call getdns_dict_get_bindata() against the first dict with name = "bindata1" + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + struct getdns_bindata *answer = NULL; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "bindata1", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_bindata_4) + { + /* + * data type at name is not bindata + * Create a dict with one int (name = "ten", value = 10) + * Call getdns_dict_get_bindata() with name = "ten" + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata *answer = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "ten", &answer), + GETDNS_RETURN_WRONG_TYPE_REQUESTED, "Return code from getdns_dict_get_bindata()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_bindata_5) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "bindata", NULL), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_bindata_6) + { + /* + * successful get bindata + * Create a dict + * Create some bindata containing "bindata" and add it to the dict with name = "bindata" + * Call getdns_dict_get_bindata() against the first dict with name = "bindata" + * expect: retrieved bindata should == "bindata" + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + struct getdns_bindata *answer = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "bindata", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_bindata()"); + + ck_assert_msg(answer->size == bindata.size, "Expected bindata size == %d, got: %d", + bindata.size, answer->size); + ck_assert_msg(strcmp((char *)answer->data, (char *)bindata.data) == 0, + "Expected bindata data to be \"%s\", got: \"%s\"", + (char *)bindata.data, (char *)answer->data); + + DICT_DESTROY(this_dict); + } + END_TEST + + Suite * + getdns_dict_get_bindata_suite (void) + { + Suite *s = suite_create ("getdns_dict_get_bindata()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_get_bindata_1); + tcase_add_test(tc_neg, getdns_dict_get_bindata_2); + tcase_add_test(tc_neg, getdns_dict_get_bindata_3); + tcase_add_test(tc_neg, getdns_dict_get_bindata_4); + tcase_add_test(tc_neg, getdns_dict_get_bindata_5); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_get_bindata_6); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From d5f1a3fe4bf98349ae29ffcf8892ec5667da2261 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Tue, 7 Jan 2014 14:49:04 -0500 Subject: [PATCH 23/35] Added tests for getdns_dict_get_int() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_get_int.h | 164 +++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 src/test/check_getdns_dict_get_int.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index bc472ff3..14c08433 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -21,6 +21,7 @@ #include "check_getdns_dict_get_dict.h" #include "check_getdns_dict_get_list.h" #include "check_getdns_dict_get_bindata.h" +#include "check_getdns_dict_get_int.h" int main (void) @@ -41,6 +42,7 @@ main (void) Suite *getdns_dict_get_dict_suite(void); Suite *getdns_dict_get_list_suite(void); Suite *getdns_dict_get_bindata_suite(void); + Suite *getdns_dict_get_int_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -55,6 +57,7 @@ main (void) srunner_add_suite(sr, getdns_dict_get_dict_suite()); srunner_add_suite(sr, getdns_dict_get_list_suite()); srunner_add_suite(sr, getdns_dict_get_bindata_suite()); + srunner_add_suite(sr, getdns_dict_get_int_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_get_int.h b/src/test/check_getdns_dict_get_int.h new file mode 100644 index 00000000..ede1f4de --- /dev/null +++ b/src/test/check_getdns_dict_get_int.h @@ -0,0 +1,164 @@ +#ifndef _check_getdns_dict_get_int_h_ +#define _check_getdns_dict_get_int_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ G E T _ I N T * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_get_int_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + uint32_t answer; + + ASSERT_RC(getdns_dict_get_int(this_dict, "key", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + + } + END_TEST + + START_TEST (getdns_dict_get_int_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + uint32_t answer; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_int(this_dict, "int", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, NULL, &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_int_3) + { + /* + * name does not exist in dict + * Create a dict with one int (name = "ten", value = 10) + * Call getdns_dict_get_int() against the dict with name = "nine" + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + uint32_t answer; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, "nine", &answer), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_int_4) + { + /* + * data type at name is not int + * Create a dict + * Create some bindata containing "bindata" and add it to the dict with name = "bindata" + * Call getdns_dict_get_int() with name = "bindata" + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + uint32_t answer; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, "bindata", &answer), + GETDNS_RETURN_WRONG_TYPE_REQUESTED, "Return code from getdns_dict_get_int()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_int_5) + { + /* + * answer = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "int", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, "int", NULL), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_get_int_6) + { + /* + * successful get int + * Create a dict with one int (name = "ten", value = 10) + * Call getdns_dict_get_int() against the dict with name = "ten" + * expect: GETDNS_RETURN_GOOD + * int retrievedshould == 10 + * + */ + struct getdns_dict *this_dict = NULL; + uint32_t answer; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "ten", 10), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, "ten", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_int()"); + + ck_assert_msg(answer == 10, "Expected retrieve int == 10, got: %d", + answer); + + DICT_DESTROY(this_dict); + } + END_TEST + + Suite * + getdns_dict_get_int_suite (void) + { + Suite *s = suite_create ("getdns_dict_get_int()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_get_int_1); + tcase_add_test(tc_neg, getdns_dict_get_int_2); + tcase_add_test(tc_neg, getdns_dict_get_int_3); + tcase_add_test(tc_neg, getdns_dict_get_int_4); + tcase_add_test(tc_neg, getdns_dict_get_int_5); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_get_int_6); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 5b9a09504a54bb3d205de666c1d5a08aa6b261f0 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Wed, 8 Jan 2014 11:29:33 -0500 Subject: [PATCH 24/35] Added tests for getdns_dict_destroy() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_destroy.h | 219 +++++++++++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 src/test/check_getdns_dict_destroy.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 14c08433..428641bb 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -22,6 +22,7 @@ #include "check_getdns_dict_get_list.h" #include "check_getdns_dict_get_bindata.h" #include "check_getdns_dict_get_int.h" +#include "check_getdns_dict_destroy.h" int main (void) @@ -43,6 +44,7 @@ main (void) Suite *getdns_dict_get_list_suite(void); Suite *getdns_dict_get_bindata_suite(void); Suite *getdns_dict_get_int_suite(void); + Suite *getdns_dict_destroy_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -58,6 +60,7 @@ main (void) srunner_add_suite(sr, getdns_dict_get_list_suite()); srunner_add_suite(sr, getdns_dict_get_bindata_suite()); srunner_add_suite(sr, getdns_dict_get_int_suite()); + srunner_add_suite(sr, getdns_dict_destroy_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_destroy.h b/src/test/check_getdns_dict_destroy.h new file mode 100644 index 00000000..d470bc82 --- /dev/null +++ b/src/test/check_getdns_dict_destroy.h @@ -0,0 +1,219 @@ +#ifndef _check_getdns_dict_destroy_h_ +#define _check_getdns_dict_destroy_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ D E S T R O Y * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_destroy_1) + { + /* + * this_dict = NULL + * expect: nothing + */ + struct getdns_dict *this_dict = NULL; + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_destroy_2) + { + /* + * build a complex dict and then destroy it + * + * dict1-> "int" = 1 + * -> "bindata" = { 8, "bindata" } + * -> "dict" = dict2->"int" = 2 + * -> "bindata" = { 8, "bindata" } + * -> "dict" = dict3 -> "int" = 3 + * -> "bindata" = { 8, "bindata" } + * -> "dict" = dict4 -> "int" = 4 + * -> "list" = list1 0: int = 5 + * -> "list" = list2 0: int = 6 + * 1: bindata = { 8, "bindata" } + * 2: dict = dict5 -> "bindata" = { 8, "bindata" } + * 3: list = list3 0: bindata = { 8, "bindata" } + * -> "list" = list4 0: int = 6 + * 1: bindata = { 8, "bindata" } + * 2: dict6 -> "int" = 8 + * -> "bindata" = { 8, "bindata" } + * -> "dict" = dict7 -> "int" = 9 + * -> "list" = list5 0: int = 10 + * 3: list6 0: int = 11 + * 1: bindata = { 8, "bindata" } + * 2: dict8 -> "bindata" = { 8, "bindata" } + * 3: list7 0: bindata = { 8, "bindata" } + * + * expect: nothing + */ + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + struct getdns_list *list7; + struct getdns_dict *dict8; + struct getdns_list *list6; + struct getdns_list *list5; + struct getdns_dict *dict7; + struct getdns_dict *dict6; + struct getdns_list *list4; + struct getdns_list *list3; + struct getdns_dict *dict5; + struct getdns_list *list2; + struct getdns_list *list1; + struct getdns_dict *dict4; + struct getdns_dict *dict3; + struct getdns_dict *dict2; + struct getdns_dict *dict1; + + /* + * Build it backwards, with the deepest elements first. + */ + LIST_CREATE(list7); + ASSERT_RC(getdns_list_set_bindata(list7, 0, &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + DICT_CREATE(dict8); + ASSERT_RC(getdns_dict_set_bindata(dict8, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + LIST_CREATE(list6); + ASSERT_RC(getdns_list_set_int(list6, 0, 11), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + ASSERT_RC(getdns_list_set_bindata(list6, 1, &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()"); + ASSERT_RC(getdns_list_set_dict(list6, 2, dict8), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_dict()"); + ASSERT_RC(getdns_list_set_list(list6, 3, list7), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_list()"); + + LIST_CREATE(list5); + ASSERT_RC(getdns_list_set_int(list5, 0, 10), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + + DICT_CREATE(dict7); + ASSERT_RC(getdns_dict_set_int(dict7, "int", 9), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + DICT_CREATE(dict6); + ASSERT_RC(getdns_dict_set_int(dict6, "int", 8), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_bindata(dict6, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_dict(dict6, "dict", dict7), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + ASSERT_RC(getdns_dict_set_list(dict6, "list", list5), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + LIST_CREATE(list4); + ASSERT_RC(getdns_list_set_int(list4, 0, 7), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + ASSERT_RC(getdns_list_set_bindata(list4, 1, &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()"); + ASSERT_RC(getdns_list_set_dict(list4, 2, dict6), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_dict()"); + ASSERT_RC(getdns_list_set_list(list4, 3, list5), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_list()"); + + LIST_CREATE(list3); + ASSERT_RC(getdns_list_set_bindata(list3, 0, &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()"); + + DICT_CREATE(dict5); + ASSERT_RC(getdns_dict_set_bindata(dict5, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + LIST_CREATE(list2); + ASSERT_RC(getdns_list_set_int(list2, 0, 6), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + ASSERT_RC(getdns_list_set_bindata(list2, 1, &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_bindata()"); + ASSERT_RC(getdns_list_set_dict(list2, 2, dict5), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_dict()"); + ASSERT_RC(getdns_list_set_list(list2, 3, list3), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_list()"); + + LIST_CREATE(list1); + ASSERT_RC(getdns_list_set_int(list1, 0, 5), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + + DICT_CREATE(dict4); + ASSERT_RC(getdns_dict_set_int(dict4, "int", 4), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + DICT_CREATE(dict3); + ASSERT_RC(getdns_dict_set_int(dict3, "int", 3), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_bindata(dict3, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_dict(dict3, "dict", dict4), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + ASSERT_RC(getdns_dict_set_list(dict3, "list", list1), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + DICT_CREATE(dict2); + ASSERT_RC(getdns_dict_set_int(dict2, "int", 2), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_bindata(dict2, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_dict(dict2, "dict", dict3), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + ASSERT_RC(getdns_dict_set_list(dict2, "list", list2), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + DICT_CREATE(dict1); + ASSERT_RC(getdns_dict_set_int(dict1, "int", 1), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_bindata(dict1, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_dict(dict1, "dict", dict2), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + ASSERT_RC(getdns_dict_set_list(dict1, "list", list4), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + /* + * Destroy all of the sub-dicts and sub-lists + */ + LIST_DESTROY(list7); + DICT_DESTROY(dict8); + LIST_DESTROY(list6); + LIST_DESTROY(list5); + DICT_DESTROY(dict7); + DICT_DESTROY(dict6); + LIST_DESTROY(list4); + LIST_DESTROY(list3); + DICT_DESTROY(dict5); + LIST_DESTROY(list2); + LIST_DESTROY(list1); + DICT_DESTROY(dict4); + DICT_DESTROY(dict3); + DICT_DESTROY(dict2); + + /* + * And now destroy the mother of all ints, bindata, dicts, and lists + */ + DICT_DESTROY(dict1); + } + END_TEST + + Suite * + getdns_dict_destroy_suite (void) + { + Suite *s = suite_create ("getdns_dict_destroy()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_destroy_1); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_destroy_2); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 1856b6bb05f63c6972ae5e7b95a1f0f946a829cd Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Wed, 8 Jan 2014 14:50:43 -0500 Subject: [PATCH 25/35] Fixed memory leaks found within tests --- src/test/check_getdns_cancel_callback.h | 1 + src/test/check_getdns_context_destroy.h | 1 + src/test/check_getdns_dict_get_dict.h | 1 + src/test/check_getdns_dict_get_names.h | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/check_getdns_cancel_callback.h b/src/test/check_getdns_cancel_callback.h index 631096ea..7ff5bc5f 100644 --- a/src/test/check_getdns_cancel_callback.h +++ b/src/test/check_getdns_cancel_callback.h @@ -302,6 +302,7 @@ ck_assert_msg(callback_completed == even, "callback_completed should == %d, got: %d", even, callback_completed); ck_assert_msg(callback_canceled == odd, "callback_canceled should == %d, got: %d", odd, callback_canceled); + DICT_DESTROY(address); CONTEXT_DESTROY; } END_TEST diff --git a/src/test/check_getdns_context_destroy.h b/src/test/check_getdns_context_destroy.h index fdb9b0e1..f085e2ca 100644 --- a/src/test/check_getdns_context_destroy.h +++ b/src/test/check_getdns_context_destroy.h @@ -111,6 +111,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_address()"); RUN_EVENT_LOOP; + DICT_DESTROY(address); CONTEXT_DESTROY; ck_assert_msg(callback_called == 1, "callback_called should == 1, got %d", callback_called); diff --git a/src/test/check_getdns_dict_get_dict.h b/src/test/check_getdns_dict_get_dict.h index 92ad6115..cdf6046a 100644 --- a/src/test/check_getdns_dict_get_dict.h +++ b/src/test/check_getdns_dict_get_dict.h @@ -190,6 +190,7 @@ ck_assert_msg(sum == sum_of_values, "Sum of int values in dict should == %d, got: %d", sum_of_values, sum); + LIST_DESTROY(names); DICT_DESTROY(this_dict); DICT_DESTROY(second_dict); } diff --git a/src/test/check_getdns_dict_get_names.h b/src/test/check_getdns_dict_get_names.h index f0f82443..5ba25a94 100644 --- a/src/test/check_getdns_dict_get_names.h +++ b/src/test/check_getdns_dict_get_names.h @@ -56,7 +56,7 @@ int i; size_t length; struct getdns_bindata *key = NULL; - char string_buffer[20]; + char string_buffer[20] = ""; DICT_CREATE(this_dict); @@ -84,6 +84,7 @@ ck_assert_msg(strcmp(string_buffer, "elevententwelve") == 0, "Expected concatenated names to be \"elevententwelve\", got \"%s\"", string_buffer); + LIST_DESTROY(answer); DICT_DESTROY(this_dict); } END_TEST From 413fcba9e3fa1e06293ff9d6a2c53235094af6fd Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 10 Jan 2014 09:50:30 -0500 Subject: [PATCH 26/35] Added tests for getdns_dict_set_dict() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_set_dict.h | 166 ++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 src/test/check_getdns_dict_set_dict.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 428641bb..3f232282 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -23,6 +23,7 @@ #include "check_getdns_dict_get_bindata.h" #include "check_getdns_dict_get_int.h" #include "check_getdns_dict_destroy.h" +#include "check_getdns_dict_set_dict.h" int main (void) @@ -45,6 +46,7 @@ main (void) Suite *getdns_dict_get_bindata_suite(void); Suite *getdns_dict_get_int_suite(void); Suite *getdns_dict_destroy_suite(void); + Suite *getdns_dict_set_dict_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -61,6 +63,7 @@ main (void) srunner_add_suite(sr, getdns_dict_get_bindata_suite()); srunner_add_suite(sr, getdns_dict_get_int_suite()); srunner_add_suite(sr, getdns_dict_destroy_suite()); + srunner_add_suite(sr, getdns_dict_set_dict_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_set_dict.h b/src/test/check_getdns_dict_set_dict.h new file mode 100644 index 00000000..2a9f91d7 --- /dev/null +++ b/src/test/check_getdns_dict_set_dict.h @@ -0,0 +1,166 @@ +#ifndef _check_getdns_dict_set_dict_h_ +#define _check_getdns_dict_set_dict_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ S E T _ D I C T * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_set_dict_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *child_dict = NULL; + + DICT_CREATE(child_dict); + ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", child_dict), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_set_dict()"); + DICT_DESTROY(child_dict); + + } + END_TEST + + START_TEST (getdns_dict_set_dict_2) + { + /* + * child_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *child_dict = NULL; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", child_dict), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_dict_set_dict()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_dict_3) + { + /* + * name already exists in dict + * Create a dict + * Create a second dict containing name = "int" with value = 100 + * Add the second dict to the first dict as name = "dict" + * Create a third dict containing name = "int" with value = 101 + * Add the third dict to the first dict as name = "dict" + * Call getdns_dict_get_dict() against the first dict with name = "dict" + * Call getdns_dict_get_int() against the retrieved dict for name = "int" + * expect: GETDNS_RETURN_GOOD (all functions) + * retrieved int should = 101 + */ + struct getdns_dict *first_dict = NULL; + struct getdns_dict *second_dict = NULL; + struct getdns_dict *third_dict = NULL; + struct getdns_dict *answer = NULL; + uint32_t retrieved_int; + + DICT_CREATE(first_dict); + + DICT_CREATE(second_dict); + ASSERT_RC(getdns_dict_set_int(second_dict, "int", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_dict(first_dict, "dict", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + DICT_CREATE(third_dict); + ASSERT_RC(getdns_dict_set_int(third_dict, "int", 101), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_dict(first_dict, "dict", third_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_dict(first_dict, "dict", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_dict()"); + + ASSERT_RC(getdns_dict_get_int(answer, "int", &retrieved_int), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_int()"); + + ck_assert_msg(retrieved_int == 101, "Exepected retrieved int == 101, got: %d", + retrieved_int); + + DICT_DESTROY(first_dict); + DICT_DESTROY(second_dict); + DICT_DESTROY(third_dict); + } + END_TEST + + START_TEST (getdns_dict_set_dict_4) + { + /* + * name already exists in dict, changing data type + * Create a dict + * Create a list + * Set list value at index 0 to int 100 + * Add the list to the dict as name = "list" + * Create a second dict + * Add an int to the second dict with name = "int", value = 101 + * Add the second dict to the first dict as name = "list" + * Call getdns_dict_get_dict to retrieve the second dict + * Call getdns_dict_get_int with name = "int" + * expect: GETDNS_RETURN_GOOD (all functions) + * retrieved int should = 101 + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + struct getdns_dict *second_dict = NULL; + struct getdns_dict *answer = NULL; + uint32_t retrieved_int; + + DICT_CREATE(this_dict); + + LIST_CREATE(list); + ASSERT_RC(getdns_list_set_int(list, 0, 100), + GETDNS_RETURN_GOOD, "Return code from getdns_list_set_int()"); + + ASSERT_RC(getdns_dict_set_list(this_dict, "list", list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); + + DICT_CREATE(second_dict); + ASSERT_RC(getdns_dict_set_int(second_dict, "int", 101), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_dict(this_dict, "list", second_dict), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); + + ASSERT_RC(getdns_dict_get_dict(this_dict, "list", &answer), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_dict()"); + ASSERT_RC(getdns_dict_get_int(answer, "int", &retrieved_int), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_int()"); + + ck_assert_msg(retrieved_int == 101, "Exepected retrieved int == 101, got: %d", + retrieved_int); + + DICT_DESTROY(this_dict); + LIST_DESTROY(list); + DICT_DESTROY(second_dict); + } + END_TEST + + Suite * + getdns_dict_set_dict_suite (void) + { + Suite *s = suite_create ("getdns_dict_set_dict()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_set_dict_1); + tcase_add_test(tc_neg, getdns_dict_set_dict_2); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_set_dict_3); + tcase_add_test(tc_pos, getdns_dict_set_dict_4); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 43c43ac305276fd69767404b87c0dc44d6520d03 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 10 Jan 2014 11:57:37 -0500 Subject: [PATCH 27/35] Test adjustments for GETDNS_RETURN_INVALID_PARAMETER --- src/test/check_getdns_dict_get_data_type.h | 12 ++++---- src/test/check_getdns_dict_set_dict.h | 35 +++++++++++++++++----- src/test/check_getdns_general.h | 4 +-- src/test/check_getdns_list_get_data_type.h | 4 +-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/test/check_getdns_dict_get_data_type.h b/src/test/check_getdns_dict_get_data_type.h index 0f42d84a..aaf55258 100644 --- a/src/test/check_getdns_dict_get_data_type.h +++ b/src/test/check_getdns_dict_get_data_type.h @@ -13,13 +13,13 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; getdns_data_type answer; ASSERT_RC(getdns_dict_get_data_type(this_dict, "key", &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_data_type()"); } END_TEST @@ -28,7 +28,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; getdns_data_type answer; @@ -38,7 +38,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); ASSERT_RC(getdns_dict_get_data_type(this_dict, NULL, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_data_type()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_data_type()"); DICT_DESTROY(this_dict); @@ -78,7 +78,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; @@ -87,7 +87,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); ASSERT_RC(getdns_dict_get_data_type(this_dict, "ten", NULL), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_names()"); DICT_DESTROY(this_dict); } diff --git a/src/test/check_getdns_dict_set_dict.h b/src/test/check_getdns_dict_set_dict.h index 2a9f91d7..0142fe0c 100644 --- a/src/test/check_getdns_dict_set_dict.h +++ b/src/test/check_getdns_dict_set_dict.h @@ -13,37 +13,57 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_dict *child_dict = NULL; DICT_CREATE(child_dict); ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", child_dict), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_set_dict()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_dict()"); DICT_DESTROY(child_dict); } END_TEST START_TEST (getdns_dict_set_dict_2) + { + /* + * name= NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + struct getdns_dict *child_dict = NULL; + + DICT_CREATE(this_dict); + DICT_CREATE(child_dict); + ASSERT_RC(getdns_dict_set_dict(this_dict, NULL, child_dict), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_dict()"); + + DICT_DESTROY(this_dict); + DICT_DESTROY(child_dict); + + } + END_TEST + + START_TEST (getdns_dict_set_dict_3) { /* * child_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_dict *child_dict = NULL; DICT_CREATE(this_dict); ASSERT_RC(getdns_dict_set_dict(this_dict, "dict", child_dict), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_dict_set_dict()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_dict()"); DICT_DESTROY(this_dict); } END_TEST - START_TEST (getdns_dict_set_dict_3) + START_TEST (getdns_dict_set_dict_4) { /* * name already exists in dict @@ -92,7 +112,7 @@ } END_TEST - START_TEST (getdns_dict_set_dict_4) + START_TEST (getdns_dict_set_dict_5) { /* * name already exists in dict, changing data type @@ -152,12 +172,13 @@ TCase *tc_neg = tcase_create("Negative"); tcase_add_test(tc_neg, getdns_dict_set_dict_1); tcase_add_test(tc_neg, getdns_dict_set_dict_2); + tcase_add_test(tc_neg, getdns_dict_set_dict_3); suite_add_tcase(s, tc_neg); /* Positive test cases */ TCase *tc_pos = tcase_create("Positive"); - tcase_add_test(tc_pos, getdns_dict_set_dict_3); tcase_add_test(tc_pos, getdns_dict_set_dict_4); + tcase_add_test(tc_pos, getdns_dict_set_dict_5); suite_add_tcase(s, tc_pos); return s; diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index 5ccd7fd7..1ffc0e86 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -96,7 +96,7 @@ { /* * callbackfn = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ @@ -107,7 +107,7 @@ ASSERT_RC(getdns_general(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL, &transaction_id, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; diff --git a/src/test/check_getdns_list_get_data_type.h b/src/test/check_getdns_list_get_data_type.h index d92d7162..874e6e34 100644 --- a/src/test/check_getdns_list_get_data_type.h +++ b/src/test/check_getdns_list_get_data_type.h @@ -53,7 +53,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_list *list = NULL; size_t index = 0; @@ -64,7 +64,7 @@ "Return code from getdns_list_set_int()"); ASSERT_RC(getdns_list_get_data_type(list, index, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_list_get_data_type()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_list_get_data_type()"); LIST_DESTROY(list); } From f392d9ebe572111caac3f8298c5aadd9d6158b2f Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 10 Jan 2014 13:50:31 -0500 Subject: [PATCH 28/35] Added tests for getdns_dict_set_list() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_set_list.h | 190 ++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 src/test/check_getdns_dict_set_list.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 3f232282..10b767ef 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -24,6 +24,7 @@ #include "check_getdns_dict_get_int.h" #include "check_getdns_dict_destroy.h" #include "check_getdns_dict_set_dict.h" +#include "check_getdns_dict_set_list.h" int main (void) @@ -47,6 +48,7 @@ main (void) Suite *getdns_dict_get_int_suite(void); Suite *getdns_dict_destroy_suite(void); Suite *getdns_dict_set_dict_suite(void); + Suite *getdns_dict_set_list_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -64,6 +66,7 @@ main (void) srunner_add_suite(sr, getdns_dict_get_int_suite()); srunner_add_suite(sr, getdns_dict_destroy_suite()); srunner_add_suite(sr, getdns_dict_set_dict_suite()); + srunner_add_suite(sr, getdns_dict_set_list_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_set_list.h b/src/test/check_getdns_dict_set_list.h new file mode 100644 index 00000000..a17c0983 --- /dev/null +++ b/src/test/check_getdns_dict_set_list.h @@ -0,0 +1,190 @@ +#ifndef _check_getdns_dict_set_list_h_ +#define _check_getdns_dict_set_list_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ S E T _ L I S T * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_set_list_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_list(this_dict, "list", list), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_list()"); + + } + END_TEST + + START_TEST (getdns_dict_set_list_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *list = NULL; + + DICT_CREATE(this_dict); + LIST_CREATE(list); + ASSERT_RC(getdns_dict_set_list(this_dict, NULL, list), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_list()"); + + DICT_DESTROY(this_dict); + LIST_DESTROY(list); + } + END_TEST + + START_TEST (getdns_dict_set_list_3) + { + /* + * child_list = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + + DICT_CREATE(this_dict); + ASSERT_RC(getdns_dict_set_list(this_dict, "list", NULL), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_list()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_list_4) + { + /* + * name already exists in dict + * Create a dict + * Create a list + * Set list value at index 0 via getdns_list_set_int() to 100 + * Add the list to the dict as name "list" + * Create a second list + * Set list value at index 0 in the second list to 101 + * Add the second list to the dict using name "list" again + * Call getdns_dict_get_list() against the dict with name = "list" + * Call getdns_list_get_int() for index 0 against the retrieved list + * expect: GETDNS_RETURN_GOOD (all functions) + * retrieved int should = 101 + */ + struct getdns_dict *this_dict = NULL; + struct getdns_list *first_list = NULL; + struct getdns_list *second_list = NULL; + struct getdns_list *retrieved_list = NULL; + uint32_t value; + + DICT_CREATE(this_dict); + + LIST_CREATE(first_list); + ASSERT_RC(getdns_list_set_int(first_list, 0, 100), + GETDNS_RETURN_GOOD, "Return from getdns_list_set_int()"); + + ASSERT_RC(getdns_dict_set_list(this_dict, "list", first_list), + GETDNS_RETURN_GOOD, "Return from getdns_list_set_list()"); + + LIST_CREATE(second_list); + ASSERT_RC(getdns_list_set_int(second_list, 0, 101), + GETDNS_RETURN_GOOD, "Return from getdns_list_set_int()"); + + ASSERT_RC(getdns_dict_set_list(this_dict, "list", second_list), + GETDNS_RETURN_GOOD, "Return from getdns_list_set_list()"); + + ASSERT_RC(getdns_dict_get_list(this_dict, "list", &retrieved_list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_list()"); + + ASSERT_RC(getdns_list_get_int(retrieved_list, 0, &value), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_int()"); + + ck_assert_msg(value == 101, "Expected int retrieved == 101, got: %d", + value); + + DICT_DESTROY(this_dict); + LIST_DESTROY(first_list); + LIST_DESTROY(second_list); + } + END_TEST + + START_TEST (getdns_dict_set_list_5) + { + /* + * name already exists in dict, changing data type + * Create a dict + * Create a second dict + * Add an int to the second dict (name = "int", value = 100) + * Add the second dict to the first dict as name "list" + * Create a list + * Set list value at index 0 in the list to 101 + * Add the list to the first dict using name "list" again + * Call getdns_dict_get_list() against the dict with name = "list" + * Call getdns_list_get_int() for index 0 against the retrieved list + * expect: GETDNS_RETURN_GOOD (all functions) + * retrieved int should = 101 + */ + struct getdns_dict *first_dict = NULL; + struct getdns_dict *second_dict = NULL; + struct getdns_list *list = NULL; + struct getdns_list *retrieved_list = NULL; + uint32_t value; + + DICT_CREATE(first_dict); + + DICT_CREATE(second_dict); + ASSERT_RC(getdns_dict_set_int(second_dict, "int", 100), + GETDNS_RETURN_GOOD, "Return from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_set_dict(first_dict, "list", second_dict), + GETDNS_RETURN_GOOD, "Return from getdns_dict_set_dict()"); + + LIST_CREATE(list); + ASSERT_RC(getdns_list_set_int(list, 0, 101), + GETDNS_RETURN_GOOD, "Return from getdns_list_set_int()"); + + ASSERT_RC(getdns_dict_set_list(first_dict, "list", list), + GETDNS_RETURN_GOOD, "Return from getdns_dict_set_list()"); + + ASSERT_RC(getdns_dict_get_list(first_dict, "list", &retrieved_list), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_list()"); + + ASSERT_RC(getdns_list_get_int(retrieved_list, 0, &value), + GETDNS_RETURN_GOOD, "Return code from getdns_list_get_int()"); + + ck_assert_msg(value == 101, "Expected int retrieved == 101, got: %d", + value); + + DICT_DESTROY(first_dict); + DICT_DESTROY(second_dict); + LIST_DESTROY(list); + } + END_TEST + + Suite * + getdns_dict_set_list_suite (void) + { + Suite *s = suite_create ("getdns_dict_set_list()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_set_list_1); + tcase_add_test(tc_neg, getdns_dict_set_list_2); + tcase_add_test(tc_neg, getdns_dict_set_list_3); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_set_list_4); + tcase_add_test(tc_pos, getdns_dict_set_list_5); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From 75b89dabe9fcfb5f348754f65eeb62ec803fd13c Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 10 Jan 2014 14:29:08 -0500 Subject: [PATCH 29/35] Added tests for getdns_dict_set_bindata() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_set_bindata.h | 160 +++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 src/test/check_getdns_dict_set_bindata.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 10b767ef..d6afe9c1 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -25,6 +25,7 @@ #include "check_getdns_dict_destroy.h" #include "check_getdns_dict_set_dict.h" #include "check_getdns_dict_set_list.h" +#include "check_getdns_dict_set_bindata.h" int main (void) @@ -49,6 +50,7 @@ main (void) Suite *getdns_dict_destroy_suite(void); Suite *getdns_dict_set_dict_suite(void); Suite *getdns_dict_set_list_suite(void); + Suite *getdns_dict_set_bindata_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -67,6 +69,7 @@ main (void) srunner_add_suite(sr, getdns_dict_destroy_suite()); srunner_add_suite(sr, getdns_dict_set_dict_suite()); srunner_add_suite(sr, getdns_dict_set_list_suite()); + srunner_add_suite(sr, getdns_dict_set_bindata_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_set_bindata.h b/src/test/check_getdns_dict_set_bindata.h new file mode 100644 index 00000000..5f8d145b --- /dev/null +++ b/src/test/check_getdns_dict_set_bindata.h @@ -0,0 +1,160 @@ +#ifndef _check_getdns_dict_set_bindata_h_ +#define _check_getdns_dict_set_bindata_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ S E T _ B I N D A T A * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_set_bindata_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "key", &bindata), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_bindata()"); + + } + END_TEST + + START_TEST (getdns_dict_set_bindata_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, NULL, &bindata), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_bindata()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_bindata_3) + { + /* + * child_bindata = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", NULL), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_bindata()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_bindata_4) + { + /* + * name already exists in dict + * Create a dict + * Add bindata to the dict (name = "bindata", value = { 8, "bindata" }) + * Add bindata to the dict (name = "bindata", value = { 15, "second_bindata" }) + * Call getdns_dict_get_bindata() with name = "bindata" + * expect: GETDNS_RETURN_GOOD (all functions) + * bindata retrieved = "second_bindata" + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + struct getdns_bindata second_bindata = { 15, (void *)"second_bindata" }; + struct getdns_bindata *retrieved_bindata = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &second_bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "bindata", &retrieved_bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_bindata()"); + + ck_assert_msg(retrieved_bindata->size, second_bindata.size, + "Expected retrieved bindata size == %d, got: %d", + second_bindata.size, retrieved_bindata->size); + + ck_assert_msg(strcmp((char *)retrieved_bindata->data, (char *)second_bindata.data) == 0, + "Expected retrieved bindata to be \"%s\", got: \"%s\"", + (char *)second_bindata.data, (char *)retrieved_bindata->data); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_bindata_5) + { + /* + * name already exists in dict, changing data type + * Create a dict + * Add an int to the dict (name = "int", value = 100) + * Add bindata to the dict (name = "int", value = { 8, "bindata" }) + * Call getdns_dict_get_bindata() against the dict with name = "int" + * expect: GETDNS_RETURN_GOOD (all functions) + * retrieved bindata should == "bindata" + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + struct getdns_bindata *retrieved_bindata = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "int", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "int", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_get_bindata(this_dict, "int", &retrieved_bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_bindata()"); + + ck_assert_msg(retrieved_bindata->size == bindata.size, + "Expected retrieved bindata size == %d, got: %d", + bindata.size, retrieved_bindata->size); + + ck_assert_msg(strcmp((char *)retrieved_bindata->data, (char *)bindata.data) == 0, + "Expected bindata data to be \"%s\", got: \"%s\"", + (char *)bindata.data, (char *)retrieved_bindata->data); + + DICT_DESTROY(this_dict); + } + END_TEST + + Suite * + getdns_dict_set_bindata_suite (void) + { + Suite *s = suite_create ("getdns_dict_set_bindata()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_set_bindata_1); + tcase_add_test(tc_neg, getdns_dict_set_bindata_2); + tcase_add_test(tc_neg, getdns_dict_set_bindata_3); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_set_bindata_4); + tcase_add_test(tc_pos, getdns_dict_set_bindata_5); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From e7be219f4e8bfc5153d0525a657430ff5b5c16af Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Fri, 10 Jan 2014 16:35:05 -0500 Subject: [PATCH 30/35] Added tests for getdns_dict_set_int() --- src/test/check_getdns.c | 3 + src/test/check_getdns_dict_set_int.h | 128 +++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/test/check_getdns_dict_set_int.h diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index d6afe9c1..e04d834d 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -26,6 +26,7 @@ #include "check_getdns_dict_set_dict.h" #include "check_getdns_dict_set_list.h" #include "check_getdns_dict_set_bindata.h" +#include "check_getdns_dict_set_int.h" int main (void) @@ -51,6 +52,7 @@ main (void) Suite *getdns_dict_set_dict_suite(void); Suite *getdns_dict_set_list_suite(void); Suite *getdns_dict_set_bindata_suite(void); + Suite *getdns_dict_set_int_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -70,6 +72,7 @@ main (void) srunner_add_suite(sr, getdns_dict_set_dict_suite()); srunner_add_suite(sr, getdns_dict_set_list_suite()); srunner_add_suite(sr, getdns_dict_set_bindata_suite()); + srunner_add_suite(sr, getdns_dict_set_int_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_dict_set_int.h b/src/test/check_getdns_dict_set_int.h new file mode 100644 index 00000000..7be7653a --- /dev/null +++ b/src/test/check_getdns_dict_set_int.h @@ -0,0 +1,128 @@ +#ifndef _check_getdns_dict_set_int_h_ +#define _check_getdns_dict_set_int_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ D I C T _ S E T _ I N T * + * * + ************************************************************************** + */ + + START_TEST (getdns_dict_set_int_1) + { + /* + * this_dict = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_dict *this_dict = NULL; + + ASSERT_RC(getdns_dict_set_int(this_dict, "key", 100), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_int()"); + + } + END_TEST + + START_TEST (getdns_dict_set_int_2) + { + /* + * name = NULL + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_dict *this_dict = NULL; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, NULL, 100), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_set_int()"); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_int_3) + { + /* + * name already exists in dict + * Create a dict + * Add an int to the dict (name = "int", value = 100) + * Add an int to the dict (name = "int", value = 101) + * Call getdns_dict_get_int() against the dict with name = "int" + * expect: GETDNS_RETURN_GOOD (all functions) + * int retrieved should = 101 + */ + struct getdns_dict *this_dict = NULL; + uint32_t value; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_int(this_dict, "int", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_set_int(this_dict, "int", 101), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, "int", &value), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_int()"); + + ck_assert_msg(value == 101, "Expected retrieved int == 101, got: %d", + value); + + DICT_DESTROY(this_dict); + } + END_TEST + + START_TEST (getdns_dict_set_int_4) + { + /* + * name already exists in dict, changing data type + * Create a dict + * Add bindata to the dict (name = "bindata", value = { 8, "bindata" }) + * Add an int to the dict (name = "bindata", value = 101) + * Call getdns_dict_get_int() with name = "bindata" + * expect: GETDNS_RETURN_GOOD (all functions) + * int retrieved should = 101 + */ + struct getdns_dict *this_dict = NULL; + struct getdns_bindata bindata = { 8, (void *)"bindata" }; + uint32_t value; + + DICT_CREATE(this_dict); + + ASSERT_RC(getdns_dict_set_bindata(this_dict, "bindata", &bindata), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_dict_set_int(this_dict, "bindata", 101), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_dict_get_int(this_dict, "bindata", &value), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_get_int()"); + + ck_assert_msg(value == 101, "Expected retrieved int == 101, got: %d", + value); + + DICT_DESTROY(this_dict); + } + END_TEST + + Suite * + getdns_dict_set_int_suite (void) + { + Suite *s = suite_create ("getdns_dict_set_int()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_dict_set_int_1); + tcase_add_test(tc_neg, getdns_dict_set_int_2); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_dict_set_int_3); + tcase_add_test(tc_pos, getdns_dict_set_int_4); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From fd4ca9d919a3fa157edabe0a42bbf52cb04ec2ee Mon Sep 17 00:00:00 2001 From: Atlas config user Date: Mon, 13 Jan 2014 16:38:41 +0000 Subject: [PATCH 31/35] initial check_getdns_convert_alabel_to_ulabel.h check_getdns_convert_ulabel_to_alabel.h --- src/test/check_getdns_address_sync.h | 36 ++++----------- .../check_getdns_convert_alabel_to_ulabel.h | 45 +++++++++++++++++++ .../check_getdns_convert_ulabel_to_alabel.h | 45 +++++++++++++++++++ 3 files changed, 98 insertions(+), 28 deletions(-) create mode 100644 src/test/check_getdns_convert_alabel_to_ulabel.h create mode 100644 src/test/check_getdns_convert_ulabel_to_alabel.h diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h index 46e053dc..848af032 100644 --- a/src/test/check_getdns_address_sync.h +++ b/src/test/check_getdns_address_sync.h @@ -42,25 +42,6 @@ END_TEST START_TEST (getdns_address_sync_3) - { - /* - * name = invalid domain (too many octets) - * expect: GETDNS_RETURN_BAD_DOMAIN_NAME - */ - struct getdns_context *context = NULL; - struct getdns_dict *response = NULL; - const char *name = "oh.my.gosh.and.for.petes.sake.are.you.fricking.crazy.man.because.this.spectacular.and.elaborately.thought.out.domain.name.of.very.significant.length.is.just.too.darn.long.because.you.know.the rfc.states.that.two.hundred.fifty.five.characters.is.the.max.com"; - - CONTEXT_CREATE(TRUE); - - ASSERT_RC(getdns_address_sync(context, name, NULL, &response), - GETDNS_RETURN_BAD_DOMAIN_NAME, "Return code from getdns_address_sync()"); - - CONTEXT_DESTROY; - } - END_TEST - - START_TEST (getdns_address_sync_4) { /* * name = invalid domain (label too long) @@ -79,7 +60,7 @@ } END_TEST - START_TEST (getdns_address_sync_5) + START_TEST (getdns_address_sync_4) { /* * response = NULL @@ -96,7 +77,7 @@ } END_TEST - START_TEST (getdns_address_sync_6) + START_TEST (getdns_address_sync_5) { /* * name = "google.com" @@ -122,7 +103,7 @@ } END_TEST - START_TEST (getdns_address_sync_7) + START_TEST (getdns_address_sync_6) { /* * name = "localhost" @@ -149,7 +130,7 @@ } END_TEST - START_TEST (getdns_address_sync_8) + START_TEST (getdns_address_sync_7) { /* * name = "google.joe" @@ -179,7 +160,7 @@ } END_TEST - START_TEST (getdns_address_sync_9) + START_TEST (getdns_address_sync_8) { /* * name = "hampster.com" need to replace this with domain from unbound zone @@ -204,7 +185,7 @@ } END_TEST - START_TEST (getdns_address_sync_10) + START_TEST (getdns_address_sync_9) { /* * name = "google.com" need to swap this out for max domain name length with max lable length` @@ -230,7 +211,7 @@ } END_TEST - START_TEST (getdns_address_sync_11) + START_TEST (getdns_address_sync_10) { /* * name = "75.101.146.66" need to change this to local unbound data @@ -258,7 +239,7 @@ } END_TEST - START_TEST (getdns_address_sync_12) + START_TEST (getdns_address_sync_11) { /* * name = "2607:f8b0:4006:802::1007" need to change this to local unbound data @@ -308,7 +289,6 @@ tcase_add_test(tc_pos, getdns_address_sync_9); tcase_add_test(tc_pos, getdns_address_sync_10); tcase_add_test(tc_pos, getdns_address_sync_11); - tcase_add_test(tc_pos, getdns_address_sync_12); suite_add_tcase(s, tc_pos); return s; diff --git a/src/test/check_getdns_convert_alabel_to_ulabel.h b/src/test/check_getdns_convert_alabel_to_ulabel.h new file mode 100644 index 00000000..2d1e709b --- /dev/null +++ b/src/test/check_getdns_convert_alabel_to_ulabel.h @@ -0,0 +1,45 @@ +#ifndef _check_getdns_convert_alabel_to_ulabel_h_ +#define _check_getdns_convert_alabel_to_ulabel_h_ + + /* + ************************************************************************************* + * * + * T E S T S F O R G E T D N S _ C O N V E R T _ A L A B E L _ T O _ U L A B E L * + * * + ************************************************************************************* + */ + + START_TEST (getdns_convert_alabel_to_ulabel_1) + { + /* + * ulabel = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + ulabel = null; + + ASSERT_RC(getdns_convert_alabel_to_ulabel( *ulabel ), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); + } + END_TEST + + + Suite * + getdns_convert_alabel_to_ulabel_suite (void) + { + Suite *s = suite_create ("getdns_convert_alabel_to_ulabel()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_convert_alabel_to_ulabel_1); + tcase_add_test(tc_neg, getdns_convert_alabel_to_ulabel_2); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_convert_alabel_to_ulabel_3); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif diff --git a/src/test/check_getdns_convert_ulabel_to_alabel.h b/src/test/check_getdns_convert_ulabel_to_alabel.h new file mode 100644 index 00000000..2d1e709b --- /dev/null +++ b/src/test/check_getdns_convert_ulabel_to_alabel.h @@ -0,0 +1,45 @@ +#ifndef _check_getdns_convert_alabel_to_ulabel_h_ +#define _check_getdns_convert_alabel_to_ulabel_h_ + + /* + ************************************************************************************* + * * + * T E S T S F O R G E T D N S _ C O N V E R T _ A L A B E L _ T O _ U L A B E L * + * * + ************************************************************************************* + */ + + START_TEST (getdns_convert_alabel_to_ulabel_1) + { + /* + * ulabel = NULL + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + ulabel = null; + + ASSERT_RC(getdns_convert_alabel_to_ulabel( *ulabel ), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); + } + END_TEST + + + Suite * + getdns_convert_alabel_to_ulabel_suite (void) + { + Suite *s = suite_create ("getdns_convert_alabel_to_ulabel()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_convert_alabel_to_ulabel_1); + tcase_add_test(tc_neg, getdns_convert_alabel_to_ulabel_2); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_convert_alabel_to_ulabel_3); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif From e854db5a94eb227fbfb76214d8e6a709bbcf6679 Mon Sep 17 00:00:00 2001 From: Atlas config user Date: Mon, 13 Jan 2014 18:38:37 +0000 Subject: [PATCH 32/35] update convert_alabel_to_ulabel convert_alabel_to_ulabel --- src/test/check_getdns.c | 6 +++ .../check_getdns_convert_alabel_to_ulabel.h | 29 ++++++++++- .../check_getdns_convert_ulabel_to_alabel.h | 49 ++++++++++++++----- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index e04d834d..cdf2890d 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -27,6 +27,8 @@ #include "check_getdns_dict_set_list.h" #include "check_getdns_dict_set_bindata.h" #include "check_getdns_dict_set_int.h" +#include "check_getdns_convert_ulabel_to_alabel.h" +//#include "check_getdns_convert_alabel_to_ulabel.h" int main (void) @@ -53,6 +55,8 @@ main (void) Suite *getdns_dict_set_list_suite(void); Suite *getdns_dict_set_bindata_suite(void); Suite *getdns_dict_set_int_suite(void); + Suite *getdns_convert_ulabel_to_alabel_suite(void); + //Suite *getdns_convert_alabel_to_ulabel_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -73,6 +77,8 @@ main (void) srunner_add_suite(sr, getdns_dict_set_list_suite()); srunner_add_suite(sr, getdns_dict_set_bindata_suite()); srunner_add_suite(sr, getdns_dict_set_int_suite()); + srunner_add_suite(sr, getdns_convert_ulabel_to_alabel_suite()); + //srunner_add_suite(sr, getdns_convert_alabel_to_ulabel_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_convert_alabel_to_ulabel.h b/src/test/check_getdns_convert_alabel_to_ulabel.h index 2d1e709b..d1884193 100644 --- a/src/test/check_getdns_convert_alabel_to_ulabel.h +++ b/src/test/check_getdns_convert_alabel_to_ulabel.h @@ -15,13 +15,38 @@ * ulabel = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - ulabel = null; + char alabel = NULL; - ASSERT_RC(getdns_convert_alabel_to_ulabel( *ulabel ), + ASSERT_RC(getdns_convert_alabel_to_ulabel( *alabel ), GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); } END_TEST + START_TEST (getdns_convert_alabel_to_ulabel_2) + { + /* + * alabel = invalid characters + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + char alabel = "#$%_"; + + ASSERT_RC(getdns_convert_alabel_to_ulabel( *alabel ), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); + } + END_TEST + + START_TEST (getdns_convert_alabel_to_ulabel_3) + { + /* + * alabel = valid characters (ace must begin with prefix "xn--" and be followed by a valid puny algorithm output; length limited to 59 chars) + * expect: GETDNS_RETURN_GOOD + */ + char alabel = "xn--caf-dma"; + + ASSERT_RC(getdns_convert_alabel_to_ulabel( *alabel ), + GETDNS_RETURN_GOOD, "Return code from getdns_convert_alabel_to_ulabel()"); + } + END_TEST Suite * getdns_convert_alabel_to_ulabel_suite (void) diff --git a/src/test/check_getdns_convert_ulabel_to_alabel.h b/src/test/check_getdns_convert_ulabel_to_alabel.h index 2d1e709b..dc20ffc4 100644 --- a/src/test/check_getdns_convert_ulabel_to_alabel.h +++ b/src/test/check_getdns_convert_ulabel_to_alabel.h @@ -1,42 +1,67 @@ -#ifndef _check_getdns_convert_alabel_to_ulabel_h_ -#define _check_getdns_convert_alabel_to_ulabel_h_ +#ifndef _check_getdns_convert_ulabel_to_alabel_h_ +#define _check_getdns_convert_ulabel_to_alabel_h_ /* ************************************************************************************* * * - * T E S T S F O R G E T D N S _ C O N V E R T _ A L A B E L _ T O _ U L A B E L * + * T E S T S F O R G E T D N S _ C O N V E R T _ U L A B E L _ T O _ A L A B E L * * * ************************************************************************************* */ - START_TEST (getdns_convert_alabel_to_ulabel_1) + START_TEST (getdns_convert_ulabel_to_alabel_1) { /* * ulabel = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - ulabel = null; + char ulabel = NULL; - ASSERT_RC(getdns_convert_alabel_to_ulabel( *ulabel ), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); + ASSERT_RC(getdns_convert_ulabel_to_alabel( *ulabel ), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_ulabel_to_alabel()"); } END_TEST + START_TEST (getdns_convert_ulabel_to_alabel_2) + { + /* + * ulabel = invalid characters + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + char ulabel = "#$%_"; + + ASSERT_RC(getdns_convert_ulabel_to_alabel( *ulabel ), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_ulabel_to_alabel()"); + } + END_TEST + + START_TEST (getdns_convert_ulabel_to_alabel_3) + { + /* + * ulabel = valid characters ( _abc, -abc, -abc-, abc- and limited to 63 octets ) + * expect: GETDNS_RETURN_GOOD + */ + char ulabel = "café"; + + ASSERT_RC(getdns_convert_ulabel_to_alabel( *ulabel ), + GETDNS_RETURN_GOOD, "Return code from getdns_convert_ulabel_to_alabel()"); + } + END_TEST Suite * - getdns_convert_alabel_to_ulabel_suite (void) + getdns_convert_ulabel_to_alabel_suite (void) { - Suite *s = suite_create ("getdns_convert_alabel_to_ulabel()"); + Suite *s = suite_create ("getdns_convert_ulabel_to_alabel()"); /* Negative test caseis */ TCase *tc_neg = tcase_create("Negative"); - tcase_add_test(tc_neg, getdns_convert_alabel_to_ulabel_1); - tcase_add_test(tc_neg, getdns_convert_alabel_to_ulabel_2); + tcase_add_test(tc_neg, getdns_convert_ulabel_to_alabel_1); + tcase_add_test(tc_neg, getdns_convert_ulabel_to_alabel_2); suite_add_tcase(s, tc_neg); /* Positive test cases */ TCase *tc_pos = tcase_create("Positive"); - tcase_add_test(tc_pos, getdns_convert_alabel_to_ulabel_3); + tcase_add_test(tc_pos, getdns_convert_ulabel_to_alabel_3); suite_add_tcase(s, tc_pos); return s; From 63ef00aa9fc1e7a7af2ce514e890c52630ca4b67 Mon Sep 17 00:00:00 2001 From: "Craig E. Despeaux" Date: Mon, 13 Jan 2014 14:13:52 -0500 Subject: [PATCH 33/35] Modify expected return code for INVALID_PARAMETER conditions --- src/test/check_getdns_address_sync.h | 8 ++++---- src/test/check_getdns_context_create.h | 4 ++-- src/test/check_getdns_dict_get_bindata.h | 12 ++++++------ src/test/check_getdns_dict_get_dict.h | 12 ++++++------ src/test/check_getdns_dict_get_int.h | 12 ++++++------ src/test/check_getdns_dict_get_list.h | 12 ++++++------ src/test/check_getdns_dict_get_names.h | 8 ++++---- src/test/check_getdns_dict_set_bindata.h | 2 +- src/test/check_getdns_dict_set_int.h | 2 +- src/test/check_getdns_general.h | 4 ++-- src/test/check_getdns_general_sync.h | 8 ++++---- src/test/check_getdns_list_get_data_type.h | 4 ++-- src/test/check_getdns_list_get_length.h | 8 ++++---- 13 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/test/check_getdns_address_sync.h b/src/test/check_getdns_address_sync.h index 46e053dc..f4c790ff 100644 --- a/src/test/check_getdns_address_sync.h +++ b/src/test/check_getdns_address_sync.h @@ -27,7 +27,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; @@ -35,7 +35,7 @@ CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, NULL, NULL, &response), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_address_sync()"); CONTEXT_DESTROY; } @@ -83,14 +83,14 @@ { /* * response = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_context *context = NULL; CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_address_sync(context, "google.com", NULL, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_address_sync()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_address_sync()"); CONTEXT_DESTROY; } diff --git a/src/test/check_getdns_context_create.h b/src/test/check_getdns_context_create.h index 5f35d4fb..570e87d0 100644 --- a/src/test/check_getdns_context_create.h +++ b/src/test/check_getdns_context_create.h @@ -13,11 +13,11 @@ { /* * context = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ ASSERT_RC(getdns_context_create(NULL, TRUE), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_context_create()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_context_create()"); } END_TEST diff --git a/src/test/check_getdns_dict_get_bindata.h b/src/test/check_getdns_dict_get_bindata.h index 637d7c2d..70a9a931 100644 --- a/src/test/check_getdns_dict_get_bindata.h +++ b/src/test/check_getdns_dict_get_bindata.h @@ -13,13 +13,13 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_bindata *answer = NULL; ASSERT_RC(getdns_dict_get_bindata(this_dict, "key", &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_bindata()"); } END_TEST @@ -28,7 +28,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_bindata bindata = { 8, (void *)"bindata" }; @@ -39,7 +39,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); ASSERT_RC(getdns_dict_get_bindata(this_dict, NULL, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_bindata()"); DICT_DESTROY(this_dict); } @@ -96,7 +96,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_bindata bindata = { 8, (void *)"bindata" }; @@ -107,7 +107,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); ASSERT_RC(getdns_dict_get_bindata(this_dict, "bindata", NULL), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_bindata()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_bindata()"); DICT_DESTROY(this_dict); } diff --git a/src/test/check_getdns_dict_get_dict.h b/src/test/check_getdns_dict_get_dict.h index cdf6046a..99272d5b 100644 --- a/src/test/check_getdns_dict_get_dict.h +++ b/src/test/check_getdns_dict_get_dict.h @@ -13,13 +13,13 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_dict *answer = NULL; ASSERT_RC(getdns_dict_get_dict(this_dict, "key", &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_dict()"); } END_TEST @@ -28,7 +28,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_dict *second_dict = NULL; @@ -40,7 +40,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); ASSERT_RC(getdns_dict_get_dict(this_dict, NULL, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_dict()"); DICT_DESTROY(this_dict); DICT_DESTROY(second_dict); @@ -111,7 +111,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_dict *second_dict = NULL; @@ -123,7 +123,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_dict()"); ASSERT_RC(getdns_dict_get_dict(this_dict, "dict", NULL), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_dict()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_dict()"); DICT_DESTROY(this_dict); DICT_DESTROY(second_dict); diff --git a/src/test/check_getdns_dict_get_int.h b/src/test/check_getdns_dict_get_int.h index ede1f4de..994a210d 100644 --- a/src/test/check_getdns_dict_get_int.h +++ b/src/test/check_getdns_dict_get_int.h @@ -13,13 +13,13 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; uint32_t answer; ASSERT_RC(getdns_dict_get_int(this_dict, "key", &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_int()"); } END_TEST @@ -28,7 +28,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; uint32_t answer; @@ -38,7 +38,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); ASSERT_RC(getdns_dict_get_int(this_dict, NULL, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_int()"); DICT_DESTROY(this_dict); } @@ -95,7 +95,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; @@ -105,7 +105,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); ASSERT_RC(getdns_dict_get_int(this_dict, "int", NULL), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_int()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_int()"); DICT_DESTROY(this_dict); } diff --git a/src/test/check_getdns_dict_get_list.h b/src/test/check_getdns_dict_get_list.h index 828866bb..c5c370f0 100644 --- a/src/test/check_getdns_dict_get_list.h +++ b/src/test/check_getdns_dict_get_list.h @@ -13,13 +13,13 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_list *answer = NULL; ASSERT_RC(getdns_dict_get_list(this_dict, "key", &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_list()"); } END_TEST @@ -28,7 +28,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_list *list = NULL; @@ -40,7 +40,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); ASSERT_RC(getdns_dict_get_list(this_dict, NULL, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_list()"); DICT_DESTROY(this_dict); LIST_DESTROY(list); @@ -103,7 +103,7 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_list *list = NULL; @@ -115,7 +115,7 @@ GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_list()"); ASSERT_RC(getdns_dict_get_list(this_dict, "list", NULL), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_list()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_list()"); DICT_DESTROY(this_dict); LIST_DESTROY(list); diff --git a/src/test/check_getdns_dict_get_names.h b/src/test/check_getdns_dict_get_names.h index 5ba25a94..6b7c0fcb 100644 --- a/src/test/check_getdns_dict_get_names.h +++ b/src/test/check_getdns_dict_get_names.h @@ -13,13 +13,13 @@ { /* * this_dict = NULL - * expect = GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect = GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_list *answer = NULL; ASSERT_RC(getdns_dict_get_names(this_dict, &answer), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_names()"); } END_TEST @@ -28,14 +28,14 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; DICT_CREATE(this_dict); ASSERT_RC(getdns_dict_get_names(this_dict, NULL), - GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_dict_get_names()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_dict_get_names()"); DICT_DESTROY(this_dict); } diff --git a/src/test/check_getdns_dict_set_bindata.h b/src/test/check_getdns_dict_set_bindata.h index 5f8d145b..94da80b3 100644 --- a/src/test/check_getdns_dict_set_bindata.h +++ b/src/test/check_getdns_dict_set_bindata.h @@ -13,7 +13,7 @@ { /* * this_dict = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; struct getdns_bindata bindata = { 8, (void *)"bindata" }; diff --git a/src/test/check_getdns_dict_set_int.h b/src/test/check_getdns_dict_set_int.h index 7be7653a..1310e4de 100644 --- a/src/test/check_getdns_dict_set_int.h +++ b/src/test/check_getdns_dict_set_int.h @@ -27,7 +27,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_dict *this_dict = NULL; diff --git a/src/test/check_getdns_general.h b/src/test/check_getdns_general.h index 1ffc0e86..4fa2c1d9 100644 --- a/src/test/check_getdns_general.h +++ b/src/test/check_getdns_general.h @@ -28,7 +28,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_context *context = NULL; \ struct event_base *event_base = NULL; \ @@ -39,7 +39,7 @@ ASSERT_RC(getdns_general(context, NULL, GETDNS_RRTYPE_A, NULL, NULL, &transaction_id, callbackfn), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_general()"); RUN_EVENT_LOOP; CONTEXT_DESTROY; diff --git a/src/test/check_getdns_general_sync.h b/src/test/check_getdns_general_sync.h index 21d98988..f56df85e 100644 --- a/src/test/check_getdns_general_sync.h +++ b/src/test/check_getdns_general_sync.h @@ -27,7 +27,7 @@ { /* * name = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_context *context = NULL; struct getdns_dict *response = NULL; @@ -35,7 +35,7 @@ CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, NULL, GETDNS_RRTYPE_A, NULL, &response), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_general_sync()"); CONTEXT_DESTROY; } @@ -83,14 +83,14 @@ { /* * response = NULL - * expect: GETDNS_RETURN_GENERIC_ERROR + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_context *context = NULL; CONTEXT_CREATE(TRUE); ASSERT_RC(getdns_general_sync(context, "google.com", GETDNS_RRTYPE_A, NULL, NULL), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_general_sync()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_general_sync()"); CONTEXT_DESTROY; } diff --git a/src/test/check_getdns_list_get_data_type.h b/src/test/check_getdns_list_get_data_type.h index 874e6e34..eb968533 100644 --- a/src/test/check_getdns_list_get_data_type.h +++ b/src/test/check_getdns_list_get_data_type.h @@ -13,14 +13,14 @@ { /* * list = NULL - * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_list *list = NULL; size_t index = 0; getdns_data_type answer; ASSERT_RC(getdns_list_get_data_type(list, index, &answer), - GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_data_type()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_list_get_data_type()"); } END_TEST diff --git a/src/test/check_getdns_list_get_length.h b/src/test/check_getdns_list_get_length.h index f43b980c..9c71c2c4 100644 --- a/src/test/check_getdns_list_get_length.h +++ b/src/test/check_getdns_list_get_length.h @@ -13,13 +13,13 @@ { /* * list = NULL - * expect = GETDNS_RETURN_NO_SUCH_LIST_ITEM + * expect = GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_list *list = NULL; size_t length; ASSERT_RC(getdns_list_get_length(list, &length), - GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_length()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_list_get_length()"); } END_TEST @@ -28,14 +28,14 @@ { /* * answer = NULL - * expect: GETDNS_RETURN_NO_SUCH_LIST_ITEM + * expect: GETDNS_RETURN_INVALID_PARAMETER */ struct getdns_list *list = NULL; LIST_CREATE(list); ASSERT_RC(getdns_list_get_length(list, NULL), - GETDNS_RETURN_NO_SUCH_LIST_ITEM, "Return code from getdns_list_get_length()"); + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_list_get_length()"); LIST_DESTROY(list); } From 8782569d45cc755224505e266d7df6ccb7872496 Mon Sep 17 00:00:00 2001 From: Atlas config user Date: Mon, 13 Jan 2014 21:25:10 +0000 Subject: [PATCH 34/35] final convert_alabel_to_ulabel.h convert_ulabel_to_alabel.h --- src/test/check_getdns.c | 6 ++--- .../check_getdns_convert_alabel_to_ulabel.h | 24 +++++++++++-------- .../check_getdns_convert_ulabel_to_alabel.h | 19 ++++++++------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index cdf2890d..8a5bb315 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -28,7 +28,7 @@ #include "check_getdns_dict_set_bindata.h" #include "check_getdns_dict_set_int.h" #include "check_getdns_convert_ulabel_to_alabel.h" -//#include "check_getdns_convert_alabel_to_ulabel.h" +#include "check_getdns_convert_alabel_to_ulabel.h" int main (void) @@ -56,7 +56,7 @@ main (void) Suite *getdns_dict_set_bindata_suite(void); Suite *getdns_dict_set_int_suite(void); Suite *getdns_convert_ulabel_to_alabel_suite(void); - //Suite *getdns_convert_alabel_to_ulabel_suite(void); + Suite *getdns_convert_alabel_to_ulabel_suite(void); sr = srunner_create(getdns_general_suite()); srunner_add_suite(sr, getdns_general_sync_suite()); @@ -78,7 +78,7 @@ main (void) srunner_add_suite(sr, getdns_dict_set_bindata_suite()); srunner_add_suite(sr, getdns_dict_set_int_suite()); srunner_add_suite(sr, getdns_convert_ulabel_to_alabel_suite()); - //srunner_add_suite(sr, getdns_convert_alabel_to_ulabel_suite()); + srunner_add_suite(sr, getdns_convert_alabel_to_ulabel_suite()); srunner_set_log(sr, "check_getdns.log"); srunner_run_all(sr, CK_NORMAL); diff --git a/src/test/check_getdns_convert_alabel_to_ulabel.h b/src/test/check_getdns_convert_alabel_to_ulabel.h index d1884193..060d545b 100644 --- a/src/test/check_getdns_convert_alabel_to_ulabel.h +++ b/src/test/check_getdns_convert_alabel_to_ulabel.h @@ -12,13 +12,14 @@ START_TEST (getdns_convert_alabel_to_ulabel_1) { /* - * ulabel = NULL + * alabel = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - char alabel = NULL; + char *alabel = NULL; + + ck_assert_msg(strcmp( getdns_convert_alabel_to_ulabel( alabel ), "nil" ) == 0, + "Was not expecting %s from getdns_convert_alabel_to_ulabel()", getdns_convert_alabel_to_ulabel( alabel ) ); - ASSERT_RC(getdns_convert_alabel_to_ulabel( *alabel ), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); } END_TEST @@ -28,10 +29,12 @@ * alabel = invalid characters * expect: GETDNS_RETURN_GENERIC_ERROR */ - char alabel = "#$%_"; + char *alabel = "#$%_"; + + ck_assert_msg(strcmp( getdns_convert_alabel_to_ulabel( alabel ), "#$%_" ) == 0, + "Was not expecting %s from getdns_convert_alabel_to_ulabel()", getdns_convert_alabel_to_ulabel( alabel ) ); + - ASSERT_RC(getdns_convert_alabel_to_ulabel( *alabel ), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_alabel_to_ulabel()"); } END_TEST @@ -41,10 +44,11 @@ * alabel = valid characters (ace must begin with prefix "xn--" and be followed by a valid puny algorithm output; length limited to 59 chars) * expect: GETDNS_RETURN_GOOD */ - char alabel = "xn--caf-dma"; + char *alabel = "xn--caf-dma"; + + ck_assert_msg(strcmp( getdns_convert_alabel_to_ulabel( alabel ), "café" ) == 0, + "Was not expecting %s from getdns_convert_alabel_to_ulabel()", getdns_convert_alabel_to_ulabel( alabel ) ); - ASSERT_RC(getdns_convert_alabel_to_ulabel( *alabel ), - GETDNS_RETURN_GOOD, "Return code from getdns_convert_alabel_to_ulabel()"); } END_TEST diff --git a/src/test/check_getdns_convert_ulabel_to_alabel.h b/src/test/check_getdns_convert_ulabel_to_alabel.h index dc20ffc4..06ab19ae 100644 --- a/src/test/check_getdns_convert_ulabel_to_alabel.h +++ b/src/test/check_getdns_convert_ulabel_to_alabel.h @@ -15,10 +15,10 @@ * ulabel = NULL * expect: GETDNS_RETURN_GENERIC_ERROR */ - char ulabel = NULL; + char *ulabel = NULL; - ASSERT_RC(getdns_convert_ulabel_to_alabel( *ulabel ), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_ulabel_to_alabel()"); + ck_assert_msg(strcmp( getdns_convert_ulabel_to_alabel( ulabel ), "nil" ) == 0, + "Was not expecting %s from getdns_convert_ulabel_to_alabel()", getdns_convert_ulabel_to_alabel( ulabel ) ); } END_TEST @@ -28,10 +28,10 @@ * ulabel = invalid characters * expect: GETDNS_RETURN_GENERIC_ERROR */ - char ulabel = "#$%_"; + char *ulabel = "#$%_"; - ASSERT_RC(getdns_convert_ulabel_to_alabel( *ulabel ), - GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_convert_ulabel_to_alabel()"); + ck_assert_msg(strcmp( getdns_convert_ulabel_to_alabel( ulabel ), "#$%_" ) == 0, + "Was not expecting %s from getdns_convert_ulabel_to_alabel()", getdns_convert_ulabel_to_alabel( ulabel ) ); } END_TEST @@ -41,10 +41,11 @@ * ulabel = valid characters ( _abc, -abc, -abc-, abc- and limited to 63 octets ) * expect: GETDNS_RETURN_GOOD */ - char ulabel = "café"; + char *ulabel = "café"; + + ck_assert_msg(strcmp( getdns_convert_ulabel_to_alabel( ulabel ), "xn--caf-dma" ) == 0, + "Was not expecting %s from getdns_convert_ulabel_to_alabel()", getdns_convert_ulabel_to_alabel( ulabel ) ); - ASSERT_RC(getdns_convert_ulabel_to_alabel( *ulabel ), - GETDNS_RETURN_GOOD, "Return code from getdns_convert_ulabel_to_alabel()"); } END_TEST From 6e296cea7f4c9a0c11b815dac01c9900c44d1b5e Mon Sep 17 00:00:00 2001 From: Bryan Graham Date: Wed, 15 Jan 2014 11:45:41 -0500 Subject: [PATCH 35/35] initial check_getdns_testcases.doc upload --- doc/check_getdns_testcases.doc | Bin 0 -> 125451 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/check_getdns_testcases.doc diff --git a/doc/check_getdns_testcases.doc b/doc/check_getdns_testcases.doc new file mode 100644 index 0000000000000000000000000000000000000000..12d277f5629ae1b06849ce9aafa1b2a7a6ee405f GIT binary patch literal 125451 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

SzN6#l~{7%>d90UFps$G5*wijvBh(OOP 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

M%a+?G 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 VN$oOYj2L8w0s=)Z0P`H^{{X?rd!qmV literal 0 HcmV?d00001