Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Functions | Variables
test_dns.c File Reference
#include "asterisk.h"
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include "asterisk/test.h"
#include "asterisk/module.h"
#include "asterisk/dns_core.h"
#include "asterisk/dns_resolver.h"
#include "asterisk/dns_internal.h"
Include dependency graph for test_dns.c:

Go to the source code of this file.

Data Structures

struct  async_resolution_data
 Data used by async result callback. More...
 
struct  resolver_data
 File-scoped data used during resolver tests. More...
 

Macros

#define DNS_ANSWER   "Grumble Grumble"
 
#define DNS_ANSWER_SIZE   strlen(DNS_ANSWER)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (resolver_add_record)
 
 AST_TEST_DEFINE (resolver_add_record_off_nominal)
 
 AST_TEST_DEFINE (resolver_data)
 
 AST_TEST_DEFINE (resolver_register_off_nominal)
 
 AST_TEST_DEFINE (resolver_register_unregister)
 
 AST_TEST_DEFINE (resolver_resolve_async)
 
 AST_TEST_DEFINE (resolver_resolve_async_cancel)
 
 AST_TEST_DEFINE (resolver_resolve_async_off_nominal)
 
 AST_TEST_DEFINE (resolver_resolve_sync)
 
 AST_TEST_DEFINE (resolver_resolve_sync_off_nominal)
 
 AST_TEST_DEFINE (resolver_set_result)
 
 AST_TEST_DEFINE (resolver_set_result_off_nominal)
 
 AST_TEST_DEFINE (resolver_unregister_off_nominal)
 
static void async_callback (const struct ast_dns_query *query)
 Async DNS callback. More...
 
static struct async_resolution_dataasync_data_alloc (void)
 Allocation/initialization for async_resolution_data. More...
 
static void async_data_destructor (void *obj)
 Destructor for async_resolution_data. More...
 
static int fail_resolve (struct ast_dns_query *query)
 A resolve() method that simply fails. More...
 
static int load_module (void)
 
static void * resolution_thread (void *dns_query)
 Thread spawned by the mock resolver. More...
 
static void resolver_data_cleanup (void)
 Cleanup global mock resolver data. More...
 
static void resolver_data_init (void)
 Initialize global mock resolver data. More...
 
static void stub_callback (const struct ast_dns_query *query)
 
static int stub_cancel (struct ast_dns_query *query)
 
static int stub_resolve (struct ast_dns_query *query)
 
static int test_cancel (struct ast_dns_query *query)
 Mock resolver's cancel method. More...
 
static int test_record (struct ast_test *test, const struct ast_dns_record *record, int rr_type, int rr_class, int ttl, const char *data, const size_t size)
 
static int test_resolve (struct ast_dns_query *query)
 Mock resolver's resolve method. More...
 
static int test_results (struct ast_test *test, const struct ast_dns_query *query, unsigned int expected_secure, unsigned int expected_bogus, unsigned int expected_rcode, const char *expected_canonical, const char *expected_answer, size_t answer_size)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "DNS API Tests" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_dns_resolver test_resolver
 The mock resolver. More...
 
static struct resolver_data test_resolver_data
 

Macro Definition Documentation

◆ DNS_ANSWER

#define DNS_ANSWER   "Grumble Grumble"

Definition at line 294 of file test_dns.c.

◆ DNS_ANSWER_SIZE

#define DNS_ANSWER_SIZE   strlen(DNS_ANSWER)

Definition at line 295 of file test_dns.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1337 of file test_dns.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1337 of file test_dns.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1337 of file test_dns.c.

◆ AST_TEST_DEFINE() [1/13]

AST_TEST_DEFINE ( resolver_add_record  )

Definition at line 421 of file test_dns.c.

