Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : SSSD tests: Resolver tests using a fake resolver library
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include <talloc.h>
24 : #include <tevent.h>
25 : #include <errno.h>
26 : #include <popt.h>
27 : #include <arpa/inet.h>
28 : #include <netinet/in.h>
29 : #include <sys/types.h>
30 : #include <stdarg.h>
31 : #include <stdlib.h>
32 :
33 : #include "providers/fail_over_srv.h"
34 : #include "tests/cmocka/common_mock.h"
35 : #include "tests/cmocka/common_mock_resp.h"
36 :
37 : #define TEST_RESOLV_TIMEOUT 5
38 : #define TEST_FO_TIMEOUT 3000
39 : #define TEST_SRV_TTL 500
40 : #define TEST_SRV_SHORT_TTL 2
41 :
42 : static TALLOC_CTX *global_mock_context = NULL;
43 :
44 : enum host_database default_host_dbs[] = { DB_FILES, DB_DNS, DB_SENTINEL };
45 :
46 : struct resolv_ctx {
47 : int foo;
48 : };
49 :
50 : /* mock resolver interface. The resolver test is separate */
51 4 : int resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
52 : int timeout, struct resolv_ctx **ctxp)
53 : {
54 4 : *ctxp = talloc(mem_ctx, struct resolv_ctx);
55 4 : return EOK;
56 : }
57 :
58 : struct tevent_req *
59 10 : resolv_gethostbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
60 : struct resolv_ctx *ctx, const char *name,
61 : enum restrict_family family_order,
62 : enum host_database *db)
63 : {
64 10 : return test_req_succeed_send(mem_ctx, ev);
65 : }
66 :
67 10 : int resolv_gethostbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
68 : int *status, int *timeouts,
69 : struct resolv_hostent **rhostent)
70 : {
71 10 : return test_request_recv(req);
72 : }
73 :
74 0 : const char *resolv_strerror(int ares_code)
75 : {
76 0 : return NULL;
77 : }
78 :
79 6 : struct tevent_req *resolv_discover_srv_send(TALLOC_CTX *mem_ctx,
80 : struct tevent_context *ev,
81 : struct resolv_ctx *resolv_ctx,
82 : const char *service,
83 : const char *protocol,
84 : const char **discovery_domains)
85 : {
86 6 : return test_req_succeed_send(mem_ctx, ev);
87 : }
88 :
89 6 : errno_t resolv_discover_srv_recv(TALLOC_CTX *mem_ctx,
90 : struct tevent_req *req,
91 : struct ares_srv_reply **_reply_list,
92 : uint32_t *_ttl,
93 : char **_dns_domain)
94 : {
95 : struct ares_srv_reply *reply_list;
96 : uint32_t ttl;
97 : char *dns_domain;
98 :
99 : /* Need to always consume all mocked values */
100 6 : reply_list = sss_mock_ptr_type(struct ares_srv_reply *);
101 6 : ttl = sss_mock_ptr_type(uint32_t);
102 6 : dns_domain = sss_mock_ptr_type(char *);
103 :
104 6 : if (_reply_list != NULL) {
105 6 : *_reply_list = reply_list;
106 : }
107 :
108 6 : if (_ttl != NULL) {
109 6 : *_ttl = ttl;
110 : }
111 :
112 6 : if (_dns_domain != NULL) {
113 6 : *_dns_domain = dns_domain;
114 : }
115 :
116 6 : return test_request_recv(req);
117 : }
118 :
119 12 : struct ares_srv_reply *pop_lowest_prio(struct ares_srv_reply **r)
120 : {
121 : struct ares_srv_reply *lowest;
122 : struct ares_srv_reply *iter;
123 : struct ares_srv_reply *prev;
124 :
125 12 : lowest = *r;
126 12 : iter = lowest;
127 42 : while (iter != NULL) {
128 18 : if (iter->priority < lowest->priority) {
129 2 : lowest = iter;
130 : }
131 :
132 18 : iter = iter->next;
133 : }
134 :
135 12 : prev = NULL;
136 12 : iter = *r;
137 26 : while (iter != lowest) {
138 2 : prev = iter;
139 2 : iter = iter->next;
140 : }
141 :
142 : /* iter points to the lowest prio. Prev points to the item before */
143 12 : if (prev) {
144 2 : prev->next = lowest->next;
145 : } else {
146 10 : *r = lowest->next;
147 : }
148 :
149 12 : return lowest;
150 : }
151 :
152 6 : int resolv_sort_srv_reply(struct ares_srv_reply **reply)
153 : {
154 : struct ares_srv_reply *r;
155 : struct ares_srv_reply *lowest;
156 6 : struct ares_srv_reply *sorted = NULL;
157 6 : struct ares_srv_reply *sorted_head = NULL;
158 :
159 6 : r = *reply;
160 6 : if (r == NULL || r->next == NULL) {
161 0 : return EOK;
162 : }
163 :
164 : do {
165 12 : lowest = pop_lowest_prio(&r);
166 12 : if (sorted) {
167 6 : sorted->next = lowest;
168 6 : sorted = sorted->next;
169 : } else {
170 6 : sorted = lowest;
171 6 : sorted_head = sorted;
172 : }
173 12 : } while (r != NULL);
174 :
175 6 : *reply = sorted_head;
176 6 : return EOK;
177 : }
178 :
179 0 : struct tevent_req *resolv_get_domain_send(TALLOC_CTX *mem_ctx,
180 : struct tevent_context *ev,
181 : struct resolv_ctx *resolv_ctx,
182 : const char *hostname,
183 : enum host_database *host_dbs,
184 : enum restrict_family family_order)
185 : {
186 0 : return test_req_succeed_send(mem_ctx, ev);
187 : }
188 :
189 0 : errno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx,
190 : struct tevent_req *req,
191 : char **_dns_domain)
192 : {
193 0 : return test_request_recv(req);
194 : }
195 :
196 : /* The unit test */
197 : struct test_fo_ctx {
198 : struct resolv_ctx *resolv;
199 : struct fo_ctx *fo_ctx;
200 : struct fo_resolve_srv_dns_ctx *srv_ctx;
201 : struct fo_service *fo_svc;
202 : struct sss_test_ctx *ctx;
203 : int ttl;
204 : };
205 :
206 17 : int test_fo_srv_data_cmp(void *ud1, void *ud2)
207 : {
208 17 : return strcasecmp((char*) ud1, (char*) ud2);
209 : }
210 :
211 4 : static int test_fo_setup(void **state)
212 : {
213 : struct test_fo_ctx *test_ctx;
214 : errno_t ret;
215 : struct fo_options fopts;
216 :
217 4 : assert_true(leak_check_setup());
218 4 : global_mock_context = talloc_new(global_talloc_context);
219 4 : assert_non_null(global_mock_context);
220 :
221 4 : test_ctx = talloc_zero(global_mock_context,
222 : struct test_fo_ctx);
223 4 : assert_non_null(test_ctx);
224 :
225 4 : test_ctx->ctx = create_ev_test_ctx(test_ctx);
226 4 : assert_non_null(test_ctx->ctx);
227 :
228 4 : ret = resolv_init(test_ctx, test_ctx->ctx->ev,
229 : TEST_RESOLV_TIMEOUT, &test_ctx->resolv);
230 4 : assert_non_null(test_ctx->resolv);
231 :
232 4 : memset(&fopts, 0, sizeof(fopts));
233 4 : fopts.retry_timeout = TEST_FO_TIMEOUT;
234 4 : fopts.family_order = IPV4_FIRST;
235 :
236 4 : test_ctx->fo_ctx = fo_context_init(test_ctx, &fopts);
237 4 : assert_non_null(test_ctx->fo_ctx);
238 :
239 4 : ret = fo_new_service(test_ctx->fo_ctx, "ldap",
240 : test_fo_srv_data_cmp,
241 : &test_ctx->fo_svc);
242 4 : assert_int_equal(ret, ERR_OK);
243 :
244 4 : *state = test_ctx;
245 4 : return 0;
246 : }
247 :
248 4 : static int test_fo_teardown(void **state)
249 : {
250 4 : struct test_fo_ctx *test_ctx =
251 4 : talloc_get_type(*state, struct test_fo_ctx);
252 :
253 4 : talloc_free(test_ctx);
254 4 : talloc_free(global_mock_context);
255 4 : assert_true(leak_check_teardown());
256 4 : return 0;
257 : }
258 :
259 3 : static int test_fo_srv_setup(void **state)
260 : {
261 : struct test_fo_ctx *test_ctx;
262 : bool ok;
263 :
264 3 : test_fo_setup(state);
265 3 : test_ctx = *state;
266 :
267 3 : test_ctx->srv_ctx = fo_resolve_srv_dns_ctx_init(test_ctx, test_ctx->resolv,
268 : IPV4_FIRST, default_host_dbs,
269 : "client.sssd.com", "sssd.local");
270 3 : assert_non_null(test_ctx->srv_ctx);
271 :
272 3 : ok = fo_set_srv_lookup_plugin(test_ctx->fo_ctx,
273 : fo_resolve_srv_dns_send,
274 : fo_resolve_srv_dns_recv,
275 3 : test_ctx->srv_ctx);
276 3 : assert_true(ok);
277 :
278 3 : *state = test_ctx;
279 3 : return 0;
280 : }
281 :
282 3 : static int test_fo_srv_teardown(void **state)
283 : {
284 3 : test_fo_teardown(state);
285 3 : return 0;
286 : }
287 :
288 : /* reply_list and dns_domain must be a talloc context so it can be used as
289 : * talloc_steal argument later
290 : */
291 6 : static void mock_srv_results(struct ares_srv_reply *reply_list,
292 : uint32_t ttl,
293 : char *dns_domain)
294 : {
295 6 : will_return(resolv_discover_srv_recv, reply_list);
296 6 : will_return(resolv_discover_srv_recv, ttl);
297 6 : will_return(resolv_discover_srv_recv, dns_domain);
298 6 : }
299 :
300 12 : static void check_server(struct test_fo_ctx *ctx,
301 : struct fo_server *srv,
302 : int port,
303 : const char *name)
304 : {
305 12 : assert_non_null(srv);
306 12 : assert_int_equal(fo_get_server_port(srv), port);
307 12 : assert_string_equal(fo_get_server_name(srv), name);
308 :
309 :
310 12 : if (ctx->srv_ctx) {
311 8 : assert_true(fo_is_srv_lookup(srv));
312 : }
313 12 : }
314 :
315 : static void test_fo_srv_step1(struct test_fo_ctx *test_ctx);
316 : static void test_fo_srv_done1(struct tevent_req *req);
317 : static void test_fo_srv_done2(struct tevent_req *req);
318 : static void test_fo_srv_done3(struct tevent_req *req);
319 : static void test_fo_srv_done4(struct tevent_req *req);
320 : static void test_fo_srv_done5(struct tevent_req *req);
321 :
322 2 : static void test_fo_srv_mock_dns(struct test_fo_ctx *test_ctx)
323 : {
324 : struct ares_srv_reply *s1;
325 : struct ares_srv_reply *s2;
326 : char *dns_domain;
327 :
328 2 : s1 = talloc_zero(test_ctx, struct ares_srv_reply);
329 2 : assert_non_null(s1);
330 2 : s1->host = talloc_strdup(s1, "ldap1.sssd.com");
331 2 : assert_non_null(s1->host);
332 2 : s1->weight = 100;
333 2 : s1->priority = 1;
334 2 : s1->port = 389;
335 :
336 2 : s2 = talloc_zero(test_ctx, struct ares_srv_reply);
337 2 : assert_non_null(s2);
338 2 : s2->host = talloc_strdup(s2, "ldap2.sssd.com");
339 2 : assert_non_null(s2->host);
340 2 : s2->weight = 100;
341 2 : s2->priority = 2;
342 2 : s2->port = 389;
343 :
344 2 : s1->next = s2;
345 :
346 2 : dns_domain = talloc_strdup(test_ctx, "sssd.com");
347 2 : assert_non_null(dns_domain);
348 :
349 2 : mock_srv_results(s1, TEST_SRV_TTL, dns_domain);
350 2 : }
351 :
352 1 : static void test_fo_srv(void **state)
353 : {
354 : errno_t ret;
355 1 : struct test_fo_ctx *test_ctx =
356 1 : talloc_get_type(*state, struct test_fo_ctx);
357 :
358 1 : test_fo_srv_mock_dns(test_ctx);
359 :
360 1 : ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com",
361 : "sssd.local", "tcp", test_ctx);
362 1 : assert_int_equal(ret, ERR_OK);
363 :
364 1 : test_fo_srv_step1(test_ctx);
365 :
366 1 : ret = test_ev_loop(test_ctx->ctx);
367 1 : assert_int_equal(ret, ERR_OK);
368 1 : }
369 :
370 2 : static void test_fo_srv_step1(struct test_fo_ctx *test_ctx)
371 : {
372 : struct tevent_req *req;
373 :
374 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
375 : test_ctx->resolv, test_ctx->fo_ctx,
376 : test_ctx->fo_svc);
377 2 : assert_non_null(req);
378 2 : tevent_req_set_callback(req, test_fo_srv_done1, test_ctx);
379 2 : }
380 :
381 2 : static void test_fo_srv_done1(struct tevent_req *req)
382 : {
383 2 : struct test_fo_ctx *test_ctx = \
384 2 : tevent_req_callback_data(req, struct test_fo_ctx);
385 : struct fo_server *srv;
386 : errno_t ret;
387 :
388 2 : ret = fo_resolve_service_recv(req, &srv);
389 2 : talloc_zfree(req);
390 2 : assert_int_equal(ret, ERR_OK);
391 :
392 : /* ldap1.sssd.com has lower priority, it must always be first */
393 2 : check_server(test_ctx, srv, 389, "ldap1.sssd.com");
394 :
395 : /* Mark the server as working and request the service again. The same server
396 : * must be returned */
397 2 : fo_set_server_status(srv, SERVER_WORKING);
398 :
399 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
400 : test_ctx->resolv, test_ctx->fo_ctx,
401 : test_ctx->fo_svc);
402 2 : assert_non_null(req);
403 2 : tevent_req_set_callback(req, test_fo_srv_done2, test_ctx);
404 2 : }
405 :
406 2 : static void test_fo_srv_done2(struct tevent_req *req)
407 : {
408 2 : struct test_fo_ctx *test_ctx = \
409 2 : tevent_req_callback_data(req, struct test_fo_ctx);
410 : struct fo_server *srv;
411 : errno_t ret;
412 :
413 2 : ret = fo_resolve_service_recv(req, &srv);
414 2 : talloc_zfree(req);
415 2 : assert_int_equal(ret, ERR_OK);
416 :
417 : /* Must be ldap1 again */
418 2 : check_server(test_ctx, srv, 389, "ldap1.sssd.com");
419 :
420 : /* Mark it at wrong, next lookup should yield ldap2 */
421 2 : fo_set_server_status(srv, SERVER_NOT_WORKING);
422 :
423 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
424 : test_ctx->resolv, test_ctx->fo_ctx,
425 : test_ctx->fo_svc);
426 2 : assert_non_null(req);
427 2 : tevent_req_set_callback(req, test_fo_srv_done3, test_ctx);
428 2 : }
429 :
430 2 : static void test_fo_srv_done3(struct tevent_req *req)
431 : {
432 2 : struct test_fo_ctx *test_ctx = \
433 2 : tevent_req_callback_data(req, struct test_fo_ctx);
434 : struct fo_server *srv;
435 : errno_t ret;
436 :
437 2 : ret = fo_resolve_service_recv(req, &srv);
438 2 : talloc_zfree(req);
439 2 : assert_int_equal(ret, ERR_OK);
440 :
441 : /* Must be ldap2 now */
442 2 : check_server(test_ctx, srv, 389, "ldap2.sssd.com");
443 :
444 : /* Mark is at wrong, next lookup must reach the end of the server list */
445 2 : fo_set_server_status(srv, SERVER_NOT_WORKING);
446 :
447 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
448 : test_ctx->resolv, test_ctx->fo_ctx,
449 : test_ctx->fo_svc);
450 2 : assert_non_null(req);
451 2 : tevent_req_set_callback(req, test_fo_srv_done4, test_ctx);
452 2 : }
453 :
454 2 : static void test_fo_srv_done4(struct tevent_req *req)
455 : {
456 2 : struct test_fo_ctx *test_ctx = \
457 2 : tevent_req_callback_data(req, struct test_fo_ctx);
458 : struct fo_server *srv;
459 : errno_t ret;
460 :
461 2 : ret = fo_resolve_service_recv(req, &srv);
462 2 : talloc_zfree(req);
463 : /* No servers are left..*/
464 2 : assert_int_equal(ret, ENOENT);
465 :
466 : /* reset the server status and try again.. */
467 2 : fo_reset_servers(test_ctx->fo_svc);
468 2 : if (test_ctx->srv_ctx) {
469 1 : test_fo_srv_mock_dns(test_ctx);
470 : }
471 :
472 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
473 : test_ctx->resolv, test_ctx->fo_ctx,
474 : test_ctx->fo_svc);
475 2 : assert_non_null(req);
476 2 : tevent_req_set_callback(req, test_fo_srv_done5, test_ctx);
477 2 : }
478 :
479 2 : static void test_fo_srv_done5(struct tevent_req *req)
480 : {
481 2 : struct test_fo_ctx *test_ctx = \
482 2 : tevent_req_callback_data(req, struct test_fo_ctx);
483 : struct fo_server *srv;
484 : errno_t ret;
485 :
486 2 : ret = fo_resolve_service_recv(req, &srv);
487 2 : talloc_zfree(req);
488 :
489 2 : assert_int_equal(ret, ERR_OK);
490 :
491 : /* ldap1.sssd.com has lower priority, it must always be first */
492 2 : check_server(test_ctx, srv, 389, "ldap1.sssd.com");
493 :
494 : /* OK, we made a full circle with the test, done */
495 2 : test_ctx->ctx->error = ERR_OK;
496 2 : test_ctx->ctx->done = true;
497 2 : }
498 :
499 : /* Make sure that two queries more than TTL seconds apart resolve
500 : * into two different lists
501 : */
502 : static void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx);
503 : static void test_fo_srv_before(struct tevent_req *req);
504 : static void test_fo_srv_after(struct tevent_req *req);
505 :
506 1 : void test_fo_srv_ttl_change(void **state)
507 : {
508 1 : struct test_fo_ctx *test_ctx =
509 1 : talloc_get_type(*state, struct test_fo_ctx);
510 :
511 1 : test_ctx->ttl = TEST_SRV_SHORT_TTL;
512 1 : test_fo_srv_ttl_change_step(test_ctx);
513 1 : }
514 :
515 2 : static void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx)
516 : {
517 : errno_t ret;
518 : struct tevent_req *req;
519 : struct ares_srv_reply *s1;
520 : struct ares_srv_reply *s2;
521 : char *dns_domain;
522 :
523 2 : s1 = talloc_zero(test_ctx, struct ares_srv_reply);
524 2 : assert_non_null(s1);
525 2 : s1->host = talloc_strdup(s1, "ldap1.sssd.com");
526 2 : assert_non_null(s1->host);
527 2 : s1->weight = 100;
528 2 : s1->priority = 1;
529 2 : s1->port = 389;
530 :
531 2 : s2 = talloc_zero(test_ctx, struct ares_srv_reply);
532 2 : assert_non_null(s2);
533 2 : s2->host = talloc_strdup(s2, "ldap2.sssd.com");
534 2 : assert_non_null(s2->host);
535 2 : s2->weight = 100;
536 2 : s2->priority = 2;
537 2 : s2->port = 389;
538 :
539 2 : s1->next = s2;
540 :
541 2 : dns_domain = talloc_strdup(test_ctx, "sssd.com");
542 2 : assert_non_null(dns_domain);
543 :
544 2 : mock_srv_results(s1, test_ctx->ttl, dns_domain);
545 :
546 2 : ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com",
547 : "sssd.local", "tcp", test_ctx);
548 2 : assert_int_equal(ret, ERR_OK);
549 :
550 2 : ret = fo_add_server(test_ctx->fo_svc, "ldap1.sssd.com",
551 : 389, (void *) discard_const("ldap://ldap1.sssd.com"),
552 : true);
553 2 : assert_int_equal(ret, ERR_OK);
554 :
555 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
556 : test_ctx->resolv, test_ctx->fo_ctx,
557 : test_ctx->fo_svc);
558 2 : assert_non_null(req);
559 2 : tevent_req_set_callback(req, test_fo_srv_before, test_ctx);
560 :
561 2 : ret = test_ev_loop(test_ctx->ctx);
562 2 : assert_int_equal(ret, ERR_OK);
563 2 : }
564 :
565 2 : static void test_fo_srv_before(struct tevent_req *req)
566 : {
567 2 : struct test_fo_ctx *test_ctx = \
568 2 : tevent_req_callback_data(req, struct test_fo_ctx);
569 : struct fo_server *srv;
570 : struct ares_srv_reply *s1;
571 : struct ares_srv_reply *s2;
572 : char *dns_domain;
573 : errno_t ret;
574 :
575 2 : ret = fo_resolve_service_recv(req, &srv);
576 2 : talloc_zfree(req);
577 2 : assert_int_equal(ret, ERR_OK);
578 :
579 2 : DEBUG(SSSDBG_TRACE_FUNC, "Before TTL change\n");
580 :
581 2 : check_server(test_ctx, srv, 389, "ldap1.sssd.com");
582 2 : fo_set_server_status(srv, SERVER_WORKING);
583 :
584 : /* Simulate changing the DNS environment. Change the host names */
585 2 : s1 = talloc_zero(test_ctx, struct ares_srv_reply);
586 2 : assert_non_null(s1);
587 2 : s1->host = talloc_strdup(s1, "ldap2.sssd.com");
588 2 : assert_non_null(s1->host);
589 2 : s1->weight = 100;
590 2 : s1->priority = 2;
591 2 : s1->port = 389;
592 :
593 2 : s2 = talloc_zero(test_ctx, struct ares_srv_reply);
594 2 : assert_non_null(s2);
595 2 : s2->host = talloc_strdup(s2, "ldap3.sssd.com");
596 2 : assert_non_null(s2->host);
597 2 : s2->weight = 100;
598 2 : s2->priority = 1;
599 2 : s2->port = 389;
600 :
601 2 : s1->next = s2;
602 :
603 2 : dns_domain = talloc_strdup(test_ctx, "sssd.com");
604 2 : assert_non_null(dns_domain);
605 :
606 2 : mock_srv_results(s1, test_ctx->ttl, dns_domain);
607 2 : sleep(test_ctx->ttl + 1);
608 :
609 2 : req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
610 : test_ctx->resolv, test_ctx->fo_ctx,
611 : test_ctx->fo_svc);
612 2 : assert_non_null(req);
613 2 : tevent_req_set_callback(req, test_fo_srv_after, test_ctx);
614 2 : }
615 :
616 2 : static void test_fo_srv_after(struct tevent_req *req)
617 : {
618 2 : struct test_fo_ctx *test_ctx = \
619 2 : tevent_req_callback_data(req, struct test_fo_ctx);
620 : struct fo_server *srv;
621 : errno_t ret;
622 :
623 2 : ret = fo_resolve_service_recv(req, &srv);
624 2 : talloc_zfree(req);
625 2 : assert_int_equal(ret, ERR_OK);
626 :
627 : /* Must be a different server now */
628 2 : check_server(test_ctx, srv, 389, "ldap3.sssd.com");
629 :
630 2 : test_ctx->ctx->error = ERR_OK;
631 2 : test_ctx->ctx->done = true;
632 2 : }
633 :
634 1 : void test_fo_srv_ttl_zero(void **state)
635 : {
636 1 : struct test_fo_ctx *test_ctx =
637 1 : talloc_get_type(*state, struct test_fo_ctx);
638 :
639 1 : test_ctx->ttl = 0;
640 1 : test_fo_srv_ttl_change_step(test_ctx);
641 1 : }
642 :
643 1 : static void test_fo_hostlist(void **state)
644 : {
645 : errno_t ret;
646 1 : struct test_fo_ctx *test_ctx =
647 1 : talloc_get_type(*state, struct test_fo_ctx);
648 :
649 1 : ret = fo_add_server(test_ctx->fo_svc,
650 : "ldap1.sssd.com", 389, test_ctx, true);
651 1 : assert_int_equal(ret, ERR_OK);
652 :
653 1 : ret = fo_add_server(test_ctx->fo_svc,
654 : "ldap2.sssd.com", 389, test_ctx, true);
655 1 : assert_int_equal(ret, ERR_OK);
656 :
657 1 : test_fo_srv_step1(test_ctx);
658 :
659 1 : ret = test_ev_loop(test_ctx->ctx);
660 1 : assert_int_equal(ret, ERR_OK);
661 1 : }
662 :
663 1 : int main(int argc, const char *argv[])
664 : {
665 : int rv;
666 : poptContext pc;
667 : int opt;
668 6 : struct poptOption long_options[] = {
669 : POPT_AUTOHELP
670 5 : SSSD_DEBUG_OPTS
671 : POPT_TABLEEND
672 : };
673 :
674 1 : const struct CMUnitTest tests[] = {
675 : cmocka_unit_test_setup_teardown(test_fo_hostlist,
676 : test_fo_setup,
677 : test_fo_teardown),
678 : cmocka_unit_test_setup_teardown(test_fo_srv,
679 : test_fo_srv_setup,
680 : test_fo_srv_teardown),
681 : cmocka_unit_test_setup_teardown(test_fo_srv_ttl_change,
682 : test_fo_srv_setup,
683 : test_fo_srv_teardown),
684 : cmocka_unit_test_setup_teardown(test_fo_srv_ttl_zero,
685 : test_fo_srv_setup,
686 : test_fo_srv_teardown),
687 : };
688 :
689 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
690 1 : debug_level = SSSDBG_INVALID;
691 :
692 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
693 1 : while((opt = poptGetNextOpt(pc)) != -1) {
694 : switch(opt) {
695 : default:
696 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
697 : poptBadOption(pc, 0), poptStrerror(opt));
698 0 : poptPrintUsage(pc, stderr, 0);
699 0 : return 1;
700 : }
701 : }
702 1 : poptFreeContext(pc);
703 :
704 1 : DEBUG_CLI_INIT(debug_level);
705 :
706 : /* Even though normally the tests should clean up after themselves
707 : * they might not after a failed run. Remove the old db to be sure */
708 1 : tests_set_cwd();
709 :
710 1 : rv = cmocka_run_group_tests(tests, NULL, NULL);
711 1 : return rv;
712 : }
|