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

Go to the source code of this file.

Data Structures

struct  query_set_data
 

Macros

#define DNS_ANSWER   "Yes sirree"
 
#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 (query_set)
 
 AST_TEST_DEFINE (query_set_empty)
 
 AST_TEST_DEFINE (query_set_nominal_cancel)
 
 AST_TEST_DEFINE (query_set_off_nominal_cancel)
 
static int load_module (void)
 
static void query_set_callback (const struct ast_dns_query_set *query_set)
 Callback which is invoked upon query set completion. More...
 
static int query_set_cancel (struct ast_dns_query *query)
 Resolver's cancel() method. More...
 
static struct query_set_dataquery_set_data_alloc (void)
 
static void query_set_data_destructor (void *obj)
 
static int query_set_resolve (struct ast_dns_query *query)
 Resolver's resolve() method. More...
 
static enum ast_test_result_state query_set_test (struct ast_test *test, int resolve, int cancel)
 Framework for running a query set DNS test. More...
 
static void * resolution_thread (void *dns_query)
 Thread that performs asynchronous resolution. More...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "DNS query set 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 query_set_resolver
 

Macro Definition Documentation

◆ DNS_ANSWER

#define DNS_ANSWER   "Yes sirree"

Definition at line 75 of file test_dns_query_set.c.

◆ DNS_ANSWER_SIZE

#define DNS_ANSWER_SIZE   strlen(DNS_ANSWER)

Definition at line 76 of file test_dns_query_set.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 392 of file test_dns_query_set.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 392 of file test_dns_query_set.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 392 of file test_dns_query_set.c.

◆ AST_TEST_DEFINE() [1/4]

AST_TEST_DEFINE ( query_set  )

Definition at line 287 of file test_dns_query_set.c.

288{
289 switch (cmd) {
290 case TEST_INIT:
291 info->name = "query_set";
292 info->category = "/main/dns/query_set/";
293 info->summary = "Test nominal asynchronous DNS query set";
294 info->description =
295 "This tests nominal query set in the following ways:\n"
296 "\t* Multiple queries are added to a query set\n"
297 "\t* The mock resolver is configured to respond to all queries\n"
298 "\t* Asynchronous resolution of the query set is started\n"
299 "\t* The mock resolver responds to all queries\n"
300 "\t* We ensure that the query set callback is invoked upon completion";
301 return AST_TEST_NOT_RUN;
302 case TEST_EXECUTE:
303 break;
304 }
305
306 return query_set_test(test, 4, 0);
307}
def info(msg)
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
@ AST_TEST_NOT_RUN
Definition: test.h:194
static enum ast_test_result_state query_set_test(struct ast_test *test, int resolve, int cancel)
Framework for running a query set DNS test.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), query_set_test(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [2/4]

AST_TEST_DEFINE ( query_set_empty  )

Definition at line 309 of file test_dns_query_set.c.

310{
311 switch (cmd) {
312 case TEST_INIT:
313 info->name = "query_set_empty";
314 info->category = "/main/dns/query_set/";
315 info->summary = "Test nominal asynchronous empty DNS query set";
316 info->description =
317 "This tests nominal query set in the following ways:\n"
318 "\t* No queries are added to a query set\n"
319 "\t* Asynchronous resolution of the query set is started\n"
320 "\t* We ensure that the query set callback is invoked upon completion";
321 return AST_TEST_NOT_RUN;
322 case TEST_EXECUTE:
323 break;
324 }
325
326 return query_set_test(test, 0, 0);
327}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), query_set_test(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [3/4]

AST_TEST_DEFINE ( query_set_nominal_cancel  )

Definition at line 329 of file test_dns_query_set.c.

330{
331 switch (cmd) {
332 case TEST_INIT:
333 info->name = "query_set_nominal_cancel";
334 info->category = "/main/dns/query_set/";
335 info->summary = "Test nominal asynchronous DNS query set cancellation";
336 info->description =
337 "This tests nominal query set cancellation in the following ways:\n"
338 "\t* Multiple queries are added to a query set\n"
339 "\t* The mock resolver is configured to NOT respond to any queries\n"
340 "\t* Asynchronous resolution of the query set is started\n"
341 "\t* The query set is canceled and is confirmed to return with success";
342 return AST_TEST_NOT_RUN;
343 case TEST_EXECUTE:
344 break;
345 }
346
347 return query_set_test(test, 0, 4);
348}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), query_set_test(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [4/4]

AST_TEST_DEFINE ( query_set_off_nominal_cancel  )

Definition at line 350 of file test_dns_query_set.c.

351{
352 switch (cmd) {
353 case TEST_INIT:
354 info->name = "query_set_off_nominal_cancel";
355 info->category = "/main/dns/query_set/";
356 info->summary = "Test off-nominal asynchronous DNS query set cancellation";
357 info->description =
358 "This tests nominal query set cancellation in the following ways:\n"
359 "\t* Multiple queries are added to a query set\n"
360 "\t* The mock resolver is configured to respond to half the queries\n"
361 "\t* Asynchronous resolution of the query set is started\n"
362 "\t* The query set is canceled and is confirmed to return failure\n"
363 "\t* The query set callback is confirmed to run, since it could not be fully canceled";
364 return AST_TEST_NOT_RUN;
365 case TEST_EXECUTE:
366 break;
367 }
368
369 return query_set_test(test, 2, 2);
370}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), query_set_test(), TEST_EXECUTE, and TEST_INIT.

