diff options
author | David Disseldorp <ddiss@samba.org> | 2012-09-11 11:59:45 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2015-03-31 18:40:24 +0200 |
commit | 13fa1b8776d2280ba3d4dfc35e7134cd0aaee70f (patch) | |
tree | 47b65f3f3565d8163223384aa943dfcc0197e09e /source4/torture/local | |
parent | 9c8ae4454c8803d0ab807c5b47da01b6d251839b (diff) | |
download | samba-13fa1b8776d2280ba3d4dfc35e7134cd0aaee70f.tar.gz |
torture: add local FSRVP server state tests
Test the storage and retrieval of FSRVP server state, with varying
shadow-copy set, shadow copy and share map hierarchies.
Signed-off-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source4/torture/local')
-rw-r--r-- | source4/torture/local/fsrvp_state.c | 494 | ||||
-rw-r--r-- | source4/torture/local/local.c | 1 | ||||
-rw-r--r-- | source4/torture/local/wscript_build | 5 |
3 files changed, 498 insertions, 2 deletions
diff --git a/source4/torture/local/fsrvp_state.c b/source4/torture/local/fsrvp_state.c new file mode 100644 index 00000000000..f9c0f0fbd8e --- /dev/null +++ b/source4/torture/local/fsrvp_state.c @@ -0,0 +1,494 @@ +/* + Test suite for FSRVP server state + + Copyright (C) David Disseldorp 2012-2015 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "includes.h" +#include "librpc/gen_ndr/security.h" +#include "lib/param/param.h" +#include "lib/util/dlinklist.h" +#include "libcli/resolve/resolve.h" +#include "librpc/gen_ndr/ndr_fsrvp.h" +#include "librpc/gen_ndr/ndr_fsrvp_c.h" +#include "source3/rpc_server/fss/srv_fss_private.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static bool test_fsrvp_state_empty(struct torture_context *tctx) +{ + NTSTATUS status; + struct fss_global fss_global; + struct stat sbuf; + char db_dir[] = "fsrvp_torture_XXXXXX"; + char *db_path = talloc_asprintf(NULL, "%s/%s", + mkdtemp(db_dir), FSS_DB_NAME); + + memset(&fss_global, 0, sizeof(fss_global)); + fss_global.mem_ctx = talloc_new(NULL); + fss_global.db_path = db_path; + + status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets, + fss_global.sc_sets_count, fss_global.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to store empty fss state"); + + torture_assert_int_equal(tctx, stat(fss_global.db_path, &sbuf), 0, + "failed to stat fss state tdb"); + talloc_free(fss_global.mem_ctx); + + memset(&fss_global, 0, sizeof(fss_global)); + fss_global.mem_ctx = talloc_new(NULL); + fss_global.db_path = db_path; + + status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets, + &fss_global.sc_sets_count, + fss_global.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to retrieve empty fss state"); + torture_assert_int_equal(tctx, fss_global.sc_sets_count, 0, + "sc_sets_count set when it should be zero"); + talloc_free(fss_global.mem_ctx); + unlink(db_path); + rmdir(db_dir); + talloc_free(db_path); + + return true; +} + +static bool test_fsrvp_state_sc_set(struct torture_context *tctx, + TALLOC_CTX *mem_ctx, + struct fss_sc_set **sc_set_out) +{ + struct fss_sc_set *sc_set; + + sc_set = talloc_zero(mem_ctx, struct fss_sc_set); + sc_set->id = GUID_random(); + sc_set->id_str = GUID_string(sc_set, &sc_set->id); + sc_set->state = FSS_SC_COMMITED; + sc_set->context = FSRVP_CTX_FILE_SHARE_BACKUP; + *sc_set_out = sc_set; + + return true; +} + +static bool test_fsrvp_state_sc(struct torture_context *tctx, + TALLOC_CTX *mem_ctx, + struct fss_sc **sc_out) +{ + struct fss_sc *sc; + + sc = talloc_zero(mem_ctx, struct fss_sc); + sc->id = GUID_random(); + sc->id_str = GUID_string(sc, &sc->id); + sc->volume_name = talloc_strdup(sc, "/this/is/a/path"); + /* keep snap path NULL, i.e. not yet commited */ + sc->create_ts = time(NULL); + *sc_out = sc; + + return true; +} + +static bool test_fsrvp_state_smap(struct torture_context *tctx, + TALLOC_CTX *mem_ctx, + const char *base_share_name, + const char *sc_share_name, + struct fss_sc_smap **smap_out) +{ + struct fss_sc_smap *smap; + + smap = talloc_zero(mem_ctx, struct fss_sc_smap); + smap->share_name = talloc_strdup(mem_ctx, base_share_name); + smap->sc_share_name = talloc_strdup(mem_ctx, sc_share_name); + smap->sc_share_comment = talloc_strdup(mem_ctx, "test sc share comment"); + smap->is_exposed = false; + *smap_out = smap; + + return true; +} + +static bool test_fsrvp_state_smap_compare(struct torture_context *tctx, + struct fss_sc_smap *smap_1, + struct fss_sc_smap *smap_2) +{ + /* already confirmed by caller */ + torture_assert_str_equal(tctx, smap_1->sc_share_name, + smap_2->sc_share_name, + "smap sc share name strings differ"); + + torture_assert_str_equal(tctx, smap_1->share_name, + smap_2->share_name, + "smap share name strings differ"); + + torture_assert_str_equal(tctx, smap_1->sc_share_comment, + smap_2->sc_share_comment, + "smap sc share comment strings differ"); + + torture_assert(tctx, (smap_1->is_exposed == smap_2->is_exposed), + "smap exposure settings differ"); + + return true; +} + +static bool test_fsrvp_state_sc_compare(struct torture_context *tctx, + struct fss_sc *sc_1, + struct fss_sc *sc_2) +{ + struct fss_sc_smap *smap_1; + struct fss_sc_smap *smap_2; + bool ok; + + /* should have already been confirmed by the caller */ + torture_assert(tctx, GUID_equal(&sc_1->id, &sc_2->id), + "sc guids differ"); + + torture_assert_str_equal(tctx, sc_1->volume_name, sc_2->volume_name, + "sc volume_name strings differ"); + + /* may be null, assert_str_eq handles null ptrs safely */ + torture_assert_str_equal(tctx, sc_1->sc_path, sc_2->sc_path, + "sc path strings differ"); + + torture_assert(tctx, difftime(sc_1->create_ts, sc_2->create_ts) == 0, + "sc create timestamps differ"); + + torture_assert_int_equal(tctx, sc_1->smaps_count, sc_2->smaps_count, + "sc smaps counts differ"); + + for (smap_1 = sc_1->smaps; smap_1; smap_1 = smap_1->next) { + bool matched = false; + for (smap_2 = sc_2->smaps; smap_2; smap_2 = smap_2->next) { + if (strcmp(smap_1->sc_share_name, + smap_2->sc_share_name) == 0) { + matched = true; + ok = test_fsrvp_state_smap_compare(tctx, + smap_1, + smap_2); + torture_assert(tctx, ok, ""); + break; + } + } + torture_assert(tctx, matched, "no match for smap"); + } + + return true; +} + +static bool test_fsrvp_state_sc_set_compare(struct torture_context *tctx, + struct fss_sc_set *sc_set_1, + struct fss_sc_set *sc_set_2) +{ + struct fss_sc *sc_1; + struct fss_sc *sc_2; + bool ok; + + /* should have already been confirmed by the caller */ + torture_assert(tctx, GUID_equal(&sc_set_1->id, &sc_set_2->id), + "sc_set guids differ"); + + torture_assert_str_equal(tctx, sc_set_1->id_str, sc_set_2->id_str, + "sc_set guid strings differ"); + + torture_assert_int_equal(tctx, sc_set_1->state, sc_set_2->state, + "sc_set state enums differ"); + + torture_assert_int_equal(tctx, sc_set_1->context, sc_set_2->context, + "sc_set contexts differ"); + + torture_assert_int_equal(tctx, sc_set_1->scs_count, sc_set_2->scs_count, + "sc_set sc counts differ"); + + for (sc_1 = sc_set_1->scs; sc_1; sc_1 = sc_1->next) { + bool matched = false; + for (sc_2 = sc_set_2->scs; sc_2; sc_2 = sc_2->next) { + if (GUID_equal(&sc_1->id, &sc_2->id)) { + matched = true; + ok = test_fsrvp_state_sc_compare(tctx, sc_1, + sc_2); + torture_assert(tctx, ok, ""); + break; + } + } + torture_assert(tctx, matched, "no match for sc"); + } + return true; +} + +static bool test_fsrvp_state_compare(struct torture_context *tctx, + struct fss_global *fss_1, + struct fss_global *fss_2) +{ + struct fss_sc_set *sc_set_1; + struct fss_sc_set *sc_set_2; + bool ok; + + torture_assert_int_equal(tctx, fss_1->sc_sets_count, + fss_2->sc_sets_count, + "sc_sets_count differ"); + + for (sc_set_1 = fss_1->sc_sets; sc_set_1; sc_set_1 = sc_set_1->next) { + bool matched = false; + for (sc_set_2 = fss_2->sc_sets; + sc_set_2; + sc_set_2 = sc_set_2->next) { + if (GUID_equal(&sc_set_1->id, &sc_set_2->id)) { + matched = true; + ok = test_fsrvp_state_sc_set_compare(tctx, + sc_set_1, + sc_set_2); + torture_assert(tctx, ok, ""); + break; + } + } + torture_assert(tctx, matched, "no match for sc_set"); + } + + return true; +} + +/* + * test a simple heirarchy of: + * + * | + * sc_set + * | + * sc + * \ + * smap + */ +static bool test_fsrvp_state_single(struct torture_context *tctx) +{ + NTSTATUS status; + bool ok; + struct fss_global fss_gs; + struct fss_global fss_gr; + struct fss_sc_set *sc_set; + struct fss_sc *sc; + struct fss_sc_smap *smap; + char db_dir[] = "fsrvp_torture_XXXXXX"; + char *db_path = talloc_asprintf(NULL, "%s/%s", + mkdtemp(db_dir), FSS_DB_NAME); + + memset(&fss_gs, 0, sizeof(fss_gs)); + fss_gs.mem_ctx = talloc_new(NULL); + fss_gs.db_path = db_path; + + ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set); + torture_assert(tctx, ok, "failed to create sc set"); + + /* use parent as mem ctx */ + ok = test_fsrvp_state_sc(tctx, sc_set, &sc); + torture_assert(tctx, ok, "failed to create sc"); + + ok = test_fsrvp_state_smap(tctx, sc, "base_share", "sc_share", &smap); + torture_assert(tctx, ok, "failed to create smap"); + + DLIST_ADD_END(fss_gs.sc_sets, sc_set, struct fss_sc_set *); + fss_gs.sc_sets_count++; + DLIST_ADD_END(sc_set->scs, sc, struct fss_sc *); + sc_set->scs_count++; + sc->sc_set = sc_set; + DLIST_ADD_END(sc->smaps, smap, struct fss_sc_smap *); + sc->smaps_count++; + + status = fss_state_store(fss_gs.mem_ctx, fss_gs.sc_sets, + fss_gs.sc_sets_count, fss_gs.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to store fss state"); + + memset(&fss_gr, 0, sizeof(fss_gr)); + fss_gr.mem_ctx = talloc_new(NULL); + fss_gr.db_path = db_path; + + status = fss_state_retrieve(fss_gr.mem_ctx, &fss_gr.sc_sets, + &fss_gr.sc_sets_count, fss_gr.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to retrieve fss state"); + + ok = test_fsrvp_state_compare(tctx, &fss_gs, &fss_gr); + torture_assert(tctx, ok, + "stored and retrieved state comparison failed"); + + talloc_free(fss_gs.mem_ctx); + talloc_free(fss_gr.mem_ctx); + unlink(db_path); + rmdir(db_dir); + talloc_free(db_path); + + return true; +} + +/* + * test a complex heirarchy of: + * + * /\ + * / \ + * sc_set_a sc_set_b + * / \ + * sc_aa sc_ab + * | | \ + * smap_aaa | \ + * | \ + * smap_aba smap_abb + */ +static bool test_fsrvp_state_multi(struct torture_context *tctx) +{ + NTSTATUS status; + bool ok; + struct fss_global fss_gs; + struct fss_global fss_gr; + struct fss_sc_set *sc_set_a; + struct fss_sc_set *sc_set_b; + struct fss_sc *sc_aa; + struct fss_sc *sc_ab; + struct fss_sc_smap *smap_aaa; + struct fss_sc_smap *smap_aba; + struct fss_sc_smap *smap_abb; + char db_dir[] = "fsrvp_torture_XXXXXX"; + char *db_path = talloc_asprintf(NULL, "%s/%s", + mkdtemp(db_dir), FSS_DB_NAME); + + memset(&fss_gs, 0, sizeof(fss_gs)); + fss_gs.mem_ctx = talloc_new(NULL); + fss_gs.db_path = db_path; + + ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set_a); + torture_assert(tctx, ok, "failed to create sc set"); + + ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set_b); + torture_assert(tctx, ok, "failed to create sc set"); + + /* use parent as mem ctx */ + ok = test_fsrvp_state_sc(tctx, sc_set_a, &sc_aa); + torture_assert(tctx, ok, "failed to create sc"); + + ok = test_fsrvp_state_sc(tctx, sc_set_a, &sc_ab); + torture_assert(tctx, ok, "failed to create sc"); + + ok = test_fsrvp_state_smap(tctx, sc_ab, "share_aa", "sc_share_aaa", + &smap_aaa); + torture_assert(tctx, ok, "failed to create smap"); + + ok = test_fsrvp_state_smap(tctx, sc_ab, "share_ab", "sc_share_aba", + &smap_aba); + torture_assert(tctx, ok, "failed to create smap"); + + ok = test_fsrvp_state_smap(tctx, sc_ab, "share_ab", "sc_share_abb", + &smap_abb); + torture_assert(tctx, ok, "failed to create smap"); + + DLIST_ADD_END(fss_gs.sc_sets, sc_set_a, struct fss_sc_set *); + fss_gs.sc_sets_count++; + DLIST_ADD_END(fss_gs.sc_sets, sc_set_b, struct fss_sc_set *); + fss_gs.sc_sets_count++; + + DLIST_ADD_END(sc_set_a->scs, sc_aa, struct fss_sc *); + sc_set_a->scs_count++; + sc_aa->sc_set = sc_set_a; + DLIST_ADD_END(sc_set_a->scs, sc_ab, struct fss_sc *); + sc_set_a->scs_count++; + sc_ab->sc_set = sc_set_a; + + DLIST_ADD_END(sc_aa->smaps, smap_aaa, struct fss_sc_smap *); + sc_aa->smaps_count++; + DLIST_ADD_END(sc_ab->smaps, smap_aba, struct fss_sc_smap *); + sc_ab->smaps_count++; + DLIST_ADD_END(sc_ab->smaps, smap_abb, struct fss_sc_smap *); + sc_ab->smaps_count++; + + status = fss_state_store(fss_gs.mem_ctx, fss_gs.sc_sets, + fss_gs.sc_sets_count, fss_gs.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to store fss state"); + + memset(&fss_gr, 0, sizeof(fss_gr)); + fss_gr.mem_ctx = talloc_new(NULL); + fss_gr.db_path = db_path; + status = fss_state_retrieve(fss_gr.mem_ctx, &fss_gr.sc_sets, + &fss_gr.sc_sets_count, fss_gr.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to retrieve fss state"); + + ok = test_fsrvp_state_compare(tctx, &fss_gs, &fss_gr); + torture_assert(tctx, ok, + "stored and retrieved state comparison failed"); + + talloc_free(fss_gs.mem_ctx); + talloc_free(fss_gr.mem_ctx); + unlink(db_path); + rmdir(db_dir); + talloc_free(db_path); + + return true; +} + +static bool test_fsrvp_state_none(struct torture_context *tctx) +{ + NTSTATUS status; + struct fss_global fss_global; + char db_dir[] = "fsrvp_torture_XXXXXX"; + char *db_path = talloc_asprintf(NULL, "%s/%s", + mkdtemp(db_dir), FSS_DB_NAME); + + memset(&fss_global, 0, sizeof(fss_global)); + fss_global.mem_ctx = talloc_new(NULL); + fss_global.db_path = db_path; + + status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets, + &fss_global.sc_sets_count, + fss_global.db_path); + torture_assert_ntstatus_ok(tctx, status, + "failed to retrieve fss state"); + torture_assert_int_equal(tctx, fss_global.sc_sets_count, 0, + "sc_sets_count set when it should be zero"); + talloc_free(fss_global.mem_ctx); + unlink(db_path); + rmdir(db_dir); + talloc_free(db_path); + + return true; +} + +struct torture_suite *torture_local_fsrvp(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, + "fsrvp_state"); + + /* dbwrap uses talloc_tos(), hence we need a stackframe :( */ + talloc_stackframe(); + + torture_suite_add_simple_test(suite, + "state_empty", + test_fsrvp_state_empty); + + torture_suite_add_simple_test(suite, + "state_single", + test_fsrvp_state_single); + + torture_suite_add_simple_test(suite, + "state_multi", + test_fsrvp_state_multi); + + torture_suite_add_simple_test(suite, + "state_none", + test_fsrvp_state_none); + + return suite; +} diff --git a/source4/torture/local/local.c b/source4/torture/local/local.c index 45cc7123e2c..5d3b4e1aa24 100644 --- a/source4/torture/local/local.c +++ b/source4/torture/local/local.c @@ -70,6 +70,7 @@ torture_registry, torture_local_verif_trailer, torture_local_nss, + torture_local_fsrvp, NULL }; diff --git a/source4/torture/local/wscript_build b/source4/torture/local/wscript_build index 41775fe591b..570222ec344 100644 --- a/source4/torture/local/wscript_build +++ b/source4/torture/local/wscript_build @@ -18,9 +18,10 @@ TORTURE_LOCAL_SOURCE = '''../../../lib/util/charset/tests/iconv.c ../../dsdb/schema/tests/schema_syntax.c ../../../lib/util/tests/anonymous_shared.c verif_trailer.c - nss_tests.c''' + nss_tests.c + fsrvp_state.c''' -TORTURE_LOCAL_DEPS = 'RPC_NDR_ECHO TDR LIBCLI_SMB MESSAGING iconv POPT_CREDENTIALS TORTURE_AUTH TORTURE_UTIL TORTURE_NDR TORTURE_LIBCRYPTO share torture_registry PROVISION ldb samdb replace-test' +TORTURE_LOCAL_DEPS = 'RPC_NDR_ECHO TDR LIBCLI_SMB MESSAGING iconv POPT_CREDENTIALS TORTURE_AUTH TORTURE_UTIL TORTURE_NDR TORTURE_LIBCRYPTO share torture_registry PROVISION ldb samdb replace-test RPC_FSS_STATE' bld.SAMBA_MODULE('TORTURE_LOCAL', source=TORTURE_LOCAL_SOURCE, |