422{
424 struct ast_dns_query some_query;
425 const struct ast_dns_record *record;
426
427 static const char *V4 = "127.0.0.1";
428 static const size_t V4_BUFSIZE = sizeof(struct in_addr);
429 char v4_buf[V4_BUFSIZE];
430
431 static const char *V6 = "::1";
432 static const size_t V6_BUFSIZE = sizeof(struct in6_addr);
433 char v6_buf[V6_BUFSIZE];
434
435 struct dns_record_details {
436 int type;
437 int class;
438 int ttl;
439 const char *data;
440 const size_t size;
441 int visited;
442 } records[] = {
443 { T_A, C_IN, 12345, v4_buf, V4_BUFSIZE, 0, },
444 { T_AAAA, C_IN, 12345, v6_buf, V6_BUFSIZE, 0, },
445 };
446
447 int num_records_visited = 0;
448
449 switch (cmd) {
450 case TEST_INIT:
451 info->name = "resolver_add_record";
452 info->category = "/main/dns/";
453 info->summary = "Test adding DNS records to a query";
454 info->description =
455 "This test performs the following:\n"
456 "\t* Ensure a nominal A record can be added to a query result\n"
457 "\t* Ensures that the record can be retrieved\n"
458 "\t* Ensure that a second record can be added to the query result\n"
459 "\t* Ensures that both records can be retrieved";
460 return AST_TEST_NOT_RUN;
461 case TEST_EXECUTE:
462 break;
463 }
464
465 memset(&some_query, 0, sizeof(some_query));
466
467 if (ast_dns_resolver_set_result(&some_query, 0, 0, NOERROR, "asterisk.org",
469 ast_test_status_update(test, "Unable to set result for DNS query\n");
470 return AST_TEST_FAIL;
471 }
472
473 result = ast_dns_query_get_result(&some_query);
474 if (!result) {
475 ast_test_status_update(test, "Unable to retrieve result from query\n");
476 return AST_TEST_FAIL;
477 }
478
479 inet_pton(AF_INET, V4, v4_buf);
480
481 /* Nominal Record */
482 if (ast_dns_resolver_add_record(&some_query, records[0].type, records[0].class,
483 records[0].ttl, records[0].data, records[0].size)) {
484 ast_test_status_update(test, "Unable to add nominal record to query result\n");
485 return AST_TEST_FAIL;
486 }
487
488 /* I should only be able to retrieve one record */
490 if (!record) {
491 ast_test_status_update(test, "Unable to retrieve record from result\n");
492 return AST_TEST_FAIL;
493 }
494
495 if (test_record(test, record, records[0].type, records[0].class, records[0].ttl,
496 records[0].data, records[0].size)) {
497 return AST_TEST_FAIL;
498 }
499
500 if (ast_dns_record_get_next(record)) {
501 ast_test_status_update(test, "Multiple records returned when only one was expected\n");
502 return AST_TEST_FAIL;
503 }
504
505 inet_pton(AF_INET6, V6, v6_buf);
506
507 if (ast_dns_resolver_add_record(&some_query, records[1].type, records[1].class,
508 records[1].ttl, records[1].data, records[1].size)) {
509 ast_test_status_update(test, "Unable to add second record to query result\n");
510 return AST_TEST_FAIL;
511 }
512
513 for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
514 int res;
515
516 /* The order of returned records is not specified by the API. We use the record type
517 * as the discriminator to determine which record data to expect.
518 */
519 if (ast_dns_record_get_rr_type(record) == records[0].type) {
520 res = test_record(test, record, records[0].type, records[0].class, records[0].ttl, records[0].data, records[0].size);
521 records[0].visited = 1;
522 } else if (ast_dns_record_get_rr_type(record) == records[1].type) {
523 res = test_record(test, record, records[1].type, records[1].class, records[1].ttl, records[1].data, records[1].size);
524 records[1].visited = 1;
525 } else {
526 ast_test_status_update(test, "Unknown record type found in DNS results\n");
527 return AST_TEST_FAIL;
528 }
529
530 if (res) {
531 return AST_TEST_FAIL;
532 }
533
534 ++num_records_visited;
535 }
536
537 if (!records[0].visited || !records[1].visited) {
538 ast_test_status_update(test, "Did not visit all added DNS records\n");
539 return AST_TEST_FAIL;
540 }
541
542 if (num_records_visited != ARRAY_LEN(records)) {
543 ast_test_status_update(test, "Did not visit the expected number of DNS records\n");
544 return AST_TEST_FAIL;
545 }
546
547 return AST_TEST_PASS;
548}
static int records
Definition: cdr_pgsql.c:78
static PGresult * result
Definition: cel_pgsql.c:84
static const char type[]
Definition: chan_ooh323.c:109
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
Definition: dns_core.c:170
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
Definition: dns_core.c:102
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
Definition: dns_core.c:77
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
Definition: dns_core.c:145
int ast_dns_resolver_set_result(struct ast_dns_query *query, unsigned int secure, unsigned int bogus, unsigned int rcode, const char *canonical, const char *answer, size_t answer_size)
Set result information for a DNS query.
Definition: dns_core.c:456
int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, const char *data, const size_t size)
Add a DNS record to the result of a DNS query.
Definition: dns_core.c:535
def info(msg)
#define NULL
Definition: resample.c:96
A DNS query.
Definition: dns_internal.h:137
For AST_LIST.
Definition: dns_internal.h:39
The result of a DNS query.
Definition: dns_internal.h:117
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
#define DNS_ANSWER_SIZE
Definition: test_dns.c:295
static int test_record(struct ast_test *test, const struct ast_dns_record *record, int rr_type, int rr_class, int ttl, const char *data, const size_t size)
Definition: test_dns.c:395
#define DNS_ANSWER
Definition: test_dns.c:294
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_dns_query_get_result(), ast_dns_record_get_next(), ast_dns_record_get_rr_type(), ast_dns_resolver_add_record(), ast_dns_resolver_set_result(), ast_dns_result_free(), ast_dns_result_get_records(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, DNS_ANSWER, DNS_ANSWER_SIZE, sip_to_pjsip::info(), NULL, RAII_VAR, records, result, TEST_EXECUTE, TEST_INIT, test_record(), and type.

◆ AST_TEST_DEFINE() [2/13]

AST_TEST_DEFINE ( resolver_add_record_off_nominal  )

Definition at line 550 of file test_dns.c.

551{
553 struct ast_dns_query some_query;
554 static const char *V4 = "127.0.0.1";
555 static const size_t V4_BUFSIZE = sizeof(struct in_addr);
556 char v4_buf[V4_BUFSIZE];
557
558 switch (cmd) {
559 case TEST_INIT:
560 info->name = "resolver_add_record_off_nominal";
561 info->category = "/main/dns/";
562 info->summary = "Test adding off-nominal DNS records to a query";
563 info->description =
564 "This test performs the following:\n"
565 "\t* Ensure a nominal A record cannot be added if no result has been set.\n"
566 "\t* Ensure that an A record with invalid RR types cannot be added to a query\n"
567 "\t* Ensure that an A record with invalid RR classes cannot be added to a query\n"
568 "\t* Ensure that an A record with invalid TTL cannot be added to a query\n"
569 "\t* Ensure that an A record with NULL data cannot be added to a query\n"
570 "\t* Ensure that an A record with invalid length cannot be added to a query";
571 return AST_TEST_NOT_RUN;
572 case TEST_EXECUTE:
573 break;
574 }
575
576 memset(&some_query, 0, sizeof(some_query));
577
578 inet_ntop(AF_INET, V4, v4_buf, V4_BUFSIZE);
579
580 /* Add record before setting result */
581 if (!ast_dns_resolver_add_record(&some_query, T_A, C_IN, 12345, v4_buf, V4_BUFSIZE)) {
582 ast_test_status_update(test, "Successfully added DNS record to query before setting a result\n");
583 return AST_TEST_FAIL;
584 }
585
586 if (ast_dns_resolver_set_result(&some_query, 0, 0, NOERROR, "asterisk.org",
588 ast_test_status_update(test, "Unable to set result for DNS query\n");
589 return AST_TEST_FAIL;
590 }
591
592 /* We get the result so it will be cleaned up when the function exits */
593 result = ast_dns_query_get_result(&some_query);
594
595 /* Invalid RR types */
596 if (!ast_dns_resolver_add_record(&some_query, -1, C_IN, 12345, v4_buf, V4_BUFSIZE)) {
597 ast_test_status_update(test, "Successfully added DNS record with negative RR type\n");
598 return AST_TEST_FAIL;
599 }
600
601 if (!ast_dns_resolver_add_record(&some_query, 65536 + 1, C_IN, 12345, v4_buf, V4_BUFSIZE)) {
602 ast_test_status_update(test, "Successfully added DNS record with too large RR type\n");
603 return AST_TEST_FAIL;
604 }
605
606 /* Invalid RR classes */
607 if (!ast_dns_resolver_add_record(&some_query, T_A, -1, 12345, v4_buf, V4_BUFSIZE)) {
608 ast_test_status_update(test, "Successfully added DNS record with negative RR class\n");
609 return AST_TEST_FAIL;
610 }
611
612 if (!ast_dns_resolver_add_record(&some_query, T_A, 65536 + 1, 12345, v4_buf, V4_BUFSIZE)) {
613 ast_test_status_update(test, "Successfully added DNS record with too large RR class\n");
614 return AST_TEST_FAIL;
615 }
616
617 /* Invalid TTL */
618 if (!ast_dns_resolver_add_record(&some_query, T_A, C_IN, -1, v4_buf, V4_BUFSIZE)) {
619 ast_test_status_update(test, "Successfully added DNS record with negative TTL\n");
620 return AST_TEST_FAIL;
621 }
622
623 /* No data */
624 if (!ast_dns_resolver_add_record(&some_query, T_A, C_IN, 12345, NULL, 0)) {
625 ast_test_status_update(test, "Successfully added a DNS record with no data\n");
626 return AST_TEST_FAIL;
627 }
628
629 /* Lie about the length */
630 if (!ast_dns_resolver_add_record(&some_query, T_A, C_IN, 12345, v4_buf, 0)) {
631 ast_test_status_update(test, "Successfully added a DNS record with length zero\n");
632 return AST_TEST_FAIL;
633 }
634
635 return AST_TEST_PASS;
636}

References ast_dns_query_get_result(), ast_dns_resolver_add_record(), ast_dns_resolver_set_result(), ast_dns_result_free(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, DNS_ANSWER, DNS_ANSWER_SIZE, sip_to_pjsip::info(), NULL, RAII_VAR, result, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [3/13]

AST_TEST_DEFINE ( resolver_data  )

Definition at line 189 of file test_dns.c.

190{
191 struct ast_dns_query some_query;
192
193 struct digits {
194 int fingers;
195 int toes;
196 };
197
198 RAII_VAR(struct digits *, average, NULL, ao2_cleanup);
199 RAII_VAR(struct digits *, polydactyl, NULL, ao2_cleanup);
200
201 struct digits *data_ptr;
202
203 switch (cmd) {
204 case TEST_INIT:
205 info->name = "resolver_data";
206 info->category = "/main/dns/";
207 info->summary = "Test getting and setting data on a DNS resolver";
208 info->description = "This test does the following:\n"
209 "\t* Ensure that requesting resolver data results in a NULL return if no data has been set.\n"
210 "\t* Ensure that setting resolver data does not result in an error.\n"
211 "\t* Ensure that retrieving the set resolver data returns the data we expect\n"
212 "\t* Ensure that setting new resolver data on the query does not result in an error\n"
213 "\t* Ensure that retrieving the resolver data returns the new data that we set";
214 return AST_TEST_NOT_RUN;
215 case TEST_EXECUTE:
216 break;
217 }
218
219 memset(&some_query, 0, sizeof(some_query));
220
221 average = ao2_alloc(sizeof(*average), NULL);
222 polydactyl = ao2_alloc(sizeof(*average), NULL);
223
224 if (!average || !polydactyl) {
225 ast_test_status_update(test, "Allocation failure during unit test\n");
226 return AST_TEST_FAIL;
227 }
228
229 /* Ensure that NULL is retrieved if we haven't set anything on the query */
230 data_ptr = ast_dns_resolver_get_data(&some_query);
231 if (data_ptr) {
232 ast_test_status_update(test, "Retrieved non-NULL resolver data from query unexpectedly\n");
233 return AST_TEST_FAIL;
234 }
235
236 if (ast_dns_resolver_set_data(&some_query, average)) {
237 ast_test_status_update(test, "Failed to set resolver data on query\n");
238 return AST_TEST_FAIL;
239 }
240
241 /* Go ahead now and remove the query's reference to the resolver data to prevent memory leaks */
242 ao2_ref(average, -1);
243
244 /* Ensure that data can be set and retrieved */
245 data_ptr = ast_dns_resolver_get_data(&some_query);
246 if (!data_ptr) {
247 ast_test_status_update(test, "Unable to retrieve resolver data from DNS query\n");
248 return AST_TEST_FAIL;
249 }
250
251 if (data_ptr != average) {
252 ast_test_status_update(test, "Unexpected resolver data retrieved from DNS query\n");
253 return AST_TEST_FAIL;
254 }
255
256 /* Ensure that attempting to set new resolver data on the query fails */
257 if (!ast_dns_resolver_set_data(&some_query, polydactyl)) {
258 ast_test_status_update(test, "Successfully overwrote resolver data on a query. We shouldn't be able to do that\n");
259 return AST_TEST_FAIL;
260 }
261
262 return AST_TEST_PASS;
263}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
Definition: dns_core.c:440
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
Definition: dns_core.c:451

References ao2_alloc, ao2_cleanup, ao2_ref, ast_dns_resolver_get_data(), ast_dns_resolver_set_data(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), NULL, RAII_VAR, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [4/13]

AST_TEST_DEFINE ( resolver_register_off_nominal  )

Definition at line 81 of file test_dns.c.

82{
83 struct ast_dns_resolver valid = {
84 .name = "valid",
85 .resolve = stub_resolve,
86 .cancel = stub_cancel,
87 };
88
89 struct ast_dns_resolver incomplete1 = {
90 .name = NULL,
91 .resolve = stub_resolve,
92 .cancel = stub_cancel,
93 };
94
95 struct ast_dns_resolver incomplete2 = {
96 .name = "incomplete2",
97 .resolve = NULL,
98 .cancel = stub_cancel,
99 };
100
101 struct ast_dns_resolver incomplete3 = {
102 .name = "incomplete3",
103 .resolve = stub_resolve,
104 .cancel = NULL,
105 };
106
107 switch (cmd) {
108 case TEST_INIT:
109 info->name = "resolver_register_off_nominal";
110 info->category = "/main/dns/";
111 info->summary = "Test off-nominal resolver registration";
112 info->description =
113 "Test off-nominal resolver registration:\n"
114 "\t* Register a duplicate resolver\n"
115 "\t* Register a resolver without a name\n"
116 "\t* Register a resolver without a resolve() method\n"
117 "\t* Register a resolver without a cancel() method";
118 return AST_TEST_NOT_RUN;
119 case TEST_EXECUTE:
120 break;
121 }
122
123 if (ast_dns_resolver_register(&valid)) {
124 ast_test_status_update(test, "Failed to register valid resolver\n");
125 return AST_TEST_FAIL;
126 }
127
128 if (!ast_dns_resolver_register(&valid)) {
129 ast_test_status_update(test, "Successfully registered the same resolver multiple times\n");
130 return AST_TEST_FAIL;
131 }
132
134
136 ast_test_status_update(test, "Successfully registered a NULL resolver\n");
137 return AST_TEST_FAIL;
138 }
139
140 if (!ast_dns_resolver_register(&incomplete1)) {
141 ast_test_status_update(test, "Successfully registered a DNS resolver with no name\n");
142 return AST_TEST_FAIL;
143 }
144
145 if (!ast_dns_resolver_register(&incomplete2)) {
146 ast_test_status_update(test, "Successfully registered a DNS resolver with no resolve() method\n");
147 return AST_TEST_FAIL;
148 }
149
150 if (!ast_dns_resolver_register(&incomplete3)) {
151 ast_test_status_update(test, "Successfully registered a DNS resolver with no cancel() method\n");
152 return AST_TEST_FAIL;
153 }
154
155 return AST_TEST_PASS;
156}
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
DNS resolver implementation.
Definition: dns_resolver.h:32
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
static int stub_resolve(struct ast_dns_query *query)
Definition: test_dns.c:36
static int stub_cancel(struct ast_dns_query *query)
Definition: test_dns.c:42

References ast_dns_resolver_register(), ast_dns_resolver_unregister(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), ast_dns_resolver::name, NULL, stub_cancel(), stub_resolve(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [5/13]

AST_TEST_DEFINE ( resolver_register_unregister  )

Definition at line 47 of file test_dns.c.

48{
49 struct ast_dns_resolver cool_guy_resolver = {
50 .name = "A snake that swallowed a deer",
51 .priority = 19890504,
52 .resolve = stub_resolve,
53 .cancel = stub_cancel,
54 };
55
56 switch (cmd) {
57 case TEST_INIT:
58 info->name = "resolver_register_unregister";
59 info->category = "/main/dns/";
60 info->summary = "Test nominal resolver registration and unregistration";
61 info->description =
62 "The test performs the following steps:\n"
63 "\t* Register a valid resolver.\n"
64 "\t* Unregister the resolver.\n"
65 "If either step fails, the test fails";
66 return AST_TEST_NOT_RUN;
67 case TEST_EXECUTE:
68 break;
69 }
70
71 if (ast_dns_resolver_register(&cool_guy_resolver)) {
72 ast_test_status_update(test, "Unable to register a perfectly good resolver\n");
73 return AST_TEST_FAIL;
74 }
75
76 ast_dns_resolver_unregister(&cool_guy_resolver);
77
78 return AST_TEST_PASS;
79}

References ast_dns_resolver_register(), ast_dns_resolver_unregister(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), ast_dns_resolver::name, stub_cancel(), stub_resolve(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [6/13]

AST_TEST_DEFINE ( resolver_resolve_async  )

Definition at line 1018 of file test_dns.c.

1019{
1020 RAII_VAR(struct async_resolution_data *, async_data, NULL, ao2_cleanup);
1021 RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup);
1022 struct ast_dns_result *result;
1024 struct timespec timeout;
1025
1026 switch (cmd) {
1027 case TEST_INIT:
1028 info->name = "resolver_resolve_async";
1029 info->category = "/main/dns/";
1030 info->summary = "Test a nominal asynchronous DNS resolution";
1031 info->description =
1032 "This test performs an asynchronous DNS resolution of a domain. The goal of this\n"
1033 "test is not to check the records for accuracy. Rather, the goal is to ensure that\n"
1034 "the resolver is called into as expected, that we regain control before the query\n"
1035 "is completed, and to ensure that nothing tried to cancel the resolution.";
1036 return AST_TEST_NOT_RUN;
1037 case TEST_EXECUTE:
1038 break;
1039 }
1040
1042 ast_test_status_update(test, "Unable to register test resolver\n");
1043 return AST_TEST_FAIL;
1044 }
1045
1047
1048 async_data = async_data_alloc();
1049 if (!async_data) {
1050 ast_test_status_update(test, "Failed to allocate asynchronous data\n");
1051 res = AST_TEST_FAIL;
1052 goto cleanup;
1053 }
1054
1055 active = ast_dns_resolve_async("asterisk.org", T_A, C_IN, async_callback, async_data);
1056 if (!active) {
1057 ast_test_status_update(test, "Asynchronous resolution of address failed\n");
1058 res = AST_TEST_FAIL;
1059 goto cleanup;
1060 }
1061
1063 ast_test_status_update(test, "DNS resolution did not call resolver's resolve() method\n");
1064 res = AST_TEST_FAIL;
1065 goto cleanup;
1066 }
1067
1069 ast_test_status_update(test, "Resolver's cancel() method called for no reason\n");
1070 res = AST_TEST_FAIL;
1071 goto cleanup;
1072 }
1073
1074 timeout = ast_tsnow();
1075 timeout.tv_sec += 10;
1076 ast_mutex_lock(&async_data->lock);
1077 while (!async_data->complete) {
1078 if (ast_cond_timedwait(&async_data->cond, &async_data->lock, &timeout) == ETIMEDOUT) {
1079 break;
1080 }
1081 }
1082 ast_mutex_unlock(&async_data->lock);
1083
1084 if (!async_data->complete) {
1085 ast_test_status_update(test, "Asynchronous resolution timed out\n");
1086 res = AST_TEST_FAIL;
1087 goto cleanup;
1088 }
1089
1091 ast_test_status_update(test, "Asynchronous resolution completed early?\n");
1092 res = AST_TEST_FAIL;
1093 goto cleanup;
1094 }
1095
1096 result = ast_dns_query_get_result(active->query);
1097 if (!result) {
1098 ast_test_status_update(test, "Asynchronous resolution yielded no result\n");
1099 res = AST_TEST_FAIL;
1100 goto cleanup;
1101 }
1102
1104 ast_test_status_update(test, "Asynchronous result had no records\n");
1105 res = AST_TEST_FAIL;
1106 goto cleanup;
1107 }
1108
1109cleanup:
1112 return res;
1113}
struct ast_dns_query_active * ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query.
Definition: dns_core.c:247
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
An active DNS query.
Definition: dns_internal.h:201
Data used by async result callback.
Definition: test_dns.c:957
int resolution_complete
Definition: test_dns.c:650
int resolve_called
Definition: test_dns.c:646
ast_test_result_state
Definition: test.h:193
static struct async_resolution_data * async_data_alloc(void)
Allocation/initialization for async_resolution_data.
Definition: test_dns.c:983
static struct ast_dns_resolver test_resolver
The mock resolver.
Definition: test_dns.c:774
static void resolver_data_cleanup(void)
Cleanup global mock resolver data.
Definition: test_dns.c:761
static struct resolver_data test_resolver_data
static void resolver_data_init(void)
Initialize global mock resolver data.
Definition: test_dns.c:746
static void async_callback(const struct ast_dns_query *query)
Async DNS callback.
Definition: test_dns.c:1008
struct timespec ast_tsnow(void)
Returns current timespec. Meant to avoid calling ast_tvnow() just to create a timespec from the timev...
Definition: time.h:186