◆ load_module()

static int load_module ( void  )
static

Definition at line 382 of file test_dns_query_set.c.

383{
384 AST_TEST_REGISTER(query_set);
385 AST_TEST_REGISTER(query_set_empty);
386 AST_TEST_REGISTER(query_set_nominal_cancel);
387 AST_TEST_REGISTER(query_set_off_nominal_cancel);
388
390}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ query_set_callback()

static void query_set_callback ( const struct ast_dns_query_set query_set)
static

Callback which is invoked upon query set completion.

Parameters
query_setThe query set

Definition at line 161 of file test_dns_query_set.c.

162{
163 struct query_set_data *qsdata = ast_dns_query_set_get_data(query_set);
164
165 ast_mutex_lock(&qsdata->lock);
166 qsdata->query_set_complete = 1;
167 ast_cond_signal(&qsdata->cond);
168 ast_mutex_unlock(&qsdata->lock);
169}
void * ast_dns_query_set_get_data(const struct ast_dns_query_set *query_set)
Retrieve user specific data from a query set.
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
#define ast_cond_signal(cond)
Definition: lock.h:203

References ast_cond_signal, ast_dns_query_set_get_data(), ast_mutex_lock, ast_mutex_unlock, query_set_data::cond, query_set_data::lock, and query_set_data::query_set_complete.

Referenced by query_set_test().

◆ query_set_cancel()

static int query_set_cancel ( struct ast_dns_query query)
static

Resolver's cancel() method.

Parameters
queryThe query to cancel
Returns
0

Definition at line 131 of file test_dns_query_set.c.

132{
133 struct ast_dns_query_set *query_set = ast_dns_query_get_data(query);
134 struct query_set_data *qsdata;
135 int res = -1;
136
137 if (!query_set) {
138 return -1;
139 }
140 qsdata = query_set->user_data;
141
142 if (qsdata->cancel++ < qsdata->cancel_allowed) {
143 res = 0;
144 }
145
146 return res;
147}
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
A set of DNS queries.
Definition: dns_internal.h:185
void * user_data
User-specific data.
Definition: dns_internal.h:197

References ast_dns_query_get_data(), query_set_data::cancel, query_set_data::cancel_allowed, and ast_dns_query_set::user_data.

◆ query_set_data_alloc()

static struct query_set_data * query_set_data_alloc ( void  )
static

Definition at line 60 of file test_dns_query_set.c.

61{
62 struct query_set_data *qsdata;
63
64 qsdata = ao2_alloc(sizeof(*qsdata), query_set_data_destructor);
65 if (!qsdata) {
66 return NULL;
67 }
68
69 ast_mutex_init(&qsdata->lock);
70 ast_cond_init(&qsdata->cond, NULL);
71
72 return qsdata;
73}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define NULL
Definition: resample.c:96
static void query_set_data_destructor(void *obj)

References ao2_alloc, ast_cond_init, ast_mutex_init, query_set_data::cond, query_set_data::lock, NULL, and query_set_data_destructor().

Referenced by query_set_test().

◆ query_set_data_destructor()

static void query_set_data_destructor ( void *  obj)
static

Definition at line 52 of file test_dns_query_set.c.

53{
54 struct query_set_data *qsdata = obj;
55
56 ast_mutex_destroy(&qsdata->lock);
57 ast_cond_destroy(&qsdata->cond);
58}
#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, query_set_data::cond, and query_set_data::lock.

Referenced by query_set_data_alloc().

◆ query_set_resolve()

static int query_set_resolve ( struct ast_dns_query query)
static

