Line data Source code
1 : /*
2 : Test suite for FSRVP server state
3 :
4 : Copyright (C) David Disseldorp 2012-2015
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include <unistd.h>
22 :
23 : #include "librpc/gen_ndr/security.h"
24 : #include "lib/param/param.h"
25 : #include "lib/util/dlinklist.h"
26 : #include "libcli/resolve/resolve.h"
27 : #include "librpc/gen_ndr/ndr_fsrvp.h"
28 : #include "librpc/gen_ndr/ndr_fsrvp_c.h"
29 : #include "source3/rpc_server/fss/srv_fss_private.h"
30 : #include "torture/torture.h"
31 : #include "torture/local/proto.h"
32 :
33 1 : static bool test_fsrvp_state_empty(struct torture_context *tctx)
34 : {
35 1 : NTSTATUS status;
36 1 : struct fss_global fss_global;
37 1 : struct stat sbuf;
38 1 : char db_dir[] = "fsrvp_torture_XXXXXX";
39 1 : char *db_path = talloc_asprintf(NULL, "%s/%s",
40 : mkdtemp(db_dir), FSS_DB_NAME);
41 :
42 1 : memset(&fss_global, 0, sizeof(fss_global));
43 1 : fss_global.mem_ctx = talloc_new(NULL);
44 1 : fss_global.db_path = db_path;
45 :
46 1 : status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
47 0 : fss_global.sc_sets_count, fss_global.db_path);
48 1 : torture_assert_ntstatus_ok(tctx, status,
49 : "failed to store empty fss state");
50 :
51 1 : torture_assert_int_equal(tctx, stat(fss_global.db_path, &sbuf), 0,
52 : "failed to stat fss state tdb");
53 1 : talloc_free(fss_global.mem_ctx);
54 :
55 1 : memset(&fss_global, 0, sizeof(fss_global));
56 1 : fss_global.mem_ctx = talloc_new(NULL);
57 1 : fss_global.db_path = db_path;
58 :
59 1 : status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets,
60 : &fss_global.sc_sets_count,
61 0 : fss_global.db_path);
62 1 : torture_assert_ntstatus_ok(tctx, status,
63 : "failed to retrieve empty fss state");
64 1 : torture_assert_int_equal(tctx, fss_global.sc_sets_count, 0,
65 : "sc_sets_count set when it should be zero");
66 1 : talloc_free(fss_global.mem_ctx);
67 1 : unlink(db_path);
68 1 : rmdir(db_dir);
69 1 : talloc_free(db_path);
70 :
71 1 : return true;
72 : }
73 :
74 3 : static bool test_fsrvp_state_sc_set(struct torture_context *tctx,
75 : TALLOC_CTX *mem_ctx,
76 : struct fss_sc_set **sc_set_out)
77 : {
78 3 : struct fss_sc_set *sc_set;
79 :
80 3 : sc_set = talloc_zero(mem_ctx, struct fss_sc_set);
81 3 : sc_set->id = GUID_random();
82 3 : sc_set->id_str = GUID_string(sc_set, &sc_set->id);
83 3 : sc_set->state = FSS_SC_COMMITED;
84 3 : sc_set->context = FSRVP_CTX_FILE_SHARE_BACKUP;
85 3 : *sc_set_out = sc_set;
86 :
87 3 : return true;
88 : }
89 :
90 3 : static bool test_fsrvp_state_sc(struct torture_context *tctx,
91 : TALLOC_CTX *mem_ctx,
92 : struct fss_sc **sc_out)
93 : {
94 3 : struct fss_sc *sc;
95 :
96 3 : sc = talloc_zero(mem_ctx, struct fss_sc);
97 3 : sc->id = GUID_random();
98 3 : sc->id_str = GUID_string(sc, &sc->id);
99 3 : sc->volume_name = talloc_strdup(sc, "/this/is/a/path");
100 : /* keep snap path NULL, i.e. not yet committed */
101 3 : sc->create_ts = time(NULL);
102 3 : *sc_out = sc;
103 :
104 3 : return true;
105 : }
106 :
107 4 : static bool test_fsrvp_state_smap(struct torture_context *tctx,
108 : TALLOC_CTX *mem_ctx,
109 : const char *base_share_name,
110 : const char *sc_share_name,
111 : struct fss_sc_smap **smap_out)
112 : {
113 4 : struct fss_sc_smap *smap;
114 :
115 4 : smap = talloc_zero(mem_ctx, struct fss_sc_smap);
116 4 : smap->share_name = talloc_strdup(mem_ctx, base_share_name);
117 4 : smap->sc_share_name = talloc_strdup(mem_ctx, sc_share_name);
118 4 : smap->sc_share_comment = talloc_strdup(mem_ctx, "test sc share comment");
119 4 : smap->is_exposed = false;
120 4 : *smap_out = smap;
121 :
122 4 : return true;
123 : }
124 :
125 4 : static bool test_fsrvp_state_smap_compare(struct torture_context *tctx,
126 : struct fss_sc_smap *smap_1,
127 : struct fss_sc_smap *smap_2)
128 : {
129 : /* already confirmed by caller */
130 4 : torture_assert_str_equal(tctx, smap_1->sc_share_name,
131 : smap_2->sc_share_name,
132 : "smap sc share name strings differ");
133 :
134 4 : torture_assert_str_equal(tctx, smap_1->share_name,
135 : smap_2->share_name,
136 : "smap share name strings differ");
137 :
138 4 : torture_assert_str_equal(tctx, smap_1->sc_share_comment,
139 : smap_2->sc_share_comment,
140 : "smap sc share comment strings differ");
141 :
142 4 : torture_assert(tctx, (smap_1->is_exposed == smap_2->is_exposed),
143 : "smap exposure settings differ");
144 :
145 0 : return true;
146 : }
147 :
148 3 : static bool test_fsrvp_state_sc_compare(struct torture_context *tctx,
149 : struct fss_sc *sc_1,
150 : struct fss_sc *sc_2)
151 : {
152 3 : struct fss_sc_smap *smap_1;
153 3 : struct fss_sc_smap *smap_2;
154 3 : bool ok;
155 :
156 : /* should have already been confirmed by the caller */
157 3 : torture_assert(tctx, GUID_equal(&sc_1->id, &sc_2->id),
158 : "sc guids differ");
159 :
160 3 : torture_assert_str_equal(tctx, sc_1->volume_name, sc_2->volume_name,
161 : "sc volume_name strings differ");
162 :
163 : /* may be null, assert_str_eq handles null ptrs safely */
164 3 : torture_assert_str_equal(tctx, sc_1->sc_path, sc_2->sc_path,
165 : "sc path strings differ");
166 :
167 3 : torture_assert(tctx, difftime(sc_1->create_ts, sc_2->create_ts) == 0,
168 : "sc create timestamps differ");
169 :
170 3 : torture_assert_int_equal(tctx, sc_1->smaps_count, sc_2->smaps_count,
171 : "sc smaps counts differ");
172 :
173 7 : for (smap_1 = sc_1->smaps; smap_1; smap_1 = smap_1->next) {
174 4 : bool matched = false;
175 5 : for (smap_2 = sc_2->smaps; smap_2; smap_2 = smap_2->next) {
176 5 : if (strcmp(smap_1->sc_share_name,
177 5 : smap_2->sc_share_name) == 0) {
178 4 : matched = true;
179 4 : ok = test_fsrvp_state_smap_compare(tctx,
180 : smap_1,
181 : smap_2);
182 4 : torture_assert(tctx, ok, "");
183 0 : break;
184 : }
185 : }
186 4 : torture_assert(tctx, matched, "no match for smap");
187 : }
188 :
189 0 : return true;
190 : }
191 :
192 3 : static bool test_fsrvp_state_sc_set_compare(struct torture_context *tctx,
193 : struct fss_sc_set *sc_set_1,
194 : struct fss_sc_set *sc_set_2)
195 : {
196 3 : struct fss_sc *sc_1;
197 3 : struct fss_sc *sc_2;
198 3 : bool ok;
199 :
200 : /* should have already been confirmed by the caller */
201 3 : torture_assert(tctx, GUID_equal(&sc_set_1->id, &sc_set_2->id),
202 : "sc_set guids differ");
203 :
204 3 : torture_assert_str_equal(tctx, sc_set_1->id_str, sc_set_2->id_str,
205 : "sc_set guid strings differ");
206 :
207 3 : torture_assert_int_equal(tctx, sc_set_1->state, sc_set_2->state,
208 : "sc_set state enums differ");
209 :
210 3 : torture_assert_int_equal(tctx, sc_set_1->context, sc_set_2->context,
211 : "sc_set contexts differ");
212 :
213 3 : torture_assert_int_equal(tctx, sc_set_1->scs_count, sc_set_2->scs_count,
214 : "sc_set sc counts differ");
215 :
216 6 : for (sc_1 = sc_set_1->scs; sc_1; sc_1 = sc_1->next) {
217 3 : bool matched = false;
218 4 : for (sc_2 = sc_set_2->scs; sc_2; sc_2 = sc_2->next) {
219 4 : if (GUID_equal(&sc_1->id, &sc_2->id)) {
220 3 : matched = true;
221 3 : ok = test_fsrvp_state_sc_compare(tctx, sc_1,
222 : sc_2);
223 3 : torture_assert(tctx, ok, "");
224 0 : break;
225 : }
226 : }
227 3 : torture_assert(tctx, matched, "no match for sc");
228 : }
229 0 : return true;
230 : }
231 :
232 2 : static bool test_fsrvp_state_compare(struct torture_context *tctx,
233 : struct fss_global *fss_1,
234 : struct fss_global *fss_2)
235 : {
236 2 : struct fss_sc_set *sc_set_1;
237 2 : struct fss_sc_set *sc_set_2;
238 2 : bool ok;
239 :
240 2 : torture_assert_int_equal(tctx, fss_1->sc_sets_count,
241 : fss_2->sc_sets_count,
242 : "sc_sets_count differ");
243 :
244 5 : for (sc_set_1 = fss_1->sc_sets; sc_set_1; sc_set_1 = sc_set_1->next) {
245 3 : bool matched = false;
246 3 : for (sc_set_2 = fss_2->sc_sets;
247 4 : sc_set_2;
248 1 : sc_set_2 = sc_set_2->next) {
249 4 : if (GUID_equal(&sc_set_1->id, &sc_set_2->id)) {
250 3 : matched = true;
251 3 : ok = test_fsrvp_state_sc_set_compare(tctx,
252 : sc_set_1,
253 : sc_set_2);
254 3 : torture_assert(tctx, ok, "");
255 0 : break;
256 : }
257 : }
258 3 : torture_assert(tctx, matched, "no match for sc_set");
259 : }
260 :
261 0 : return true;
262 : }
263 :
264 : /*
265 : * test a simple hierarchy of:
266 : *
267 : * |
268 : * sc_set
269 : * |
270 : * sc
271 : * \
272 : * smap
273 : */
274 1 : static bool test_fsrvp_state_single(struct torture_context *tctx)
275 : {
276 1 : NTSTATUS status;
277 1 : bool ok;
278 1 : struct fss_global fss_gs;
279 1 : struct fss_global fss_gr;
280 1 : struct fss_sc_set *sc_set;
281 1 : struct fss_sc *sc;
282 1 : struct fss_sc_smap *smap;
283 1 : char db_dir[] = "fsrvp_torture_XXXXXX";
284 1 : char *db_path = talloc_asprintf(NULL, "%s/%s",
285 : mkdtemp(db_dir), FSS_DB_NAME);
286 :
287 1 : memset(&fss_gs, 0, sizeof(fss_gs));
288 1 : fss_gs.mem_ctx = talloc_new(NULL);
289 1 : fss_gs.db_path = db_path;
290 :
291 1 : ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set);
292 1 : torture_assert(tctx, ok, "failed to create sc set");
293 :
294 : /* use parent as mem ctx */
295 1 : ok = test_fsrvp_state_sc(tctx, sc_set, &sc);
296 1 : torture_assert(tctx, ok, "failed to create sc");
297 :
298 1 : ok = test_fsrvp_state_smap(tctx, sc, "base_share", "sc_share", &smap);
299 1 : torture_assert(tctx, ok, "failed to create smap");
300 :
301 1 : DLIST_ADD_END(fss_gs.sc_sets, sc_set);
302 1 : fss_gs.sc_sets_count++;
303 1 : DLIST_ADD_END(sc_set->scs, sc);
304 1 : sc_set->scs_count++;
305 1 : sc->sc_set = sc_set;
306 1 : DLIST_ADD_END(sc->smaps, smap);
307 1 : sc->smaps_count++;
308 :
309 1 : status = fss_state_store(fss_gs.mem_ctx, fss_gs.sc_sets,
310 0 : fss_gs.sc_sets_count, fss_gs.db_path);
311 1 : torture_assert_ntstatus_ok(tctx, status,
312 : "failed to store fss state");
313 :
314 1 : memset(&fss_gr, 0, sizeof(fss_gr));
315 1 : fss_gr.mem_ctx = talloc_new(NULL);
316 1 : fss_gr.db_path = db_path;
317 :
318 1 : status = fss_state_retrieve(fss_gr.mem_ctx, &fss_gr.sc_sets,
319 0 : &fss_gr.sc_sets_count, fss_gr.db_path);
320 1 : torture_assert_ntstatus_ok(tctx, status,
321 : "failed to retrieve fss state");
322 :
323 1 : ok = test_fsrvp_state_compare(tctx, &fss_gs, &fss_gr);
324 1 : torture_assert(tctx, ok,
325 : "stored and retrieved state comparison failed");
326 :
327 1 : talloc_free(fss_gs.mem_ctx);
328 1 : talloc_free(fss_gr.mem_ctx);
329 1 : unlink(db_path);
330 1 : rmdir(db_dir);
331 1 : talloc_free(db_path);
332 :
333 1 : return true;
334 : }
335 :
336 : /*
337 : * test a complex hierarchy of:
338 : *
339 : * /\
340 : * / \
341 : * sc_set_a sc_set_b
342 : * / \
343 : * sc_aa sc_ab
344 : * | | \
345 : * smap_aaa | \
346 : * | \
347 : * smap_aba smap_abb
348 : */
349 1 : static bool test_fsrvp_state_multi(struct torture_context *tctx)
350 : {
351 1 : NTSTATUS status;
352 1 : bool ok;
353 1 : struct fss_global fss_gs;
354 1 : struct fss_global fss_gr;
355 1 : struct fss_sc_set *sc_set_a;
356 1 : struct fss_sc_set *sc_set_b;
357 1 : struct fss_sc *sc_aa;
358 1 : struct fss_sc *sc_ab;
359 1 : struct fss_sc_smap *smap_aaa;
360 1 : struct fss_sc_smap *smap_aba;
361 1 : struct fss_sc_smap *smap_abb;
362 1 : char db_dir[] = "fsrvp_torture_XXXXXX";
363 1 : char *db_path = talloc_asprintf(NULL, "%s/%s",
364 : mkdtemp(db_dir), FSS_DB_NAME);
365 :
366 1 : memset(&fss_gs, 0, sizeof(fss_gs));
367 1 : fss_gs.mem_ctx = talloc_new(NULL);
368 1 : fss_gs.db_path = db_path;
369 :
370 1 : ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set_a);
371 1 : torture_assert(tctx, ok, "failed to create sc set");
372 :
373 1 : ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set_b);
374 1 : torture_assert(tctx, ok, "failed to create sc set");
375 :
376 : /* use parent as mem ctx */
377 1 : ok = test_fsrvp_state_sc(tctx, sc_set_a, &sc_aa);
378 1 : torture_assert(tctx, ok, "failed to create sc");
379 :
380 1 : ok = test_fsrvp_state_sc(tctx, sc_set_a, &sc_ab);
381 1 : torture_assert(tctx, ok, "failed to create sc");
382 :
383 1 : ok = test_fsrvp_state_smap(tctx, sc_ab, "share_aa", "sc_share_aaa",
384 : &smap_aaa);
385 1 : torture_assert(tctx, ok, "failed to create smap");
386 :
387 1 : ok = test_fsrvp_state_smap(tctx, sc_ab, "share_ab", "sc_share_aba",
388 : &smap_aba);
389 1 : torture_assert(tctx, ok, "failed to create smap");
390 :
391 1 : ok = test_fsrvp_state_smap(tctx, sc_ab, "share_ab", "sc_share_abb",
392 : &smap_abb);
393 1 : torture_assert(tctx, ok, "failed to create smap");
394 :
395 1 : DLIST_ADD_END(fss_gs.sc_sets, sc_set_a);
396 1 : fss_gs.sc_sets_count++;
397 1 : DLIST_ADD_END(fss_gs.sc_sets, sc_set_b);
398 1 : fss_gs.sc_sets_count++;
399 :
400 1 : DLIST_ADD_END(sc_set_a->scs, sc_aa);
401 1 : sc_set_a->scs_count++;
402 1 : sc_aa->sc_set = sc_set_a;
403 1 : DLIST_ADD_END(sc_set_a->scs, sc_ab);
404 1 : sc_set_a->scs_count++;
405 1 : sc_ab->sc_set = sc_set_a;
406 :
407 1 : DLIST_ADD_END(sc_aa->smaps, smap_aaa);
408 1 : sc_aa->smaps_count++;
409 1 : DLIST_ADD_END(sc_ab->smaps, smap_aba);
410 1 : sc_ab->smaps_count++;
411 1 : DLIST_ADD_END(sc_ab->smaps, smap_abb);
412 1 : sc_ab->smaps_count++;
413 :
414 1 : status = fss_state_store(fss_gs.mem_ctx, fss_gs.sc_sets,
415 0 : fss_gs.sc_sets_count, fss_gs.db_path);
416 1 : torture_assert_ntstatus_ok(tctx, status,
417 : "failed to store fss state");
418 :
419 1 : memset(&fss_gr, 0, sizeof(fss_gr));
420 1 : fss_gr.mem_ctx = talloc_new(NULL);
421 1 : fss_gr.db_path = db_path;
422 1 : status = fss_state_retrieve(fss_gr.mem_ctx, &fss_gr.sc_sets,
423 0 : &fss_gr.sc_sets_count, fss_gr.db_path);
424 1 : torture_assert_ntstatus_ok(tctx, status,
425 : "failed to retrieve fss state");
426 :
427 1 : ok = test_fsrvp_state_compare(tctx, &fss_gs, &fss_gr);
428 1 : torture_assert(tctx, ok,
429 : "stored and retrieved state comparison failed");
430 :
431 1 : talloc_free(fss_gs.mem_ctx);
432 1 : talloc_free(fss_gr.mem_ctx);
433 1 : unlink(db_path);
434 1 : rmdir(db_dir);
435 1 : talloc_free(db_path);
436 :
437 1 : return true;
438 : }
439 :
440 1 : static bool test_fsrvp_state_none(struct torture_context *tctx)
441 : {
442 1 : NTSTATUS status;
443 1 : struct fss_global fss_global;
444 1 : char db_dir[] = "fsrvp_torture_XXXXXX";
445 1 : char *db_path = talloc_asprintf(NULL, "%s/%s",
446 : mkdtemp(db_dir), FSS_DB_NAME);
447 :
448 1 : memset(&fss_global, 0, sizeof(fss_global));
449 1 : fss_global.mem_ctx = talloc_new(NULL);
450 1 : fss_global.db_path = db_path;
451 :
452 1 : status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets,
453 : &fss_global.sc_sets_count,
454 0 : fss_global.db_path);
455 1 : torture_assert_ntstatus_ok(tctx, status,
456 : "failed to retrieve fss state");
457 1 : torture_assert_int_equal(tctx, fss_global.sc_sets_count, 0,
458 : "sc_sets_count set when it should be zero");
459 1 : talloc_free(fss_global.mem_ctx);
460 1 : unlink(db_path);
461 1 : rmdir(db_dir);
462 1 : talloc_free(db_path);
463 :
464 1 : return true;
465 : }
466 :
467 2354 : struct torture_suite *torture_local_fsrvp(TALLOC_CTX *mem_ctx)
468 : {
469 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx,
470 : "fsrvp_state");
471 :
472 : /* dbwrap uses talloc_tos(), hence we need a stackframe :( */
473 2354 : talloc_stackframe();
474 :
475 2354 : torture_suite_add_simple_test(suite,
476 : "state_empty",
477 : test_fsrvp_state_empty);
478 :
479 2354 : torture_suite_add_simple_test(suite,
480 : "state_single",
481 : test_fsrvp_state_single);
482 :
483 2354 : torture_suite_add_simple_test(suite,
484 : "state_multi",
485 : test_fsrvp_state_multi);
486 :
487 2354 : torture_suite_add_simple_test(suite,
488 : "state_none",
489 : test_fsrvp_state_none);
490 :
491 2354 : return suite;
492 : }
|