References ao2_cleanup, ast_cond_timedwait, ast_dns_query_get_result(), ast_dns_resolve_async(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_dns_result_get_records(), ast_mutex_lock, ast_mutex_unlock, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_tsnow(), async_callback(), async_data_alloc(), resolver_data::canceled, cleanup(), sip_to_pjsip::info(), NULL, RAII_VAR, resolver_data::resolution_complete, resolver_data::resolve_called, resolver_data_cleanup(), resolver_data_init(), result, TEST_EXECUTE, TEST_INIT, test_resolver, and test_resolver_data.

◆ AST_TEST_DEFINE() [7/13]

AST_TEST_DEFINE ( resolver_resolve_async_cancel  )

Definition at line 1200 of file test_dns.c.

1201{
1202 RAII_VAR(struct async_resolution_data *, async_data, NULL, ao2_cleanup);
1203 RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup);
1204 struct ast_dns_result *result;
1206 struct timespec timeout;
1207
1208 switch (cmd) {
1209 case TEST_INIT:
1210 info->name = "resolver_resolve_async_cancel";
1211 info->category = "/main/dns/";
1212 info->summary = "Test canceling an asynchronous DNS resolution";
1213 info->description =
1214 "This test performs an asynchronous DNS resolution of a domain and then cancels\n"
1215 "the resolution. The goal of this test is to ensure that the cancel() callback of\n"
1216 "the resolver is called and that it properly interrupts the resolution such that no\n"
1217 "records are returned.";
1218 return AST_TEST_NOT_RUN;
1219 case TEST_EXECUTE:
1220 break;
1221 }
1222
1224 ast_test_status_update(test, "Unable to register test resolver\n");
1225 return AST_TEST_FAIL;
1226 }
1227
1229
1230 async_data = async_data_alloc();
1231 if (!async_data) {
1232 ast_test_status_update(test, "Failed to allocate asynchronous data\n");
1233 res = AST_TEST_FAIL;
1234 goto cleanup;
1235 }
1236
1237 active = ast_dns_resolve_async("asterisk.org", T_A, C_IN, async_callback, async_data);
1238 if (!active) {
1239 ast_test_status_update(test, "Asynchronous resolution of address failed\n");
1240 res = AST_TEST_FAIL;
1241 goto cleanup;
1242 }
1243
1245 ast_test_status_update(test, "DNS resolution did not call resolver's resolve() method\n");
1246 res = AST_TEST_FAIL;
1247 goto cleanup;
1248 }
1249
1251 ast_test_status_update(test, "Resolver's cancel() method called for no reason\n");
1252 res = AST_TEST_FAIL;
1253 goto cleanup;
1254 }
1255
1256 ast_dns_resolve_cancel(active);
1257
1259 ast_test_status_update(test, "Resolver's cancel() method was not called\n");
1260 res = AST_TEST_FAIL;
1261 goto cleanup;
1262 }
1263
1264 timeout = ast_tsnow();
1265 timeout.tv_sec += 10;
1266 ast_mutex_lock(&async_data->lock);
1267 while (!async_data->complete) {
1268 if (ast_cond_timedwait(&async_data->cond, &async_data->lock, &timeout) == ETIMEDOUT) {
1269 break;
1270 }
1271 }
1272 ast_mutex_unlock(&async_data->lock);
1273
1274 if (!async_data->complete) {
1275 ast_test_status_update(test, "Asynchronous resolution timed out\n");
1276 res = AST_TEST_FAIL;
1277 goto cleanup;
1278 }
1279
1281 ast_test_status_update(test, "Resolution completed without cancelation\n");
1282 res = AST_TEST_FAIL;
1283 goto cleanup;
1284 }
1285
1286 result = ast_dns_query_get_result(active->query);
1287 if (result) {
1288 ast_test_status_update(test, "Canceled resolution had a result\n");
1289 res = AST_TEST_FAIL;
1290 goto cleanup;
1291 }
1292
1293cleanup:
1296 return res;
1297}
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
Definition: dns_core.c:272

