From 802220cc4ef437d8f169c51c7ce073a51f507b92 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 24 Feb 2014 15:42:51 +0100 Subject: DP: Provide separate dp_copy_defaults function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://fedorahosted.org/sssd/ticket/2257 Reviewed-by: Pavel Březina (cherry picked from commit 90afedb00608547ae1f32aa7aafd552c4b306909) --- Makefile.am | 12 ++ src/providers/ad/ad_common.c | 16 +- src/providers/data_provider.h | 5 + src/providers/data_provider_opts.c | 42 ++-- src/tests/cmocka/test_dp_opts.c | 421 +++++++++++++++++++++++++++++++++++++ src/tests/ipa_ldap_opt-tests.c | 2 +- 6 files changed, 476 insertions(+), 22 deletions(-) create mode 100644 src/tests/cmocka/test_dp_opts.c diff --git a/Makefile.am b/Makefile.am index f490bc39a..d9d41df5f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -154,6 +154,7 @@ if HAVE_CMOCKA test_utils \ ad_access_filter_tests \ ad_common_tests \ + dp_opt_tests \ test_search_bases endif @@ -1456,6 +1457,17 @@ ad_common_tests_LDADD = \ libsss_krb5_common.la \ libsss_test_common.la +dp_opt_tests_SOURCES = \ + src/providers/data_provider_opts.c \ + src/tests/cmocka/test_dp_opts.c +dp_opt_tests_CFLAGS = \ + $(AM_CFLAGS) +dp_opt_tests_LDADD = \ + $(CMOCKA_LIBS) \ + $(TALLOC_LIBS) \ + $(SSSD_INTERNAL_LTLIBS) \ + libsss_test_common.la + endif noinst_PROGRAMS = pam_test_client diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c index 99fa4c07a..605de49f7 100644 --- a/src/providers/ad/ad_common.c +++ b/src/providers/ad/ad_common.c @@ -44,10 +44,10 @@ ad_create_default_sdap_options(TALLOC_CTX *mem_ctx) return NULL; } - ret = dp_copy_options(id_opts, - ad_def_ldap_opts, - SDAP_OPTS_BASIC, - &id_opts->basic); + ret = dp_copy_defaults(id_opts, + ad_def_ldap_opts, + SDAP_OPTS_BASIC, + &id_opts->basic); if (ret != EOK) { goto fail; } @@ -117,10 +117,10 @@ ad_create_default_options(TALLOC_CTX *mem_ctx, ad_options = talloc_zero(mem_ctx, struct ad_options); if (ad_options == NULL) return NULL; - ret = dp_copy_options(ad_options, - ad_basic_opts, - AD_OPTS_BASIC, - &ad_options->basic); + ret = dp_copy_defaults(ad_options, + ad_basic_opts, + AD_OPTS_BASIC, + &ad_options->basic); if (ret != EOK) { talloc_free(ad_options); return NULL; diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index d086d5d2f..d86ff58e6 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -295,6 +295,11 @@ int dp_copy_options(TALLOC_CTX *memctx, int num_opts, struct dp_option **_opts); +int dp_copy_defaults(TALLOC_CTX *memctx, + struct dp_option *src_opts, + int num_opts, + struct dp_option **_opts); + const char *_dp_opt_get_cstring(struct dp_option *opts, int id, const char *location); char *_dp_opt_get_string(struct dp_option *opts, diff --git a/src/providers/data_provider_opts.c b/src/providers/data_provider_opts.c index 5a2e3b74d..0cc48e46e 100644 --- a/src/providers/data_provider_opts.c +++ b/src/providers/data_provider_opts.c @@ -131,11 +131,11 @@ done: } /* =Basic-Option-Helpers================================================== */ - -int dp_copy_options(TALLOC_CTX *memctx, - struct dp_option *src_opts, - int num_opts, - struct dp_option **_opts) +static int dp_copy_options_ex(TALLOC_CTX *memctx, + bool copy_values, + struct dp_option *src_opts, + int num_opts, + struct dp_option **_opts) { struct dp_option *opts; int i, ret = EOK; @@ -151,9 +151,9 @@ int dp_copy_options(TALLOC_CTX *memctx, switch (src_opts[i].type) { case DP_OPT_STRING: - if (src_opts[i].val.string) { + if (copy_values) { ret = dp_opt_set_string(opts, i, src_opts[i].val.string); - } else if (src_opts[i].def_val.string) { + } else { ret = dp_opt_set_string(opts, i, src_opts[i].def_val.string); } if (ret != EOK) { @@ -169,9 +169,9 @@ int dp_copy_options(TALLOC_CTX *memctx, break; case DP_OPT_BLOB: - if (src_opts[i].val.blob.data) { + if (copy_values) { ret = dp_opt_set_blob(opts, i, src_opts[i].val.blob); - } else if (src_opts[i].def_val.blob.data) { + } else { ret = dp_opt_set_blob(opts, i, src_opts[i].def_val.blob); } if (ret != EOK) { @@ -185,9 +185,9 @@ int dp_copy_options(TALLOC_CTX *memctx, break; case DP_OPT_NUMBER: - if (src_opts[i].val.number) { + if (copy_values) { ret = dp_opt_set_int(opts, i, src_opts[i].val.number); - } else if (src_opts[i].def_val.number) { + } else { ret = dp_opt_set_int(opts, i, src_opts[i].def_val.number); } if (ret != EOK) { @@ -201,9 +201,9 @@ int dp_copy_options(TALLOC_CTX *memctx, break; case DP_OPT_BOOL: - if (src_opts[i].val.boolean) { + if (copy_values) { ret = dp_opt_set_bool(opts, i, src_opts[i].val.boolean); - } else if (src_opts[i].def_val.boolean) { + } else { ret = dp_opt_set_bool(opts, i, src_opts[i].def_val.boolean); } if (ret != EOK) { @@ -225,6 +225,22 @@ done: return ret; } +int dp_copy_options(TALLOC_CTX *memctx, + struct dp_option *src_opts, + int num_opts, + struct dp_option **_opts) +{ + return dp_copy_options_ex(memctx, true, src_opts, num_opts, _opts); +} + +int dp_copy_defaults(TALLOC_CTX *memctx, + struct dp_option *src_opts, + int num_opts, + struct dp_option **_opts) +{ + return dp_copy_options_ex(memctx, false, src_opts, num_opts, _opts); +} + static const char *dp_opt_type_to_string(enum dp_opt_type type) { switch (type) { diff --git a/src/tests/cmocka/test_dp_opts.c b/src/tests/cmocka/test_dp_opts.c new file mode 100644 index 000000000..07998b403 --- /dev/null +++ b/src/tests/cmocka/test_dp_opts.c @@ -0,0 +1,421 @@ +/* + Authors: + Jakub Hrozek + + Copyright (C) 2014 Red Hat + + SSSD tests: Data Provider Option Tests + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include "providers/data_provider.h" + +#include "tests/cmocka/common_mock.h" + +#define STRING_DEFAULT "stringval" +#define BLOB_DEFAULT "blobval" +#define INT_DEFAULT 123 + +#define TESTS_PATH "tests_opts" +#define TEST_CONF_DB "test_opt_conf.ldb" +#define TEST_SYSDB_FILE "cache_opt_test.ldb" +#define TEST_DOM_NAME "opt_test" +#define TEST_ID_PROVIDER "ldap" + +enum test_opts { + OPT_STRING_NODEFAULT, + OPT_STRING_DEFAULT, + OPT_BLOB_NODEFAULT, + OPT_BLOB_DEFAULT, + OPT_INT_NODEFAULT, + OPT_INT_DEFAULT, + OPT_BOOL_TRUE, + OPT_BOOL_FALSE, + + OPT_NUM_OPTS +}; + +struct dp_option test_def_opts[] = { + { "string_nodefault", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "string_default", DP_OPT_STRING, { STRING_DEFAULT }, NULL_STRING}, + { "blob_nodefault", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB }, + { "blob_default", DP_OPT_BLOB, + { .blob = { discard_const(BLOB_DEFAULT), + sizeof(BLOB_DEFAULT) - 1 } }, + NULL_BLOB }, + { "int_nodefault", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, + { "int_default", DP_OPT_NUMBER, { .number = INT_DEFAULT }, NULL_NUMBER }, + { "bool_true", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "bool_false", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + DP_OPTION_TERMINATOR +}; + +static void assert_defaults(struct dp_option *opts) +{ + char *s; + struct dp_opt_blob b; + int i; + bool bo; + + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_null(s); + + s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); + assert_non_null(s); + assert_string_equal(s, STRING_DEFAULT); + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_null(b.data); + assert_int_equal(b.length, 0); + + b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); + assert_non_null(b.data); + assert_int_equal(b.length, strlen(BLOB_DEFAULT)); + assert_memory_equal(b.data, BLOB_DEFAULT, strlen(BLOB_DEFAULT)); + + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 0); + + i = dp_opt_get_int(opts, OPT_INT_DEFAULT); + assert_int_equal(i, INT_DEFAULT); + + bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); + assert_true(bo == true); + + bo = dp_opt_get_bool(opts, OPT_BOOL_FALSE); + assert_true(bo == false); +} + +void opt_test_copy_default(void **state) +{ + int ret; + TALLOC_CTX *mem_ctx; + struct dp_option *opts; + struct dp_opt_blob b; + + mem_ctx = talloc_new(global_talloc_context); + assert_non_null(mem_ctx); + + ret = dp_copy_defaults(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); + assert_int_equal(ret, EOK); + assert_defaults(opts); + + /* Test that copy_defaults would still copy defaults even if we + * change the values + */ + ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); + assert_int_equal(ret, EOK); + ret = dp_opt_set_string(opts, OPT_STRING_DEFAULT, "str2"); + assert_int_equal(ret, EOK); + + b.data = discard_const_p(uint8_t, "blob1"); + b.length = strlen("blob1"); + ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); + assert_int_equal(ret, EOK); + + ret = dp_opt_set_blob(opts, OPT_BLOB_DEFAULT, b); + b.data = discard_const_p(uint8_t, "blob2"); + b.length = strlen("blob2"); + assert_int_equal(ret, EOK); + + ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); + assert_int_equal(ret, EOK); + ret = dp_opt_set_int(opts, OPT_INT_DEFAULT, 789); + assert_int_equal(ret, EOK); + + ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); + assert_int_equal(ret, EOK); + ret = dp_opt_set_bool(opts, OPT_BOOL_FALSE, true); + assert_int_equal(ret, EOK); + + talloc_free(opts); + ret = dp_copy_defaults(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); + assert_int_equal(ret, EOK); + assert_defaults(opts); +} + +void opt_test_copy_options(void **state) +{ + int ret; + TALLOC_CTX *mem_ctx; + struct dp_option *opts; + char *s; + struct dp_opt_blob b; + int i; + bool bo; + + mem_ctx = talloc_new(global_talloc_context); + assert_non_null(mem_ctx); + + ret = dp_copy_options(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); + assert_int_equal(ret, EOK); + assert_int_equal(ret, EOK); + + ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); + assert_int_equal(ret, EOK); + + b.data = discard_const_p(uint8_t, "blob1"); + b.length = strlen("blob1"); + ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); + assert_int_equal(ret, EOK); + + ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); + assert_int_equal(ret, EOK); + + ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); + assert_int_equal(ret, EOK); + + /* Test that options set to an explicit value retain + * the value and even options with default value + * do not return the default unless explicitly set + */ + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_string_equal(s, "str1"); + s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); + assert_null(s); + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_non_null(b.data); + assert_int_equal(b.length, strlen("blob1")); + assert_memory_equal(b.data, "blob1", strlen("blob1")); + b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); + assert_null(b.data); + assert_int_equal(b.length, 0); + + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 456); + i = dp_opt_get_int(opts, OPT_INT_DEFAULT); + assert_int_equal(i, 0); + + bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); + assert_false(bo == true); +} + +void opt_test_get(void **state) +{ + int ret; + struct sss_test_ctx *tctx; + struct dp_option *opts; + char *dompath; + struct sss_test_conf_param params[] = { + { "string_nodefault", "stringval2" }, + { "blob_nodefault", "blobval2" }, + { "int_nodefault", "456" }, + { "bool_true", "false" }, + { NULL, NULL }, /* Sentinel */ + }; + char *s; + struct dp_opt_blob b; + int i; + bool bo; + + tctx = create_dom_test_ctx(global_talloc_context, TESTS_PATH, TEST_CONF_DB, + TEST_SYSDB_FILE, TEST_DOM_NAME, + TEST_ID_PROVIDER, params); + assert_non_null(tctx); + + dompath = talloc_asprintf(tctx, "config/domain/%s", TEST_DOM_NAME); + assert_non_null(dompath); + + ret = dp_get_options(global_talloc_context, tctx->confdb, dompath, + test_def_opts, OPT_NUM_OPTS, &opts); + assert_int_equal(ret, EOK); + + /* Options that were not specified explicitly should only have the default + * value, those that have been specified explicitly should carry that + * value + */ + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_non_null(s); + assert_string_equal(s, "stringval2"); + + s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); + assert_non_null(s); + assert_string_equal(s, STRING_DEFAULT); + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_non_null(b.data); + assert_int_equal(b.length, strlen("blobval2")); + assert_memory_equal(b.data, "blobval2", strlen("blobval2")); + + b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); + assert_non_null(b.data); + assert_int_equal(b.length, strlen(BLOB_DEFAULT)); + assert_memory_equal(b.data, BLOB_DEFAULT, strlen(BLOB_DEFAULT)); + + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 456); + + i = dp_opt_get_int(opts, OPT_INT_DEFAULT); + assert_int_equal(i, INT_DEFAULT); + + bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); + assert_true(bo == false); + + bo = dp_opt_get_bool(opts, OPT_BOOL_FALSE); + assert_true(bo == false); +} + +void opt_test_getset_setup(void **state) +{ + int ret; + struct dp_option *opts; + + ret = dp_copy_defaults(global_talloc_context, + test_def_opts, OPT_NUM_OPTS, &opts); + assert_int_equal(ret, EOK); + assert_defaults(opts); + + *state = opts; +} + +void opt_test_getset_teardown(void **state) +{ + struct dp_option *opts = talloc_get_type(*state, struct dp_option); + talloc_free(opts); +} + +void opt_test_getset_string(void **state) +{ + struct dp_option *opts = talloc_get_type(*state, struct dp_option); + int ret; + char *s; + + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_null(s); + + ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); + assert_int_equal(ret, EOK); + + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_non_null(s); + assert_string_equal(s, "str1"); +} + +void opt_test_getset_blob(void **state) +{ + struct dp_option *opts = talloc_get_type(*state, struct dp_option); + int ret; + struct dp_opt_blob b; + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_null(b.data); + assert_int_equal(b.length, 0); + + b.data = discard_const_p(uint8_t, "blob2"); + b.length = strlen("blob2"); + ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); + assert_int_equal(ret, EOK); + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_non_null(b.data); + assert_int_equal(b.length, strlen("blob2")); + assert_memory_equal(b.data, "blob2", strlen("blob2")); +} + +void opt_test_getset_int(void **state) +{ + struct dp_option *opts = talloc_get_type(*state, struct dp_option); + int ret; + int i; + + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 0); + + ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); + assert_int_equal(ret, EOK); + + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 456); +} + +void opt_test_getset_bool(void **state) +{ + struct dp_option *opts = talloc_get_type(*state, struct dp_option); + int ret; + bool b; + + b = dp_opt_get_bool(opts, OPT_BOOL_TRUE); + assert_true(b == true); + + ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); + assert_int_equal(ret, EOK); + + b = dp_opt_get_bool(opts, OPT_BOOL_TRUE); + assert_false(b == true); +} + +int main(int argc, const char *argv[]) +{ + int no_cleanup = 0; + poptContext pc; + int opt; + int ret; + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_DEBUG_OPTS + {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0, + _("Do not delete the test database after a test run"), NULL }, + POPT_TABLEEND + }; + const UnitTest tests[] = { + unit_test_setup_teardown(opt_test_getset_string, + opt_test_getset_setup, + opt_test_getset_teardown), + unit_test_setup_teardown(opt_test_getset_int, + opt_test_getset_setup, + opt_test_getset_teardown), + unit_test_setup_teardown(opt_test_getset_bool, + opt_test_getset_setup, + opt_test_getset_teardown), + unit_test_setup_teardown(opt_test_getset_blob, + opt_test_getset_setup, + opt_test_getset_teardown), + unit_test(opt_test_copy_default), + unit_test(opt_test_copy_options), + unit_test(opt_test_get) + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ + debug_level = SSSDBG_INVALID; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + DEBUG_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(); + test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_SYSDB_FILE); + test_dom_suite_setup(TESTS_PATH); + + ret = run_tests(tests); + if (ret == 0 && !no_cleanup) { + test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_SYSDB_FILE); + } + return ret; +} diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c index 40afa5cba..25a094082 100644 --- a/src/tests/ipa_ldap_opt-tests.c +++ b/src/tests/ipa_ldap_opt-tests.c @@ -170,7 +170,7 @@ START_TEST(test_copy_opts) tmp_ctx = talloc_new(NULL); fail_unless(tmp_ctx != NULL, "talloc_new failed"); - ret = dp_copy_options(tmp_ctx, ad_def_ldap_opts, SDAP_OPTS_BASIC, &opts); + ret = dp_copy_defaults(tmp_ctx, ad_def_ldap_opts, SDAP_OPTS_BASIC, &opts); fail_unless(ret == EOK, "[%s]", strerror(ret)); for (int i=0; i < SDAP_OPTS_BASIC; i++) { -- cgit