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 0 : static bool test_fsrvp_state_empty(struct torture_context *tctx)
34 : {
35 : NTSTATUS status;
36 : struct fss_global fss_global;
37 : struct stat sbuf;
38 0 : char db_dir[] = "fsrvp_torture_XXXXXX";
39 0 : char *db_path = talloc_asprintf(NULL, "%s/%s",
40 : mkdtemp(db_dir), FSS_DB_NAME);
41 :
42 0 : memset(&fss_global, 0, sizeof(fss_global));
43 0 : fss_global.mem_ctx = talloc_new(NULL);
44 0 : fss_global.db_path = db_path;
45 :
46 0 : status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
47 0 : fss_global.sc_sets_count, fss_global.db_path);
48 0 : torture_assert_ntstatus_ok(tctx, status,
49 : "failed to store empty fss state");
50 :
51 0 : torture_assert_int_equal(tctx, stat(fss_global.db_path, &sbuf), 0,
52 : "failed to stat fss state tdb");
53 0 : talloc_free(fss_global.mem_ctx);
54 :
55 0 : memset(&fss_global, 0, sizeof(fss_global));
56 0 : fss_global.mem_ctx = talloc_new(NULL);
57 0 : fss_global.db_path = db_path;
58 :
59 0 : 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 0 : torture_assert_ntstatus_ok(tctx, status,
63 : "failed to retrieve empty fss state");
64 0 : torture_assert_int_equal(tctx, fss_global.sc_sets_count, 0,
65 : "sc_sets_count set when it should be zero");
66 0 : talloc_free(fss_global.mem_ctx);
67 0 : unlink(db_path);
68 0 : rmdir(db_dir);
69 0 : talloc_free(db_path);
70 :
71 0 : return true;
72 : }
73 :
74 0 : 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 : struct fss_sc_set *sc_set;
79 :
80 0 : sc_set = talloc_zero(mem_ctx, struct fss_sc_set);
81 0 : sc_set->id = GUID_random();
82 0 : sc_set->id_str = GUID_string(sc_set, &sc_set->id);
83 0 : sc_set->state = FSS_SC_COMMITED;
84 0 : sc_set->context = FSRVP_CTX_FILE_SHARE_BACKUP;
85 0 : *sc_set_out = sc_set;
86 :
87 0 : return true;
88 : }
89 :
90 0 : static bool test_fsrvp_state_sc(struct torture_context *tctx,
91 : TALLOC_CTX *mem_ctx,
92 : struct fss_sc **sc_out)
93 : {
94 : struct fss_sc *sc;
95 :
96 0 : sc = talloc_zero(mem_ctx, struct fss_sc);
97 0 : sc->id = GUID_random();
98 0 : sc->id_str = GUID_string(sc, &sc->id);
99 0 : sc->volume_name = talloc_strdup(sc, "/this/is/a/path");
100 : /* keep snap path NULL, i.e. not yet committed */
101 0 : sc->create_ts = time(NULL);
102 0 : *sc_out = sc;
103 :
104 0 : return true;
105 : }
106 :
107 0 : 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 : struct fss_sc_smap *smap;
114 :
115 0 : smap = talloc_zero(mem_ctx, struct fss_sc_smap);
116 0 : smap->share_name = talloc_strdup(mem_ctx, base_share_name);
117 0 : smap->sc_share_name = talloc_strdup(mem_ctx, sc_share_name);
118 0 : smap->sc_share_comment = talloc_strdup(mem_ctx, "test sc share comment");
119 0 : smap->is_exposed = false;
120 0 : *smap_out = smap;
121 :
122 0 : return true;
123 : }
124 :
125 0 : 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 0 : 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 0 : torture_assert_str_equal(tctx, smap_1->share_name,
135 : smap_2->share_name,
136 : "smap share name strings differ");
137 :
138 0 : 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 0 : torture_assert(tctx, (smap_1->is_exposed == smap_2->is_exposed),
143 : "smap exposure settings differ");
144 :
145 0 : return true;
146 : }
147 :
148 0 : 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 : struct fss_sc_smap *smap_1;
153 : struct fss_sc_smap *smap_2;
154 : bool ok;
155 :
156 : /* should have already been confirmed by the caller */
157 0 : torture_assert(tctx, GUID_equal(&sc_1->id, &sc_2->id),
158 : "sc guids differ");
159 :
160 0 : 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 0 : torture_assert_str_equal(tctx, sc_1->sc_path, sc_2->sc_path,
165 : "sc path strings differ");
166 :
167 0 : torture_assert(tctx, difftime(sc_1->create_ts, sc_2->create_ts) == 0,
168 : "sc create timestamps differ");
169 :
170 0 : torture_assert_int_equal(tctx, sc_1->smaps_count, sc_2->smaps_count,
171 : "sc smaps counts differ");
172 :
173 0 : for (smap_1 = sc_1->smaps; smap_1; smap_1 = smap_1->next) {
174 0 : bool matched = false;
175 0 : for (smap_2 = sc_2->smaps; smap_2; smap_2 = smap_2->next) {
176 0 : if (strcmp(smap_1->sc_share_name,
177 0 : smap_2->sc_share_name) == 0) {
178 0 : matched = true;
179 0 : ok = test_fsrvp_state_smap_compare(tctx,
180 : smap_1,
181 : smap_2);
182 0 : torture_assert(tctx, ok, "");
183 0 : break;
184 : }
185 : }
186 0 : torture_assert(tctx, matched, "no match for smap");
187 : }
188 :
189 0 : return true;
190 : }
191 :
192 0 : 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 : struct fss_sc *sc_1;
197 : struct fss_sc *sc_2;
198 : bool ok;
199 :
200 : /* should have already been confirmed by the caller */
201 0 : torture_assert(tctx, GUID_equal(&sc_set_1->id, &sc_set_2->id),
202 : "sc_set guids differ");
203 :
204 0 : torture_assert_str_equal(tctx, sc_set_1->id_str, sc_set_2->id_str,
205 : "sc_set guid strings differ");
206 :
207 0 : torture_assert_int_equal(tctx, sc_set_1->state, sc_set_2->state,
208 : "sc_set state enums differ");
209 :
210 0 : torture_assert_int_equal(tctx, sc_set_1->context, sc_set_2->context,
211 : "sc_set contexts differ");
212 :
213 0 : torture_assert_int_equal(tctx, sc_set_1->scs_count, sc_set_2->scs_count,
214 : "sc_set sc counts differ");
215 :
216 0 : for (sc_1 = sc_set_1->scs; sc_1; sc_1 = sc_1->next) {
217 0 : bool matched = false;
218 0 : for (sc_2 = sc_set_2->scs; sc_2; sc_2 = sc_2->next) {
219 0 : if (GUID_equal(&sc_1->id, &sc_2->id)) {
220 0 : matched = true;
221 0 : ok = test_fsrvp_state_sc_compare(tctx, sc_1,
222 : sc_2);
223 0 : torture_assert(tctx, ok, "");
224 0 : break;
225 : }
226 : }
227 0 : torture_assert(tctx, matched, "no match for sc");
228 : }
229 0 : return true;
230 : }
231 :
232 0 : static bool test_fsrvp_state_compare(struct torture_context *tctx,
233 : struct fss_global *fss_1,
234 : struct fss_global *fss_2)
235 : {
236 : struct fss_sc_set *sc_set_1;
237 : struct fss_sc_set *sc_set_2;
238 : bool ok;
239 :
240 0 : torture_assert_int_equal(tctx, fss_1->sc_sets_count,
241 : fss_2->sc_sets_count,
242 : "sc_sets_count differ");
243 :
244 0 : for (sc_set_1 = fss_1->sc_sets; sc_set_1; sc_set_1 = sc_set_1->next) {
245 0 : bool matched = false;
246 0 : for (sc_set_2 = fss_2->sc_sets;
247 0 : sc_set_2;
248 0 : sc_set_2 = sc_set_2->next) {
249 0 : if (GUID_equal(&sc_set_1->id, &sc_set_2->id)) {
250 0 : matched = true;
251 0 : ok = test_fsrvp_state_sc_set_compare(tctx,
252 : sc_set_1,
253 : sc_set_2);
254 0 : torture_assert(tctx, ok, "");
255 0 : break;
256 : }
257 : }
258 0 : 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 0 : static bool test_fsrvp_state_single(struct torture_context *tctx)
275 : {
276 : NTSTATUS status;
277 : bool ok;
278 : struct fss_global fss_gs;
279 : struct fss_global fss_gr;
280 : struct fss_sc_set *sc_set;
281 : struct fss_sc *sc;
282 : struct fss_sc_smap *smap;
283 0 : char db_dir[] = "fsrvp_torture_XXXXXX";
284 0 : char *db_path = talloc_asprintf(NULL, "%s/%s",
285 : mkdtemp(db_dir), FSS_DB_NAME);
286 :
287 0 : memset(&fss_gs, 0, sizeof(fss_gs));
288 0 : fss_gs.mem_ctx = talloc_new(NULL);
289 0 : fss_gs.db_path = db_path;
290 :
291 0 : ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set);
292 0 : torture_assert(tctx, ok, "failed to create sc set");
293 :
294 : /* use parent as mem ctx */
295 0 : ok = test_fsrvp_state_sc(tctx, sc_set, &sc);
296 0 : torture_assert(tctx, ok, "failed to create sc");
297 :
298 0 : ok = test_fsrvp_state_smap(tctx, sc, "base_share", "sc_share", &smap);
299 0 : torture_assert(tctx, ok, "failed to create smap");
300 :
301 0 : DLIST_ADD_END(fss_gs.sc_sets, sc_set);
302 0 : fss_gs.sc_sets_count++;
303 0 : DLIST_ADD_END(sc_set->scs, sc);
304 0 : sc_set->scs_count++;
305 0 : sc->sc_set = sc_set;
306 0 : DLIST_ADD_END(sc->smaps, smap);
307 0 : sc->smaps_count++;
308 :
309 0 : status = fss_state_store(fss_gs.mem_ctx, fss_gs.sc_sets,
310 0 : fss_gs.sc_sets_count, fss_gs.db_path);
311 0 : torture_assert_ntstatus_ok(tctx, status,
312 : "failed to store fss state");
313 :
314 0 : memset(&fss_gr, 0, sizeof(fss_gr));
315 0 : fss_gr.mem_ctx = talloc_new(NULL);
316 0 : fss_gr.db_path = db_path;
317 :
318 0 : status = fss_state_retrieve(fss_gr.mem_ctx, &fss_gr.sc_sets,
319 0 : &fss_gr.sc_sets_count, fss_gr.db_path);
320 0 : torture_assert_ntstatus_ok(tctx, status,
321 : "failed to retrieve fss state");
322 :
323 0 : ok = test_fsrvp_state_compare(tctx, &fss_gs, &fss_gr);
324 0 : torture_assert(tctx, ok,
325 : "stored and retrieved state comparison failed");
326 :
327 0 : talloc_free(fss_gs.mem_ctx);
328 0 : talloc_free(fss_gr.mem_ctx);
329 0 : unlink(db_path);
330 0 : rmdir(db_dir);
331 0 : talloc_free(db_path);
332 :
333 0 : 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 0 : static bool test_fsrvp_state_multi(struct torture_context *tctx)
350 : {
351 : NTSTATUS status;
352 : bool ok;
353 : struct fss_global fss_gs;
354 : struct fss_global fss_gr;
355 : struct fss_sc_set *sc_set_a;
356 : struct fss_sc_set *sc_set_b;
357 : struct fss_sc *sc_aa;
358 : struct fss_sc *sc_ab;
359 : struct fss_sc_smap *smap_aaa;
360 : struct fss_sc_smap *smap_aba;
361 : struct fss_sc_smap *smap_abb;
362 0 : char db_dir[] = "fsrvp_torture_XXXXXX";
363 0 : char *db_path = talloc_asprintf(NULL, "%s/%s",
364 : mkdtemp(db_dir), FSS_DB_NAME);
365 :
366 0 : memset(&fss_gs, 0, sizeof(fss_gs));
367 0 : fss_gs.mem_ctx = talloc_new(NULL);
368 0 : fss_gs.db_path = db_path;
369 :
370 0 : ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set_a);
371 0 : torture_assert(tctx, ok, "failed to create sc set");
372 :
373 0 : ok = test_fsrvp_state_sc_set(tctx, fss_gs.mem_ctx, &sc_set_b);
374 0 : torture_assert(tctx, ok, "failed to create sc set");
375 :
376 : /* use parent as mem ctx */
377 0 : ok = test_fsrvp_state_sc(tctx, sc_set_a, &sc_aa);
378 0 : torture_assert(tctx, ok, "failed to create sc");
379 :
380 0 : ok = test_fsrvp_state_sc(tctx, sc_set_a, &sc_ab);
381 0 : torture_assert(tctx, ok, "failed to create sc");
382 :
383 0 : ok = test_fsrvp_state_smap(tctx, sc_ab, "share_aa", "sc_share_aaa",
384 : &smap_aaa);
385 0 : torture_assert(tctx, ok, "failed to create smap");
386 :
387 0 : ok = test_fsrvp_state_smap(tctx, sc_ab, "share_ab", "sc_share_aba",
388 : &smap_aba);
389 0 : torture_assert(tctx, ok, "failed to create smap");
390 :
391 0 : ok = test_fsrvp_state_smap(tctx, sc_ab, "share_ab", "sc_share_abb",
392 : &smap_abb);
393 0 : torture_assert(tctx, ok, "failed to create smap");
394 :
395 0 : DLIST_ADD_END(fss_gs.sc_sets, sc_set_a);
396 0 : fss_gs.sc_sets_count++;
397 0 : DLIST_ADD_END(fss_gs.sc_sets, sc_set_b);
398 0 : fss_gs.sc_sets_count++;
399 :
400 0 : DLIST_ADD_END(sc_set_a->scs, sc_aa);
401 0 : sc_set_a->scs_count++;
402 0 : sc_aa->sc_set = sc_set_a;
403 0 : DLIST_ADD_END(sc_set_a->scs, sc_ab);
404 0 : sc_set_a->scs_count++;
405 0 : sc_ab->sc_set = sc_set_a;
406 :
407 0 : DLIST_ADD_END(sc_aa->smaps, smap_aaa);
408 0 : sc_aa->smaps_count++;
409 0 : DLIST_ADD_END(sc_ab->smaps, smap_aba);
410 0 : sc_ab->smaps_count++;
411 0 : DLIST_ADD_END(sc_ab->smaps, smap_abb);
412 0 : sc_ab->smaps_count++;
413 :
414 0 : status = fss_state_store(fss_gs.mem_ctx, fss_gs.sc_sets,
415 0 : fss_gs.sc_sets_count, fss_gs.db_path);
416 0 : torture_assert_ntstatus_ok(tctx, status,
417 : "failed to store fss state");
418 :
419 0 : memset(&fss_gr, 0, sizeof(fss_gr));
420 0 : fss_gr.mem_ctx = talloc_new(NULL);
421 0 : fss_gr.db_path = db_path;
422 0 : status = fss_state_retrieve(fss_gr.mem_ctx, &fss_gr.sc_sets,
423 0 : &fss_gr.sc_sets_count, fss_gr.db_path);
424 0 : torture_assert_ntstatus_ok(tctx, status,
425 : "failed to retrieve fss state");
426 :
427 0 : ok = test_fsrvp_state_compare(tctx, &fss_gs, &fss_gr);
428 0 : torture_assert(tctx, ok,
429 : "stored and retrieved state comparison failed");
430 :
431 0 : talloc_free(fss_gs.mem_ctx);
432 0 : talloc_free(fss_gr.mem_ctx);
433 0 : unlink(db_path);
434 0 : rmdir(db_dir);
435 0 : talloc_free(db_path);
436 :
437 0 : return true;
438 : }
439 :
440 0 : static bool test_fsrvp_state_none(struct torture_context *tctx)
441 : {
442 : NTSTATUS status;
443 : struct fss_global fss_global;
444 0 : char db_dir[] = "fsrvp_torture_XXXXXX";
445 0 : char *db_path = talloc_asprintf(NULL, "%s/%s",
446 : mkdtemp(db_dir), FSS_DB_NAME);
447 :
448 0 : memset(&fss_global, 0, sizeof(fss_global));
449 0 : fss_global.mem_ctx = talloc_new(NULL);
450 0 : fss_global.db_path = db_path;
451 :
452 0 : 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 0 : torture_assert_ntstatus_ok(tctx, status,
456 : "failed to retrieve fss state");
457 0 : torture_assert_int_equal(tctx, fss_global.sc_sets_count, 0,
458 : "sc_sets_count set when it should be zero");
459 0 : talloc_free(fss_global.mem_ctx);
460 0 : unlink(db_path);
461 0 : rmdir(db_dir);
462 0 : talloc_free(db_path);
463 :
464 0 : return true;
465 : }
466 :
467 964 : struct torture_suite *torture_local_fsrvp(TALLOC_CTX *mem_ctx)
468 : {
469 964 : struct torture_suite *suite = torture_suite_create(mem_ctx,
470 : "fsrvp_state");
471 :
472 : /* dbwrap uses talloc_tos(), hence we need a stackframe :( */
473 964 : talloc_stackframe();
474 :
475 964 : torture_suite_add_simple_test(suite,
476 : "state_empty",
477 : test_fsrvp_state_empty);
478 :
479 964 : torture_suite_add_simple_test(suite,
480 : "state_single",
481 : test_fsrvp_state_single);
482 :
483 964 : torture_suite_add_simple_test(suite,
484 : "state_multi",
485 : test_fsrvp_state_multi);
486 :
487 964 : torture_suite_add_simple_test(suite,
488 : "state_none",
489 : test_fsrvp_state_none);
490 :
491 964 : return suite;
492 : }
|