References ao2_cleanup, ast_cond_timedwait, ast_dns_query_get_result(), ast_dns_resolve_async(), ast_dns_resolve_cancel(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_tsnow(), async_callback(), async_data_alloc(), resolver_data::canceled, cleanup(), sip_to_pjsip::info(), NULL, RAII_VAR, resolver_data::resolution_complete, resolver_data::resolve_called, resolver_data_cleanup(), resolver_data_init(), result, TEST_EXECUTE, TEST_INIT, test_resolver, and test_resolver_data.

◆ AST_TEST_DEFINE() [8/13]

AST_TEST_DEFINE ( resolver_resolve_async_off_nominal  )

Definition at line 1121 of file test_dns.c.

1122{
1123 struct ast_dns_resolver terrible_resolver = {
1124 .name = "Ed Wood's Filmography",
1125 .priority = 0,
1126 .resolve = fail_resolve,
1127 .cancel = stub_cancel,
1128 };
1129
1130 struct dns_resolve_data {
1131 const char *name;
1132 int rr_type;
1133 int rr_class;
1134 ast_dns_resolve_callback callback;
1135 } resolves [] = {
1136 { NULL, T_A, C_IN, stub_callback },
1137 { "asterisk.org", -1, C_IN, stub_callback },
1138 { "asterisk.org", 65536 + 1, C_IN, stub_callback },
1139 { "asterisk.org", T_A, -1, stub_callback },
1140 { "asterisk.org", T_A, 65536 + 1, stub_callback },
1141 { "asterisk.org", T_A, C_IN, NULL },
1142 };
1143
1144 struct ast_dns_query_active *active;
1146 int i;
1147
1148 switch (cmd) {
1149 case TEST_INIT:
1150 info->name = "resolver_resolve_async_off_nominal";
1151 info->category = "/main/dns/";
1152 info->summary = "Test off-nominal asynchronous DNS resolution";
1153 info->description =
1154 "This test performs several off-nominal asynchronous DNS resolutions:\n"
1155 "\t* Attempt resolution with NULL name\n"
1156 "\t* Attempt resolution with invalid RR type\n"
1157 "\t* Attempt resolution with invalid RR class\n"
1158 "\t* Attempt resolution with NULL callback pointer\n"
1159 "\t* Attempt resolution with resolver that returns an error";
1160 return AST_TEST_NOT_RUN;
1161 case TEST_EXECUTE:
1162 break;
1163 }
1164
1166 ast_test_status_update(test, "Failed to register test resolver\n");
1167 return AST_TEST_FAIL;
1168 }
1169
1170 for (i = 0; i < ARRAY_LEN(resolves); ++i) {
1171 active = ast_dns_resolve_async(resolves[i].name, resolves[i].rr_type, resolves[i].rr_class,
1172 resolves[i].callback, NULL);
1173 if (active) {
1174 ast_test_status_update(test, "Successfully performed asynchronous resolution with invalid data\n");
1175 ao2_ref(active, -1);
1176 res = AST_TEST_FAIL;
1177 }
1178 }
1179
1181
1182 if (ast_dns_resolver_register(&terrible_resolver)) {
1183 ast_test_status_update(test, "Failed to register the DNS resolver\n");
1184 return AST_TEST_FAIL;
1185 }
1186
1187 active = ast_dns_resolve_async("asterisk.org", T_A, C_IN, stub_callback, NULL);
1188
1189 ast_dns_resolver_unregister(&terrible_resolver);
1190
1191 if (active) {
1192 ast_test_status_update(test, "Successfully performed asynchronous resolution with invalid data\n");
1193 ao2_ref(active, -1);
1194 return AST_TEST_FAIL;
1195 }
1196
1197 return res;
1198}
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition: dns_core.h:171
static const char name[]
Definition: format_mp3.c:68
static void stub_callback(const struct ast_dns_query *query)
Definition: test_dns.c:1116
static int fail_resolve(struct ast_dns_query *query)
A resolve() method that simply fails.
Definition: test_dns.c:857