Resolver's resolve() method.

Parameters
queryThe query that is to be resolved
Return values
0Successfully created thread to perform the resolution
non-zeroFailed to create resolution thread

Definition at line 111 of file test_dns_query_set.c.

112{
113 struct ast_dns_query_set *query_set = ast_dns_query_get_data(query);
114 struct query_set_data *qsdata = query_set->user_data;
115 pthread_t resolver_thread;
116
117 /* Only the queries which will not be canceled actually start a thread */
118 if (qsdata->resolves++ < qsdata->cancel_allowed) {
119 return 0;
120 }
121
122 return ast_pthread_create_detached(&resolver_thread, NULL, resolution_thread, ao2_bump(query));
123}
#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 that performs asynchronous resolution.
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588

References ao2_bump, ast_dns_query_get_data(), ast_pthread_create_detached, query_set_data::cancel_allowed, NULL, resolution_thread(), query_set_data::resolves, and ast_dns_query_set::user_data.

◆ query_set_test()

static enum ast_test_result_state query_set_test ( struct ast_test *  test,
int  resolve,
int  cancel 
)
static

Framework for running a query set DNS test.

This function serves as a common way of testing various numbers of queries in a query set and optional canceling of them.

Parameters
testThe test being run
resolveThe number of queries that should be allowed to complete resolution
cancelThe number of queries that should be allowed to be canceled

Definition at line 181 of file test_dns_query_set.c.

182{
183 int total = resolve + cancel;
184 RAII_VAR(struct ast_dns_query_set *, query_set, NULL, ao2_cleanup);
185 RAII_VAR(struct query_set_data *, qsdata, NULL, ao2_cleanup);
187 int idx;
188 struct timespec timeout;
189
191 ast_test_status_update(test, "Failed to register query set DNS resolver\n");
192 return AST_TEST_FAIL;
193 }
194
195 qsdata = query_set_data_alloc();
196 if (!qsdata) {
197 ast_test_status_update(test, "Failed to allocate data necessary for query set test\n");
198 res = AST_TEST_FAIL;
199 goto cleanup;
200 }
201
202 query_set = ast_dns_query_set_create();
203 if (!query_set) {
204 ast_test_status_update(test, "Failed to create DNS query set\n");
205 res = AST_TEST_FAIL;
206 goto cleanup;
207 }
208
209 qsdata->resolves_allowed = resolve;
210 qsdata->cancel_allowed = cancel;
211
212 for (idx = 0; idx < total; ++idx) {
213 if (ast_dns_query_set_add(query_set, "asterisk.org", T_A, C_IN)) {
214 ast_test_status_update(test, "Failed to add query to DNS query set\n");
215 res = AST_TEST_FAIL;
216 goto cleanup;
217 }
218 }
219
220 if (ast_dns_query_set_num_queries(query_set) != total) {
221 ast_test_status_update(test, "DNS query set does not contain the correct number of queries\n");
222 res = AST_TEST_FAIL;
223 goto cleanup;
224 }
225
227
228 if (cancel && (cancel == total)) {
229 if (ast_dns_query_set_resolve_cancel(query_set)) {
230 ast_test_status_update(test, "Failed to cancel DNS query set when it should be cancellable\n");
231 res = AST_TEST_FAIL;
232 }
233
234 if (qsdata->query_set_complete) {
235 ast_test_status_update(test, "Query set callback was invoked despite all queries being cancelled\n");
236 res = AST_TEST_FAIL;
237 }
238
239 goto cleanup;
240 } else if (cancel) {
241 if (!ast_dns_query_set_resolve_cancel(query_set)) {
242 ast_test_status_update(test, "Successfully cancelled DNS query set when it should not be possible\n");
243 res = AST_TEST_FAIL;
244 goto cleanup;
245 }
246 }
247
248 timeout = ast_tsnow();
249 timeout.tv_sec += 10;
250
251 ast_mutex_lock(&qsdata->lock);
252 while (!qsdata->query_set_complete) {
253 if (ast_cond_timedwait(&qsdata->cond, &qsdata->lock, &timeout) == ETIMEDOUT) {
254 break;
255 }
256 }
257 ast_mutex_unlock(&qsdata->lock);
258
259 if (!qsdata->query_set_complete) {
260 ast_test_status_update(test, "Query set did not complete when it should have\n");
261 res = AST_TEST_FAIL;
262 goto cleanup;
263 }
264
265 for (idx = 0; idx < ast_dns_query_set_num_queries(query_set); ++idx) {
266 const struct ast_dns_query *query = ast_dns_query_set_get(query_set, idx);
267
268 if (strcmp(ast_dns_query_get_name(query), "asterisk.org")) {
269 ast_test_status_update(test, "Query did not have expected name\n");
270 res = AST_TEST_FAIL;
271 }
272 if (ast_dns_query_get_rr_type(query) != T_A) {
273 ast_test_status_update(test, "Query did not have expected type\n");
274 res = AST_TEST_FAIL;
275 }
276 if (ast_dns_query_get_rr_class(query) != C_IN) {
277 ast_test_status_update(test, "Query did not have expected class\n");
278 res = AST_TEST_FAIL;
279 }
280 }
281
282cleanup:
284 return res;
285}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
Definition: dns_core.c:62
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
Definition: dns_core.c:67
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
Definition: dns_core.c:57
struct ast_dns_query * ast_dns_query_set_get(const struct ast_dns_query_set *query_set, unsigned int index)
Retrieve a query from a query set.
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
Definition: dns_query_set.c:60
size_t ast_dns_query_set_num_queries(const struct ast_dns_query_set *query_set)
Retrieve the number of queries in a query set.
int ast_dns_query_set_add(struct ast_dns_query_set *query_set, const char *name, int rr_type, int rr_class)
Add a query to a query set.
int ast_dns_query_set_resolve_cancel(struct ast_dns_query_set *query_set)
Cancel an asynchronous DNS query set resolution.
void ast_dns_query_set_resolve_async(struct ast_dns_query_set *query_set, ast_dns_query_set_callback callback, void *data)
Asynchronously resolve queries in a query set.
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
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
static int total
Definition: res_adsi.c:970
A DNS query.
Definition: dns_internal.h:137
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
static struct ast_dns_resolver query_set_resolver
static struct query_set_data * query_set_data_alloc(void)
static void query_set_callback(const struct ast_dns_query_set *query_set)
Callback which is invoked upon query set completion.
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
#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

