test_fo_srv.c revision 57c5ea8825c7179fd93382dbcbb07e828e5aec19
132N/A/*
132N/A Authors:
132N/A Jakub Hrozek <jhrozek@redhat.com>
132N/A
132N/A Copyright (C) 2014 Red Hat
132N/A
132N/A SSSD tests: Resolver tests using a fake resolver library
132N/A
132N/A This program is free software; you can redistribute it and/or modify
132N/A it under the terms of the GNU General Public License as published by
132N/A the Free Software Foundation; either version 3 of the License, or
132N/A (at your option) any later version.
132N/A
132N/A This program is distributed in the hope that it will be useful,
132N/A but WITHOUT ANY WARRANTY; without even the implied warranty of
132N/A MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
132N/A GNU General Public License for more details.
132N/A
132N/A You should have received a copy of the GNU General Public License
132N/A along with this program. If not, see <http://www.gnu.org/licenses/>.
1149N/A*/
132N/A
132N/A#include <talloc.h>
215N/A#include <tevent.h>
132N/A#include <errno.h>
1215N/A#include <popt.h>
1215N/A#include <arpa/inet.h>
1318N/A#include <netinet/in.h>
1176N/A#include <sys/types.h>
132N/A#include <stdarg.h>
132N/A#include <stdlib.h>
132N/A
132N/A#include "providers/fail_over_srv.h"
132N/A#include "tests/cmocka/common_mock.h"
132N/A#include "tests/cmocka/common_mock_resp.h"
132N/A
132N/A#define TEST_RESOLV_TIMEOUT 5
132N/A#define TEST_FO_TIMEOUT 3000
132N/A#define TEST_SRV_TTL 500
132N/A#define TEST_SRV_SHORT_TTL 2
132N/A
132N/Astatic TALLOC_CTX *global_mock_context = NULL;
132N/A
132N/Aenum host_database default_host_dbs[] = { DB_FILES, DB_DNS, DB_SENTINEL };
132N/A
132N/Astruct resolv_ctx {
132N/A int foo;
132N/A};
132N/A
132N/A/* mock resolver interface. The resolver test is separate */
132N/Aint resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
132N/A int timeout, struct resolv_ctx **ctxp)
132N/A{
132N/A *ctxp = talloc(mem_ctx, struct resolv_ctx);
132N/A return EOK;
132N/A}
132N/A
132N/Astruct tevent_req *
132N/Aresolv_gethostbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
132N/A struct resolv_ctx *ctx, const char *name,
132N/A enum restrict_family family_order,
132N/A enum host_database *db)
132N/A{
132N/A return test_req_succeed_send(mem_ctx, ev);
132N/A}
132N/A
132N/Aint resolv_gethostbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
132N/A int *status, int *timeouts,
132N/A struct resolv_hostent **rhostent)
132N/A{
132N/A return test_request_recv(req);
132N/A}
132N/A
132N/Aconst char *resolv_strerror(int ares_code)
132N/A{
132N/A return NULL;
132N/A}
132N/A
132N/Astruct tevent_req *resolv_discover_srv_send(TALLOC_CTX *mem_ctx,
132N/A struct tevent_context *ev,
132N/A struct resolv_ctx *resolv_ctx,
132N/A const char *service,
132N/A const char *protocol,
132N/A const char **discovery_domains)
132N/A{
132N/A return test_req_succeed_send(mem_ctx, ev);
132N/A}
132N/A
132N/Aerrno_t resolv_discover_srv_recv(TALLOC_CTX *mem_ctx,
132N/A struct tevent_req *req,
132N/A struct ares_srv_reply **_reply_list,
132N/A uint32_t *_ttl,
219N/A char **_dns_domain)
1318N/A{
220N/A struct ares_srv_reply *reply_list;
1176N/A uint32_t ttl;
1176N/A char *dns_domain;
341N/A
341N/A /* Need to always consume all mocked values */
379N/A reply_list = sss_mock_ptr_type(struct ares_srv_reply *);
411N/A ttl = sss_mock_ptr_type(uint32_t);
487N/A dns_domain = sss_mock_ptr_type(char *);
706N/A
706N/A if (_reply_list != NULL) {
706N/A *_reply_list = reply_list;
741N/A }
741N/A
706N/A if (_ttl != NULL) {
706N/A *_ttl = ttl;
736N/A }
487N/A
704N/A if (_dns_domain != NULL) {
487N/A *_dns_domain = dns_domain;
704N/A }
1215N/A
1215N/A return test_request_recv(req);
487N/A}
487N/A
320N/Astruct ares_srv_reply *pop_lowest_prio(struct ares_srv_reply **r)
336N/A{
336N/A struct ares_srv_reply *lowest;
336N/A struct ares_srv_reply *iter;
1215N/A struct ares_srv_reply *prev;
1215N/A
336N/A lowest = *r;
336N/A iter = lowest;
336N/A while (iter != NULL) {
341N/A if (iter->priority < lowest->priority) {
487N/A lowest = iter;
336N/A }
336N/A
336N/A iter = iter->next;
379N/A }
379N/A
487N/A prev = NULL;
379N/A iter = *r;
379N/A while (iter != lowest) {
411N/A prev = iter;
411N/A iter = iter->next;
487N/A }
411N/A
411N/A /* iter points to the lowest prio. Prev points to the item before */
411N/A if (prev) {
320N/A prev->next = lowest->next;
336N/A } else {
320N/A *r = lowest->next;
336N/A }
1031N/A
1031N/A return lowest;
132N/A}
949N/A
1215N/Aint resolv_sort_srv_reply(struct ares_srv_reply **reply)
949N/A{
949N/A struct ares_srv_reply *r;
949N/A struct ares_srv_reply *lowest;
949N/A struct ares_srv_reply *sorted = NULL;
949N/A struct ares_srv_reply *sorted_head = NULL;
949N/A
949N/A r = *reply;
949N/A if (r == NULL || r->next == NULL) {
1272N/A return EOK;
1272N/A }
1028N/A
1028N/A do {
1072N/A lowest = pop_lowest_prio(&r);
1072N/A if (sorted) {
1215N/A sorted->next = lowest;
1215N/A sorted = sorted->next;
949N/A } else {
949N/A sorted = lowest;
949N/A sorted_head = sorted;
949N/A }
949N/A } while (r != NULL);
949N/A
949N/A *reply = sorted_head;
949N/A return EOK;
949N/A}
949N/A
949N/Astruct tevent_req *resolv_get_domain_send(TALLOC_CTX *mem_ctx,
949N/A struct tevent_context *ev,
949N/A struct resolv_ctx *resolv_ctx,
1256N/A const char *hostname,
1256N/A enum host_database *host_dbs,
1275N/A enum restrict_family family_order)
1275N/A{
949N/A return test_req_succeed_send(mem_ctx, ev);
949N/A}
132N/A
132N/Aerrno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx,
230N/A struct tevent_req *req,
989N/A char **_dns_domain)
989N/A{
989N/A return test_request_recv(req);
989N/A}
989N/A
989N/A/* The unit test */
230N/Astruct test_fo_ctx {
230N/A struct resolv_ctx *resolv;
230N/A struct fo_ctx *fo_ctx;
935N/A struct fo_resolve_srv_dns_ctx *srv_ctx;
935N/A struct fo_service *fo_svc;
230N/A struct sss_test_ctx *ctx;
230N/A int ttl;
230N/A
989N/A struct fo_server *srv;
989N/A
989N/A int num_done;
989N/A};
1215N/A
989N/Aint test_fo_srv_data_cmp(void *ud1, void *ud2)
989N/A{
989N/A return strcasecmp((char*) ud1, (char*) ud2);
989N/A}
989N/A
989N/Astatic int test_fo_setup(void **state)
989N/A{
989N/A struct test_fo_ctx *test_ctx;
989N/A errno_t ret;
1215N/A struct fo_options fopts;
1215N/A
1215N/A assert_true(leak_check_setup());
989N/A global_mock_context = talloc_new(global_talloc_context);
989N/A assert_non_null(global_mock_context);
1215N/A
989N/A test_ctx = talloc_zero(global_mock_context,
989N/A struct test_fo_ctx);
989N/A assert_non_null(test_ctx);
989N/A
230N/A test_ctx->ctx = create_ev_test_ctx(test_ctx);
230N/A assert_non_null(test_ctx->ctx);
230N/A
230N/A ret = resolv_init(test_ctx, test_ctx->ctx->ev,
230N/A TEST_RESOLV_TIMEOUT, &test_ctx->resolv);
230N/A assert_non_null(test_ctx->resolv);
230N/A
230N/A memset(&fopts, 0, sizeof(fopts));
301N/A fopts.retry_timeout = TEST_FO_TIMEOUT;
1318N/A fopts.family_order = IPV4_FIRST;
132N/A
949N/A test_ctx->fo_ctx = fo_context_init(test_ctx, &fopts);
213N/A assert_non_null(test_ctx->fo_ctx);
301N/A
741N/A ret = fo_new_service(test_ctx->fo_ctx, "ldap",
132N/A test_fo_srv_data_cmp,
1318N/A &test_ctx->fo_svc);
1318N/A assert_int_equal(ret, ERR_OK);
1318N/A
1318N/A *state = test_ctx;
1318N/A return 0;
132N/A}
211N/A
213N/Astatic int test_fo_teardown(void **state)
213N/A{
213N/A struct test_fo_ctx *test_ctx =
213N/A talloc_get_type(*state, struct test_fo_ctx);
213N/A
1215N/A talloc_free(test_ctx);
213N/A talloc_free(global_mock_context);
213N/A assert_true(leak_check_teardown());
487N/A return 0;
213N/A}
213N/A
213N/Astatic int test_fo_srv_setup(void **state)
213N/A{
213N/A struct test_fo_ctx *test_ctx;
213N/A bool ok;
1215N/A
1215N/A test_fo_setup(state);
1215N/A test_ctx = *state;
1215N/A
1215N/A test_ctx->srv_ctx = fo_resolve_srv_dns_ctx_init(test_ctx, test_ctx->resolv,
1215N/A IPV4_FIRST, default_host_dbs,
1215N/A "client.sssd.com", "sssd.local");
213N/A assert_non_null(test_ctx->srv_ctx);
213N/A
213N/A ok = fo_set_srv_lookup_plugin(test_ctx->fo_ctx,
213N/A fo_resolve_srv_dns_send,
1215N/A fo_resolve_srv_dns_recv,
1215N/A test_ctx->srv_ctx);
845N/A assert_true(ok);
1215N/A
213N/A *state = test_ctx;
213N/A return 0;
230N/A}
213N/A
213N/Astatic int test_fo_srv_teardown(void **state)
211N/A{
211N/A test_fo_teardown(state);
211N/A return 0;
211N/A}
211N/A
1215N/A/* reply_list and dns_domain must be a talloc context so it can be used as
1215N/A * talloc_steal argument later
1215N/A */
1215N/Astatic void mock_srv_results(struct ares_srv_reply *reply_list,
1215N/A uint32_t ttl,
1215N/A char *dns_domain)
211N/A{
1318N/A will_return(resolv_discover_srv_recv, reply_list);
1318N/A will_return(resolv_discover_srv_recv, ttl);
1318N/A will_return(resolv_discover_srv_recv, dns_domain);
1318N/A}
1318N/A
1318N/Astatic void check_server(struct test_fo_ctx *ctx,
1318N/A struct fo_server *srv,
1318N/A int port,
1318N/A const char *name)
1318N/A{
1318N/A assert_non_null(srv);
1318N/A assert_int_equal(fo_get_server_port(srv), port);
1318N/A assert_string_equal(fo_get_server_name(srv), name);
1318N/A
1318N/A
1318N/A if (ctx->srv_ctx) {
1318N/A assert_true(fo_is_srv_lookup(srv));
1318N/A }
1318N/A}
1318N/A
1318N/Astatic void test_fo_srv_step1(struct test_fo_ctx *test_ctx);
1318N/Astatic void test_fo_srv_done1(struct tevent_req *req);
1318N/Astatic void test_fo_srv_done2(struct tevent_req *req);
1318N/Astatic void test_fo_srv_done3(struct tevent_req *req);
1318N/Astatic void test_fo_srv_done4(struct tevent_req *req);
1318N/Astatic void test_fo_srv_done5(struct tevent_req *req);
1318N/A
1318N/A
1318N/Astruct ares_srv_reply *
132N/Amock_ares_reply(TALLOC_CTX *mem_ctx, const char *hostname,
211N/A int weight, int priority, int port)
1215N/A{
950N/A struct ares_srv_reply *s;
144N/A
453N/A s = talloc_zero(mem_ctx, struct ares_srv_reply);
144N/A if (s == NULL) {
260N/A return NULL;
260N/A }
260N/A
260N/A s->host = talloc_strdup(s, hostname);
260N/A if (s->host == NULL) {
260N/A talloc_free(s);
260N/A return NULL;
260N/A }
144N/A
219N/A s->weight = weight;
219N/A s->priority = priority;
1215N/A s->port = port;
1215N/A
1215N/A return s;
1215N/A}
1215N/A
1215N/Astatic void test_fo_srv_mock_dns(struct test_fo_ctx *test_ctx,
219N/A int ttl)
220N/A{
220N/A struct ares_srv_reply *s1;
1215N/A struct ares_srv_reply *s2;
220N/A char *dns_domain;
1215N/A
1215N/A s1 = mock_ares_reply(test_ctx, "ldap1.sssd.com", 100, 1, 389);
1215N/A assert_non_null(s1);
1215N/A
1215N/A s2 = mock_ares_reply(test_ctx, "ldap2.sssd.com", 100, 2, 389);
1215N/A assert_non_null(s2);
1215N/A
1215N/A s1->next = s2;
1215N/A
1215N/A dns_domain = talloc_strdup(test_ctx, "sssd.com");
1215N/A assert_non_null(dns_domain);
1215N/A
1215N/A mock_srv_results(s1, ttl, dns_domain);
1215N/A}
1215N/A
1215N/Astatic void test_fo_srv(void **state)
1215N/A{
1215N/A errno_t ret;
1215N/A struct test_fo_ctx *test_ctx =
1215N/A talloc_get_type(*state, struct test_fo_ctx);
1215N/A
1215N/A test_fo_srv_mock_dns(test_ctx, TEST_SRV_TTL);
1215N/A
1215N/A ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com",
220N/A "sssd.local", "tcp", test_ctx);
220N/A assert_int_equal(ret, ERR_OK);
221N/A
1215N/A test_fo_srv_step1(test_ctx);
1215N/A
1215N/A ret = test_ev_loop(test_ctx->ctx);
1215N/A assert_int_equal(ret, ERR_OK);
1215N/A}
981N/A
981N/Astatic void test_fo_srv_step1(struct test_fo_ctx *test_ctx)
1215N/A{
1215N/A struct tevent_req *req;
221N/A
295N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
336N/A test_ctx->resolv, test_ctx->fo_ctx,
336N/A test_ctx->fo_svc);
336N/A assert_non_null(req);
336N/A tevent_req_set_callback(req, test_fo_srv_done1, test_ctx);
341N/A}
336N/A
336N/Astatic void test_fo_srv_done1(struct tevent_req *req)
336N/A{
336N/A struct test_fo_ctx *test_ctx = \
341N/A tevent_req_callback_data(req, struct test_fo_ctx);
336N/A struct fo_server *srv;
336N/A errno_t ret;
879N/A
336N/A ret = fo_resolve_service_recv(req, req, &srv);
341N/A talloc_zfree(req);
341N/A assert_int_equal(ret, ERR_OK);
336N/A
336N/A /* ldap1.sssd.com has lower priority, it must always be first */
295N/A check_server(test_ctx, srv, 389, "ldap1.sssd.com");
341N/A
295N/A /* Mark the server as working and request the service again. The same server
295N/A * must be returned */
295N/A fo_set_server_status(srv, SERVER_WORKING);
295N/A
295N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
295N/A test_ctx->resolv, test_ctx->fo_ctx,
295N/A test_ctx->fo_svc);
295N/A assert_non_null(req);
295N/A tevent_req_set_callback(req, test_fo_srv_done2, test_ctx);
301N/A}
879N/A
339N/Astatic void test_fo_srv_done2(struct tevent_req *req)
341N/A{
341N/A struct test_fo_ctx *test_ctx = \
339N/A tevent_req_callback_data(req, struct test_fo_ctx);
339N/A struct fo_server *srv;
339N/A errno_t ret;
341N/A
339N/A ret = fo_resolve_service_recv(req, req, &srv);
339N/A talloc_zfree(req);
339N/A assert_int_equal(ret, ERR_OK);
339N/A
339N/A /* Must be ldap1 again */
339N/A check_server(test_ctx, srv, 389, "ldap1.sssd.com");
339N/A
339N/A /* Mark it at wrong, next lookup should yield ldap2 */
339N/A fo_set_server_status(srv, SERVER_NOT_WORKING);
379N/A
379N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
379N/A test_ctx->resolv, test_ctx->fo_ctx,
379N/A test_ctx->fo_svc);
379N/A assert_non_null(req);
379N/A tevent_req_set_callback(req, test_fo_srv_done3, test_ctx);
411N/A}
379N/A
379N/Astatic void test_fo_srv_done3(struct tevent_req *req)
379N/A{
386N/A struct test_fo_ctx *test_ctx = \
379N/A tevent_req_callback_data(req, struct test_fo_ctx);
1024N/A struct fo_server *srv;
379N/A errno_t ret;
379N/A
379N/A ret = fo_resolve_service_recv(req, req, &srv);
379N/A talloc_zfree(req);
411N/A assert_int_equal(ret, ERR_OK);
411N/A
411N/A /* Must be ldap2 now */
411N/A check_server(test_ctx, srv, 389, "ldap2.sssd.com");
411N/A
411N/A /* Mark is at wrong, next lookup must reach the end of the server list */
411N/A fo_set_server_status(srv, SERVER_NOT_WORKING);
411N/A
411N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
411N/A test_ctx->resolv, test_ctx->fo_ctx,
411N/A test_ctx->fo_svc);
411N/A assert_non_null(req);
411N/A tevent_req_set_callback(req, test_fo_srv_done4, test_ctx);
411N/A}
411N/A
411N/Astatic void test_fo_srv_done4(struct tevent_req *req)
482N/A{
411N/A struct test_fo_ctx *test_ctx = \
411N/A tevent_req_callback_data(req, struct test_fo_ctx);
411N/A struct fo_server *srv;
1072N/A errno_t ret;
1072N/A
1072N/A ret = fo_resolve_service_recv(req, req, &srv);
411N/A talloc_zfree(req);
463N/A /* No servers are left..*/
411N/A assert_int_equal(ret, ENOENT);
339N/A
996N/A /* reset the server status and try again.. */
1215N/A fo_reset_servers(test_ctx->fo_svc);
996N/A if (test_ctx->srv_ctx) {
996N/A test_fo_srv_mock_dns(test_ctx, TEST_SRV_TTL);
1215N/A }
1215N/A
1215N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
1215N/A test_ctx->resolv, test_ctx->fo_ctx,
1215N/A test_ctx->fo_svc);
1215N/A assert_non_null(req);
1215N/A tevent_req_set_callback(req, test_fo_srv_done5, test_ctx);
1215N/A}
1215N/A
1215N/Astatic void test_fo_srv_done5(struct tevent_req *req)
996N/A{
996N/A struct test_fo_ctx *test_ctx = \
996N/A tevent_req_callback_data(req, struct test_fo_ctx);
1215N/A struct fo_server *srv;
996N/A errno_t ret;
996N/A
1215N/A ret = fo_resolve_service_recv(req, req, &srv);
1215N/A talloc_zfree(req);
1215N/A
1215N/A assert_int_equal(ret, ERR_OK);
1215N/A
1215N/A /* ldap1.sssd.com has lower priority, it must always be first */
1215N/A check_server(test_ctx, srv, 389, "ldap1.sssd.com");
1215N/A
1215N/A /* OK, we made a full circle with the test, done */
1215N/A test_ctx->ctx->error = ERR_OK;
996N/A test_ctx->ctx->done = true;
996N/A}
336N/A
381N/A/* Make sure that two queries more than TTL seconds apart resolve
336N/A * into two different lists
336N/A */
336N/Astatic void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx);
336N/Astatic void test_fo_srv_before(struct tevent_req *req);
336N/Astatic void test_fo_srv_after(struct tevent_req *req);
336N/A
336N/Avoid test_fo_srv_ttl_change(void **state)
336N/A{
336N/A struct test_fo_ctx *test_ctx =
336N/A talloc_get_type(*state, struct test_fo_ctx);
336N/A
301N/A test_ctx->ttl = TEST_SRV_SHORT_TTL;
301N/A test_fo_srv_ttl_change_step(test_ctx);
301N/A}
301N/A
301N/Astatic void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx)
301N/A{
301N/A errno_t ret;
301N/A struct tevent_req *req;
301N/A
301N/A test_fo_srv_mock_dns(test_ctx, test_ctx->ttl);
691N/A
301N/A ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com",
301N/A "sssd.local", "tcp", test_ctx);
301N/A assert_int_equal(ret, ERR_OK);
301N/A
301N/A ret = fo_add_server(test_ctx->fo_svc, "ldap1.sssd.com",
301N/A 389, (void *) discard_const("ldap://ldap1.sssd.com"),
448N/A true);
446N/A assert_int_equal(ret, ERR_OK);
448N/A
500N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
736N/A test_ctx->resolv, test_ctx->fo_ctx,
706N/A test_ctx->fo_svc);
706N/A assert_non_null(req);
807N/A tevent_req_set_callback(req, test_fo_srv_before, test_ctx);
1215N/A
455N/A ret = test_ev_loop(test_ctx->ctx);
706N/A assert_int_equal(ret, ERR_OK);
706N/A}
455N/A
706N/Astatic void test_fo_srv_before(struct tevent_req *req)
455N/A{
480N/A struct test_fo_ctx *test_ctx = \
706N/A tevent_req_callback_data(req, struct test_fo_ctx);
480N/A struct ares_srv_reply *s1;
480N/A struct ares_srv_reply *s2;
455N/A char *dns_domain;
706N/A errno_t ret;
455N/A
480N/A ret = fo_resolve_service_recv(req, test_ctx, &test_ctx->srv);
480N/A talloc_zfree(req);
741N/A assert_int_equal(ret, ERR_OK);
741N/A
500N/A DEBUG(SSSDBG_TRACE_FUNC, "Before TTL change\n");
500N/A
500N/A check_server(test_ctx, test_ctx->srv, 389, "ldap1.sssd.com");
1215N/A fo_set_server_status(test_ctx->srv, SERVER_WORKING);
1215N/A
1215N/A /* Simulate changing the DNS environment. Change the host names */
1215N/A s1 = mock_ares_reply(test_ctx, "ldap1.sssd.com", 100, 2, 389);
1215N/A assert_non_null(s1);
1215N/A
1215N/A s2 = mock_ares_reply(test_ctx, "ldap2.sssd.com", 100, 1, 389);
725N/A assert_non_null(s2);
725N/A
1215N/A s1->next = s2;
1215N/A
1215N/A dns_domain = talloc_strdup(test_ctx, "sssd.com");
1215N/A assert_non_null(dns_domain);
725N/A
1215N/A mock_srv_results(s1, test_ctx->ttl, dns_domain);
1215N/A sleep(test_ctx->ttl + 1);
1215N/A
1215N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
1215N/A test_ctx->resolv, test_ctx->fo_ctx,
1215N/A test_ctx->fo_svc);
1215N/A assert_non_null(req);
1215N/A tevent_req_set_callback(req, test_fo_srv_after, test_ctx);
1215N/A}
1215N/A
1215N/Astatic void test_fo_srv_after2(struct tevent_req *req);
1215N/A
301N/Astatic void test_fo_srv_after(struct tevent_req *req)
301N/A{
736N/A struct test_fo_ctx *test_ctx = \
1215N/A tevent_req_callback_data(req, struct test_fo_ctx);
1215N/A struct fo_server *srv;
1215N/A errno_t ret;
1215N/A struct ares_srv_reply *s1;
1215N/A struct ares_srv_reply *s2;
1215N/A char *dns_domain;
1215N/A
736N/A ret = fo_resolve_service_recv(req, req, &srv);
736N/A talloc_zfree(req);
736N/A assert_int_equal(ret, ERR_OK);
736N/A
736N/A /* Try accessing server from a previous iteration. The
736N/A * server should be collapsed, but at least we shouldn't crash
736N/A */
736N/A fo_set_server_status(test_ctx->srv, SERVER_WORKING);
736N/A
736N/A sleep(test_ctx->ttl + 1);
736N/A
736N/A /* Must be a different server now */
741N/A check_server(test_ctx, srv, 389, "ldap2.sssd.com");
741N/A
1215N/A /* Simulate changing the DNS environment. Change the host names */
1215N/A s1 = mock_ares_reply(test_ctx, "ldap1.sssd.com", 100, 1, 389);
1215N/A assert_non_null(s1);
1215N/A
1215N/A s2 = mock_ares_reply(test_ctx, "ldap2.sssd.com", 100, 2, 389);
736N/A assert_non_null(s2);
736N/A
336N/A s1->next = s2;
301N/A
301N/A dns_domain = talloc_strdup(test_ctx, "sssd.com");
501N/A assert_non_null(dns_domain);
301N/A
301N/A mock_srv_results(s1, test_ctx->ttl, dns_domain);
301N/A sleep(test_ctx->ttl + 1);
301N/A
301N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
301N/A test_ctx->resolv, test_ctx->fo_ctx,
301N/A test_ctx->fo_svc);
301N/A assert_non_null(req);
301N/A tevent_req_set_callback(req, test_fo_srv_after2, test_ctx);
449N/A}
624N/A
624N/Astatic void test_fo_srv_after2(struct tevent_req *req)
624N/A{
624N/A struct test_fo_ctx *test_ctx = \
624N/A tevent_req_callback_data(req, struct test_fo_ctx);
624N/A struct fo_server *srv;
624N/A errno_t ret;
624N/A
624N/A ret = fo_resolve_service_recv(req, req, &srv);
624N/A talloc_zfree(req);
624N/A assert_int_equal(ret, ERR_OK);
624N/A
624N/A /* Must be a different server now */
624N/A check_server(test_ctx, srv, 389, "ldap1.sssd.com");
624N/A
624N/A test_ctx->ctx->error = ERR_OK;
624N/A test_ctx->ctx->done = true;
624N/A}
624N/A
624N/Avoid test_fo_srv_ttl_zero(void **state)
624N/A{
624N/A struct test_fo_ctx *test_ctx =
624N/A talloc_get_type(*state, struct test_fo_ctx);
801N/A
801N/A test_ctx->ttl = 0;
801N/A test_fo_srv_ttl_change_step(test_ctx);
801N/A}
801N/A
801N/Astatic void test_fo_hostlist(void **state)
801N/A{
801N/A errno_t ret;
801N/A struct test_fo_ctx *test_ctx =
801N/A talloc_get_type(*state, struct test_fo_ctx);
1095N/A
1095N/A ret = fo_add_server(test_ctx->fo_svc,
1215N/A "ldap1.sssd.com", 389, test_ctx, true);
1215N/A assert_int_equal(ret, ERR_OK);
1099N/A
1215N/A ret = fo_add_server(test_ctx->fo_svc,
1215N/A "ldap2.sssd.com", 389, test_ctx, true);
1215N/A assert_int_equal(ret, ERR_OK);
1095N/A
1095N/A test_fo_srv_step1(test_ctx);
1176N/A
1176N/A ret = test_ev_loop(test_ctx->ctx);
1215N/A assert_int_equal(ret, ERR_OK);
1215N/A}
1215N/A
1215N/Astatic void test_fo_srv_dup_done(struct tevent_req *req);
1215N/A
1215N/A/* Test that running two parallel SRV queries doesn't return an error.
1215N/A * This is a regression test for https://fedorahosted.org/sssd/ticket/3131
1176N/A */
1215N/Avoid test_fo_srv_duplicates(void **state)
1215N/A{
1215N/A errno_t ret;
1176N/A struct tevent_req *req;
1215N/A struct test_fo_ctx *test_ctx =
1215N/A talloc_get_type(*state, struct test_fo_ctx);
1215N/A
1215N/A test_fo_srv_mock_dns(test_ctx, test_ctx->ttl);
1215N/A test_fo_srv_mock_dns(test_ctx, test_ctx->ttl);
1215N/A
1215N/A ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com",
1215N/A "sssd.local", "tcp", test_ctx);
1217N/A assert_int_equal(ret, ERR_OK);
1215N/A
1215N/A ret = fo_add_server(test_ctx->fo_svc, "ldap1.sssd.com",
1215N/A 389, (void *) discard_const("ldap://ldap1.sssd.com"),
1176N/A true);
1215N/A assert_int_equal(ret, ERR_OK);
1215N/A
1215N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
1215N/A test_ctx->resolv, test_ctx->fo_ctx,
1215N/A test_ctx->fo_svc);
1215N/A assert_non_null(req);
1215N/A tevent_req_set_callback(req, test_fo_srv_dup_done, test_ctx);
1215N/A
1215N/A req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
1215N/A test_ctx->resolv, test_ctx->fo_ctx,
1215N/A test_ctx->fo_svc);
1215N/A assert_non_null(req);
1215N/A tevent_req_set_callback(req, test_fo_srv_dup_done, test_ctx);
1215N/A
1215N/A ret = test_ev_loop(test_ctx->ctx);
1215N/A assert_int_equal(ret, ERR_OK);
1215N/A}
1176N/A
1215N/Astatic void test_fo_srv_dup_done(struct tevent_req *req)
1215N/A{
1215N/A struct test_fo_ctx *test_ctx = \
1215N/A tevent_req_callback_data(req, struct test_fo_ctx);
1176N/A errno_t ret;
1215N/A const char *name;
1215N/A
1215N/A ret = fo_resolve_service_recv(req, test_ctx, &test_ctx->srv);
1215N/A talloc_zfree(req);
1176N/A assert_int_equal(ret, EOK);
1215N/A
1215N/A name = fo_get_server_name(test_ctx->srv);
1215N/A assert_string_equal(name, "ldap1.sssd.com");
1215N/A
1215N/A test_ctx->num_done++;
1176N/A if (test_ctx->num_done == 2) {
1215N/A test_ctx->ctx->error = ERR_OK;
1215N/A test_ctx->ctx->done = true;
1176N/A }
1215N/A}
1215N/A
1176N/Aint main(int argc, const char *argv[])
1215N/A{
1215N/A int rv;
1215N/A poptContext pc;
1215N/A int opt;
1215N/A struct poptOption long_options[] = {
1215N/A POPT_AUTOHELP
1215N/A SSSD_DEBUG_OPTS
1215N/A POPT_TABLEEND
1215N/A };
1176N/A
1176N/A const struct CMUnitTest tests[] = {
1176N/A cmocka_unit_test_setup_teardown(test_fo_hostlist,
1176N/A test_fo_setup,
1176N/A test_fo_teardown),
1176N/A cmocka_unit_test_setup_teardown(test_fo_srv,
1176N/A test_fo_srv_setup,
1176N/A test_fo_srv_teardown),
1176N/A cmocka_unit_test_setup_teardown(test_fo_srv_ttl_change,
1215N/A test_fo_srv_setup,
1215N/A test_fo_srv_teardown),
1176N/A cmocka_unit_test_setup_teardown(test_fo_srv_ttl_zero,
1215N/A test_fo_srv_setup,
1215N/A test_fo_srv_teardown),
1176N/A cmocka_unit_test_setup_teardown(test_fo_srv_duplicates,
1215N/A test_fo_srv_setup,
1215N/A test_fo_srv_teardown),
1215N/A };
1176N/A
1215N/A /* Set debug level to invalid value so we can decide if -d 0 was used. */
1176N/A debug_level = SSSDBG_INVALID;
1176N/A
1215N/A pc = poptGetContext(argv[0], argc, argv, long_options, 0);
1176N/A while((opt = poptGetNextOpt(pc)) != -1) {
1176N/A switch(opt) {
1176N/A default:
1176N/A fprintf(stderr, "\nInvalid option %s: %s\n\n",
1176N/A poptBadOption(pc, 0), poptStrerror(opt));
1215N/A poptPrintUsage(pc, stderr, 0);
1215N/A return 1;
1215N/A }
1176N/A }
1216N/A poptFreeContext(pc);
132N/A
DEBUG_CLI_INIT(debug_level);
/* Even though normally the tests should clean up after themselves
* they might not after a failed run. Remove the old DB to be sure */
tests_set_cwd();
rv = cmocka_run_group_tests(tests, NULL, NULL);
return rv;
}