References ao2_ref, ARRAY_LEN, ast_dns_resolve_async(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, fail_resolve(), sip_to_pjsip::info(), name, ast_dns_resolver::name, NULL, stub_callback(), stub_cancel(), TEST_EXECUTE, TEST_INIT, and test_resolver.

◆ AST_TEST_DEFINE() [9/13]

AST_TEST_DEFINE ( resolver_resolve_sync  )

Definition at line 781 of file test_dns.c.

782{
785
786 switch (cmd) {
787 case TEST_INIT:
788 info->name = "resolver_resolve_sync";
789 info->category = "/main/dns/";
790 info->summary = "Test a nominal synchronous DNS resolution";
791 info->description =
792 "This test performs a synchronous DNS resolution of a domain. The goal of this\n"
793 "test is not to check the records for accuracy. Rather, the goal is to ensure that\n"
794 "the resolver is called into as expected, that the query completes entirely before\n"
795 "returning from the synchronous resolution, that nothing tried to cancel the resolution\n,"
796 "and that some records were returned.";
797 return AST_TEST_NOT_RUN;
798 case TEST_EXECUTE:
799 break;
800 }
801
803 ast_test_status_update(test, "Unable to register test resolver\n");
804 return AST_TEST_FAIL;
805 }
806
808
809 if (ast_dns_resolve("asterisk.org", T_A, C_IN, &result)) {
810 ast_test_status_update(test, "Resolution of address failed\n");
811 res = AST_TEST_FAIL;
812 goto cleanup;
813 }
814
815 if (!result) {
816 ast_test_status_update(test, "DNS resolution returned a NULL result\n");
817 res = AST_TEST_FAIL;
818 goto cleanup;
819 }
820
822 ast_test_status_update(test, "DNS resolution did not call resolver's resolve() method\n");
823 res = AST_TEST_FAIL;
824 goto cleanup;
825 }
826
828 ast_test_status_update(test, "Resolver's cancel() method called for no reason\n");
829 res = AST_TEST_FAIL;
830 goto cleanup;
831 }
832
834 ast_test_status_update(test, "Synchronous resolution completed early?\n");
835 res = AST_TEST_FAIL;
836 goto cleanup;
837 }
838
840 ast_test_status_update(test, "Synchronous resolution yielded no records.\n");
841 res = AST_TEST_FAIL;
842 goto cleanup;
843 }
844
845cleanup:
848 return res;
849}
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
Definition: dns_core.c:314