References ao2_cleanup, ast_cond_timedwait, ast_dns_query_get_name(), ast_dns_query_get_rr_class(), ast_dns_query_get_rr_type(), ast_dns_query_set_add(), ast_dns_query_set_create(), ast_dns_query_set_get(), ast_dns_query_set_num_queries(), ast_dns_query_set_resolve_async(), ast_dns_query_set_resolve_cancel(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_TEST_FAIL, AST_TEST_PASS, ast_test_status_update, ast_tsnow(), query_set_data::cancel, cleanup(), NULL, query_set_callback(), query_set_data_alloc(), query_set_resolver, RAII_VAR, and total.

Referenced by AST_TEST_DEFINE().

◆ resolution_thread()

static void * resolution_thread ( void *  dns_query)
static

Thread that performs asynchronous resolution.

This thread uses the query's user data to determine how to perform the resolution. If the allowed number of resolutions has not been reached then this will succeed, otherwise the query is expected to have been canceled.

Parameters
dns_queryThe ast_dns_query that is being performed
Returns
NULL

Definition at line 89 of file test_dns_query_set.c.

90{
91 struct ast_dns_query *query = dns_query;
92 struct ast_dns_query_set *query_set = ast_dns_query_get_data(query);
93 struct query_set_data *qsdata = query_set->user_data;
94
95 ast_assert(qsdata != NULL);
96
97 ast_dns_resolver_set_result(query, 0, 0, NOERROR, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE);
99
100 ao2_ref(query, -1);
101 return NULL;
102}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
#define DNS_ANSWER_SIZE
#define DNS_ANSWER
#define ast_assert(a)
Definition: utils.h:739

References ao2_ref, ast_assert, ast_dns_query_get_data(), ast_dns_resolver_completed(), ast_dns_resolver_set_result(), DNS_ANSWER, DNS_ANSWER_SIZE, NULL, and ast_dns_query_set::user_data.

Referenced by query_set_resolve().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 372 of file test_dns_query_set.c.

373{
374 AST_TEST_UNREGISTER(query_set);
375 AST_TEST_UNREGISTER(query_set_empty);
376 AST_TEST_UNREGISTER(query_set_nominal_cancel);
377 AST_TEST_UNREGISTER(query_set_off_nominal_cancel);
378
379 return 0;
380}
#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 query set 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 392 of file test_dns_query_set.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 392 of file test_dns_query_set.c.

◆ query_set_resolver

struct ast_dns_resolver query_set_resolver
static

Definition at line 149 of file test_dns_query_set.c.

Referenced by query_set_test().