References ast_dns_resolve(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_dns_result_free(), ast_dns_result_get_records(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, resolver_data::canceled, cleanup(), sip_to_pjsip::info(), NULL, RAII_VAR, resolver_data::resolution_complete, resolver_data::resolve_called, resolver_data_cleanup(), resolver_data_init(), result, TEST_EXECUTE, TEST_INIT, test_resolver, and test_resolver_data.

◆ AST_TEST_DEFINE() [10/13]

AST_TEST_DEFINE ( resolver_resolve_sync_off_nominal  )

Definition at line 862 of file test_dns.c.

863{
864 struct ast_dns_resolver terrible_resolver = {
865 .name = "Uwe Boll's Filmography",
866 .priority = 0,
867 .resolve = fail_resolve,
868 .cancel = stub_cancel,
869 };
870
871 struct ast_dns_result *result = NULL;
872
873 struct dns_resolve_data {
874 const char *name;
875 int rr_type;
876 int rr_class;
877 struct ast_dns_result **result;
878 } resolves [] = {
879 { NULL, T_A, C_IN, &result },
880 { "asterisk.org", -1, C_IN, &result },
881 { "asterisk.org", 65536 + 1, C_IN, &result },
882 { "asterisk.org", T_A, -1, &result },
883 { "asterisk.org", T_A, 65536 + 1, &result },
884 { "asterisk.org", T_A, C_IN, NULL },
885 };
886
887 int i;
888
890
891 switch (cmd) {
892 case TEST_INIT:
893 info->name = "resolver_resolve_sync_off_nominal";
894 info->category = "/main/dns/";
895 info->summary = "Test off-nominal synchronous DNS resolution";
896 info->description =
897 "This test performs several off-nominal synchronous DNS resolutions:\n"
898 "\t* Attempt resolution with NULL name\n"
899 "\t* Attempt resolution with invalid RR type\n"
900 "\t* Attempt resolution with invalid RR class\n"
901 "\t* Attempt resolution with NULL result pointer\n"
902 "\t* Attempt resolution with resolver that returns an error";
903 return AST_TEST_NOT_RUN;
904 case TEST_EXECUTE:
905 break;
906 }
907
909 ast_test_status_update(test, "Failed to register test resolver\n");
910 return AST_TEST_FAIL;
911 }
912
913 for (i = 0; i < ARRAY_LEN(resolves); ++i) {
914 if (!ast_dns_resolve(resolves[i].name, resolves[i].rr_type, resolves[i].rr_class, resolves[i].result)) {
915 ast_test_status_update(test, "Successfully resolved DNS query with invalid parameters\n");
916 res = AST_TEST_FAIL;
917 } else if (result) {
918 ast_test_status_update(test, "Failed resolution set a non-NULL result\n");
920 res = AST_TEST_FAIL;
921 }
922 }
923
925
926 /* As a final test, try a legitimate query with a bad resolver */
927 if (ast_dns_resolver_register(&terrible_resolver)) {
928 ast_test_status_update(test, "Failed to register the terrible resolver\n");
929 return AST_TEST_FAIL;
930 }
931
932 if (!ast_dns_resolve("asterisk.org", T_A, C_IN, &result)) {
933 ast_test_status_update(test, "DNS resolution succeeded when we expected it not to\n");
934 ast_dns_resolver_unregister(&terrible_resolver);
935 return AST_TEST_FAIL;
936 }
937
938 ast_dns_resolver_unregister(&terrible_resolver);
939
940 if (result) {
941 ast_test_status_update(test, "Failed DNS resolution set the result to something non-NULL\n");
943 return AST_TEST_FAIL;
944 }
945
946 return res;
947}

References ARRAY_LEN, ast_dns_resolve(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_dns_result_free(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, fail_resolve(), sip_to_pjsip::info(), name, ast_dns_resolver::name, NULL, result, stub_cancel(), TEST_EXECUTE, TEST_INIT, and test_resolver.

◆ AST_TEST_DEFINE() [11/13]

AST_TEST_DEFINE ( resolver_set_result  )

Definition at line 297 of file test_dns.c.

298{
299 struct ast_dns_query some_query;
300 struct ast_dns_result *result;
301
302 struct dns_result {
303 unsigned int secure;
304 unsigned int bogus;
305 unsigned int rcode;
306 } results[] = {
307 { 0, 0, NOERROR, },
308 { 0, 1, NOERROR, },
309 { 1, 0, NOERROR, },
310 { 0, 0, NXDOMAIN, },
311 };
312 int i;
314
315 switch (cmd) {
316 case TEST_INIT:
317 info->name = "resolver_set_result";
318 info->category = "/main/dns/";
319 info->summary = "Test setting and getting results on DNS queries";
320 info->description =
321 "This test performs the following:\n"
322 "\t* Sets a result that is not secure, bogus, and has rcode 0\n"
323 "\t* Sets a result that is not secure, has rcode 0, but is secure\n"
324 "\t* Sets a result that is not bogus, has rcode 0, but is secure\n"
325 "\t* Sets a result that is not secure or bogus, but has rcode NXDOMAIN\n"
326 "After each result is set, we ensure that parameters retrieved from\n"
327 "the result have the expected values.";
328 return AST_TEST_NOT_RUN;
329 case TEST_EXECUTE:
330 break;
331 }
332
333 memset(&some_query, 0, sizeof(some_query));
334
335 for (i = 0; i < ARRAY_LEN(results); ++i) {
336 if (ast_dns_resolver_set_result(&some_query, results[i].secure, results[i].bogus,
337 results[i].rcode, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE)) {
338 ast_test_status_update(test, "Unable to add DNS result to query\n");
339 res = AST_TEST_FAIL;
340 }
341
342 if (test_results(test, &some_query, results[i].secure, results[i].bogus,
343 results[i].rcode, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE)) {
344 res = AST_TEST_FAIL;
345 }
346 }
347
348 /* The final result we set needs to be freed */
349 result = ast_dns_query_get_result(&some_query);
351
352 return res;
353}
static int test_results(struct ast_test *test, const struct ast_dns_query *query, unsigned int expected_secure, unsigned int expected_bogus, unsigned int expected_rcode, const char *expected_canonical, const char *expected_answer, size_t answer_size)
Definition: test_dns.c:265

References ARRAY_LEN, ast_dns_query_get_result(), ast_dns_resolver_set_result(), ast_dns_result_free(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, DNS_ANSWER, DNS_ANSWER_SIZE, sip_to_pjsip::info(), result, TEST_EXECUTE, TEST_INIT, and test_results().

◆ AST_TEST_DEFINE() [12/13]

AST_TEST_DEFINE ( resolver_set_result_off_nominal  )

Definition at line 355 of file test_dns.c.

356{
357 struct ast_dns_query some_query;
358 struct ast_dns_result *result;
359
360 switch (cmd) {
361 case TEST_INIT:
362 info->name = "resolver_set_result_off_nominal";
363 info->category = "/main/dns/";
364 info->summary = "Test setting off-nominal DNS results";
365 info->description =
366 "This test performs the following:\n"
367 "\t* Attempt to add a DNS result that is both bogus and secure\n"
368 "\t* Attempt to add a DNS result that has no canonical name";
369 return AST_TEST_NOT_RUN;
370 case TEST_EXECUTE:
371 break;
372 }
373
374 memset(&some_query, 0, sizeof(some_query));
375
376 if (!ast_dns_resolver_set_result(&some_query, 1, 1, NOERROR, "asterisk.org",
378 ast_test_status_update(test, "Successfully added a result that was both secure and bogus\n");
379 result = ast_dns_query_get_result(&some_query);
381 return AST_TEST_FAIL;
382 }
383
384 if (!ast_dns_resolver_set_result(&some_query, 0, 0, NOERROR, NULL,
386 ast_test_status_update(test, "Successfully added result with no canonical name\n");
387 result = ast_dns_query_get_result(&some_query);
389 return AST_TEST_FAIL;
390 }
391
392 return AST_TEST_PASS;
393}

References ast_dns_query_get_result(), ast_dns_resolver_set_result(), ast_dns_result_free(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, DNS_ANSWER, DNS_ANSWER_SIZE, sip_to_pjsip::info(), NULL, result, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [13/13]

AST_TEST_DEFINE ( resolver_unregister_off_nominal  )

Definition at line 158 of file test_dns.c.

159{
160 struct ast_dns_resolver non_existent = {
161 .name = "I do not exist",
162 .priority = 20141004,
163 .resolve = stub_resolve,
164 .cancel = stub_cancel,
165 };
166
167 switch (cmd) {
168 case TEST_INIT:
169 info->name = "resolver_unregister_off_nominal";
170 info->category = "/main/dns/";
171 info->summary = "Test off-nominal DNS resolver unregister";
172 info->description =
173 "The test attempts the following:\n"
174 "\t* Unregister a resolver that is not registered.\n"
175 "\t* Unregister a NULL pointer.\n"
176 "Because unregistering a resolver does not return an indicator of success, the best\n"
177 "this test can do is verify that nothing blows up when this is attempted.";
178 return AST_TEST_NOT_RUN;
179 case TEST_EXECUTE:
180 break;
181 }
182
183 ast_dns_resolver_unregister(&non_existent);
185
186 return AST_TEST_PASS;
187}

References ast_dns_resolver_unregister(), AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), ast_dns_resolver::name, NULL, stub_cancel(), stub_resolve(), TEST_EXECUTE, and TEST_INIT.

◆ async_callback()

static void async_callback ( const struct ast_dns_query query)
static

Async DNS callback.

This is called when an async query completes, either because it resolved or because it was canceled. In our case, this callback is used to signal to the test that it can continue

Parameters
queryThe DNS query that has completed

Definition at line 1008 of file test_dns.c.

1009{
1010 struct async_resolution_data *async_data = ast_dns_query_get_data(query);
1011
1012 ast_mutex_lock(&async_data->lock);
1013 async_data->complete = 1;
1014 ast_cond_signal(&async_data->cond);
1015 ast_mutex_unlock(&async_data->lock);
1016}
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
Definition: dns_core.c:72
#define ast_cond_signal(cond)
Definition: lock.h:203
ast_mutex_t lock
Definition: test_dns.c:959

References ast_cond_signal, ast_dns_query_get_data(), ast_mutex_lock, ast_mutex_unlock, async_resolution_data::complete, async_resolution_data::cond, and async_resolution_data::lock.

Referenced by AST_TEST_DEFINE().

◆ async_data_alloc()

static struct async_resolution_data * async_data_alloc ( void  )
static

Allocation/initialization for async_resolution_data.

The DNS core mandates that a query's user data has to be ao2 allocated, so this is a helper method for doing that.

Return values
NULLFailed allocation
non-NULLNewly allocated async_resolution_data

Definition at line 983 of file test_dns.c.

984{
985 struct async_resolution_data *async_data;
986
987 async_data = ao2_alloc(sizeof(*async_data), async_data_destructor);
988 if (!async_data) {
989 return NULL;
990 }
991
992 async_data->complete = 0;
993 ast_mutex_init(&async_data->lock);
994 ast_cond_init(&async_data->cond, NULL);
995
996 return async_data;
997}
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
static void async_data_destructor(void *obj)
Destructor for async_resolution_data.
Definition: test_dns.c:966

References ao2_alloc, ast_cond_init, ast_mutex_init, async_data_destructor(), async_resolution_data::complete, async_resolution_data::cond, async_resolution_data::lock, and NULL.

Referenced by AST_TEST_DEFINE().

◆ async_data_destructor()

static void async_data_destructor ( void *  obj)
static

Destructor for async_resolution_data.

Definition at line 966 of file test_dns.c.

967{
968 struct async_resolution_data *async_data = obj;
969
970 ast_mutex_destroy(&async_data->lock);
971 ast_cond_destroy(&async_data->cond);
972}
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_mutex_destroy(a)
Definition: lock.h:188

References ast_cond_destroy, ast_mutex_destroy, async_resolution_data::cond, and async_resolution_data::lock.

Referenced by async_data_alloc().

◆ fail_resolve()

static int fail_resolve ( struct ast_dns_query query)
static

A resolve() method that simply fails.

Parameters
queryThe DNS query to resolve. This is ignored.
Returns
-1

Definition at line 857 of file test_dns.c.

858{
859 return -1;
860}

Referenced by AST_TEST_DEFINE().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1318 of file test_dns.c.

1319{
1320 AST_TEST_REGISTER(resolver_register_unregister);
1321 AST_TEST_REGISTER(resolver_register_off_nominal);
1322 AST_TEST_REGISTER(resolver_unregister_off_nominal);
1324 AST_TEST_REGISTER(resolver_set_result);
1325 AST_TEST_REGISTER(resolver_set_result_off_nominal);
1326 AST_TEST_REGISTER(resolver_add_record);
1327 AST_TEST_REGISTER(resolver_add_record_off_nominal);
1328 AST_TEST_REGISTER(resolver_resolve_sync);
1329 AST_TEST_REGISTER(resolver_resolve_sync_off_nominal);
1330 AST_TEST_REGISTER(resolver_resolve_async);
1331 AST_TEST_REGISTER(resolver_resolve_async_off_nominal);
1332 AST_TEST_REGISTER(resolver_resolve_async_cancel);
1333
1335}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
File-scoped data used during resolver tests.
Definition: test_dns.c:644
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ resolution_thread()

static void * resolution_thread ( void *  dns_query)
static

Thread spawned by the mock resolver.

All DNS resolvers are required to be asynchronous. The mock resolver spawns this thread for every DNS query that is executed.

This thread waits for 5 seconds and then returns the same A record every time. The 5 second wait is to allow for the query to be canceled if desired

Parameters
dns_queryThe ast_dns_query that is being resolved
Returns
NULL

Definition at line 670 of file test_dns.c.

671{
672 struct ast_dns_query *query = dns_query;
673 struct timespec timeout;
674
675 static const char *V4 = "127.0.0.1";
676 static const size_t V4_BUFSIZE = sizeof(struct in_addr);
677 char v4_buf[V4_BUFSIZE];
678
679 timeout = ast_tsnow();
680 timeout.tv_sec += 5;
681
685 break;
686 }
687 }
689
692 ao2_ref(query, -1);
693 return NULL;
694 }
695
696 ast_dns_resolver_set_result(query, 0, 0, NOERROR, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE);
697
698 inet_pton(AF_INET, V4, v4_buf);
699 ast_dns_resolver_add_record(query, T_A, C_IN, 12345, v4_buf, V4_BUFSIZE);
700
703
704 ao2_ref(query, -1);
705 return NULL;
706}
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
ast_mutex_t lock
Definition: test_dns.c:652
ast_cond_t cancel_cond
Definition: test_dns.c:654

References ao2_ref, ast_cond_timedwait, ast_dns_resolver_add_record(), ast_dns_resolver_completed(), ast_dns_resolver_set_result(), ast_mutex_lock, ast_mutex_unlock, ast_tsnow(), resolver_data::cancel_cond, resolver_data::canceled, DNS_ANSWER, DNS_ANSWER_SIZE, resolver_data::lock, NULL, resolver_data::resolution_complete, and test_resolver_data.

Referenced by test_resolve().

◆ resolver_data_cleanup()

static void resolver_data_cleanup ( void  )
static

Cleanup global mock resolver data.

This must be called at the end of tests that use the mock resolver

Definition at line 761 of file test_dns.c.

References ast_cond_destroy, ast_mutex_destroy, resolver_data::cancel_cond, resolver_data::lock, and test_resolver_data.

Referenced by AST_TEST_DEFINE().

◆ resolver_data_init()

static void resolver_data_init ( void  )
static

Initialize global mock resolver data.

This must be called at the beginning of tests that use the mock resolver

Definition at line 746 of file test_dns.c.

References ast_cond_init, ast_mutex_init, resolver_data::cancel_cond, resolver_data::canceled, resolver_data::lock, NULL, resolver_data::resolution_complete, resolver_data::resolve_called, and test_resolver_data.

Referenced by AST_TEST_DEFINE().

◆ stub_callback()

static void stub_callback ( const struct ast_dns_query query)
static

Stub async resolution callback

Definition at line 1116 of file test_dns.c.

1117{
1118 return;
1119}

Referenced by AST_TEST_DEFINE().

◆ stub_cancel()

static int stub_cancel ( struct ast_dns_query query)
static

Definition at line 42 of file test_dns.c.

43{
44 return 0;
45}

Referenced by AST_TEST_DEFINE().

◆ stub_resolve()

static int stub_resolve ( struct ast_dns_query query)
static

Definition at line 36 of file test_dns.c.

37{
38 return 0;
39}

Referenced by AST_TEST_DEFINE().

◆ test_cancel()

static int test_cancel ( struct ast_dns_query query)
static

Mock resolver's cancel method.

This signals the resolution thread not to return any DNS results.

Parameters
queryDNS query to cancel
Returns
0

Definition at line 731 of file test_dns.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, resolver_data::cancel_cond, resolver_data::canceled, resolver_data::lock, and test_resolver_data.

◆ test_record()

static int test_record ( struct ast_test *  test,
const struct ast_dns_record record,
int  rr_type,
int  rr_class,
int  ttl,
const char *  data,
const size_t  size 
)
static

Definition at line 395 of file test_dns.c.

397{
398 if (ast_dns_record_get_rr_type(record) != rr_type) {
399 ast_test_status_update(test, "Unexpected rr_type from DNS record\n");
400 return -1;
401 }
402
403 if (ast_dns_record_get_rr_class(record) != rr_class) {
404 ast_test_status_update(test, "Unexpected rr_class from DNS record\n");
405 return -1;
406 }
407
408 if (ast_dns_record_get_ttl(record) != ttl) {
409 ast_test_status_update(test, "Unexpected ttl from DNS record\n");
410 return -1;
411 }
412
413 if (memcmp(ast_dns_record_get_data(record), data, size)) {
414 ast_test_status_update(test, "Unexpected data in DNS record\n");
415 return -1;
416 }
417
418 return 0;
419}
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
Definition: dns_core.c:150
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
Definition: dns_core.c:155
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
Definition: dns_core.c:160

References ast_dns_record_get_data(), ast_dns_record_get_rr_class(), ast_dns_record_get_rr_type(), ast_dns_record_get_ttl(), and ast_test_status_update.

Referenced by AST_TEST_DEFINE().

◆ test_resolve()

static int test_resolve ( struct ast_dns_query query)
static

Mock resolver's resolve method.

Parameters
queryThe query to resolve
Return values
0Successfully spawned resolution thread
non-zeroFailed to spawn the resolution thread

Definition at line 715 of file test_dns.c.

716{
717 pthread_t resolver_thread;
718
720 return ast_pthread_create_detached(&resolver_thread, NULL, resolution_thread, ao2_bump(query));
721}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static void * resolution_thread(void *dns_query)
Thread spawned by the mock resolver.
Definition: test_dns.c:670
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588

References ao2_bump, ast_pthread_create_detached, NULL, resolution_thread(), resolver_data::resolve_called, and test_resolver_data.

◆ test_results()

static int test_results ( struct ast_test *  test,
const struct ast_dns_query query,
unsigned int  expected_secure,
unsigned int  expected_bogus,
unsigned int  expected_rcode,
const char *  expected_canonical,
const char *  expected_answer,
size_t  answer_size 
)
static

Definition at line 265 of file test_dns.c.

269{
270 struct ast_dns_result *result;
271
273 if (!result) {
274 ast_test_status_update(test, "Unable to retrieve result from query\n");
275 return -1;
276 }
277
278 if (ast_dns_result_get_secure(result) != expected_secure ||
279 ast_dns_result_get_bogus(result) != expected_bogus ||
280 ast_dns_result_get_rcode(result) != expected_rcode ||
281 strcmp(ast_dns_result_get_canonical(result), expected_canonical) ||
282 memcmp(ast_dns_result_get_answer(result), expected_answer, answer_size)) {
283 ast_test_status_update(test, "Unexpected values in result from query\n");
284 return -1;
285 }
286
287 return 0;
288}
const char * ast_dns_result_get_canonical(const struct ast_dns_result *result)
Get the canonical name of the result.
Definition: dns_core.c:97
unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
Get the error rcode of a DN result.
Definition: dns_core.c:92
unsigned int ast_dns_result_get_bogus(const struct ast_dns_result *result)
Get whether the result is bogus or not.
Definition: dns_core.c:87
unsigned int ast_dns_result_get_secure(const struct ast_dns_result *result)
Get whether the result is secure or not.
Definition: dns_core.c:82
const char * ast_dns_result_get_answer(const struct ast_dns_result *result)
Get the raw DNS answer from a DNS result.
Definition: dns_core.c:107
size_t answer_size
The size of the raw DNS answer.
Definition: dns_internal.h:131

References ast_dns_result::answer_size, ast_dns_query_get_result(), ast_dns_result_get_answer(), ast_dns_result_get_bogus(), ast_dns_result_get_canonical(), ast_dns_result_get_rcode(), ast_dns_result_get_secure(), ast_test_status_update, and result.

Referenced by AST_TEST_DEFINE().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1299 of file test_dns.c.

1300{
1301 AST_TEST_UNREGISTER(resolver_register_unregister);
1302 AST_TEST_UNREGISTER(resolver_register_off_nominal);
1303 AST_TEST_UNREGISTER(resolver_unregister_off_nominal);
1305 AST_TEST_UNREGISTER(resolver_set_result);
1306 AST_TEST_UNREGISTER(resolver_set_result_off_nominal);
1307 AST_TEST_UNREGISTER(resolver_add_record);
1308 AST_TEST_UNREGISTER(resolver_add_record_off_nominal);
1309 AST_TEST_UNREGISTER(resolver_resolve_sync);
1310 AST_TEST_UNREGISTER(resolver_resolve_sync_off_nominal);
1311 AST_TEST_UNREGISTER(resolver_resolve_async);
1312 AST_TEST_UNREGISTER(resolver_resolve_async_off_nominal);
1313 AST_TEST_UNREGISTER(resolver_resolve_async_cancel);
1314
1315 return 0;
1316}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "DNS API Tests" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 1337 of file test_dns.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1337 of file test_dns.c.

◆ test_resolver

struct ast_dns_resolver test_resolver
static

The mock resolver.

The mock resolver does not care about the DNS query that is actually being made on it. It simply regurgitates the same DNS record no matter what.

Definition at line 774 of file test_dns.c.

Referenced by AST_TEST_DEFINE().

◆ test_resolver_data

struct resolver_data test_resolver_data
static