2 Unix SMB/CIFS implementation.
4 local testing of registry library - registry backend
6 Copyright (C) Jelmer Vernooij 2005-2007
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "lib/registry/registry.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "torture/torture.h"
27 #include "librpc/gen_ndr/winreg.h"
28 #include "libcli/security/security.h"
29 #include "system/filesys.h"
32 * Test obtaining a predefined key.
34 static bool test_get_predefined(struct torture_context *tctx,
37 const struct registry_context *rctx =
38 (const struct registry_context *)_data;
39 struct registry_key *root;
42 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
43 torture_assert_werr_ok(tctx, error,
44 "getting predefined key failed");
49 * Test obtaining a predefined key.
51 static bool test_get_predefined_unknown(struct torture_context *tctx,
54 const struct registry_context *rctx = _data;
55 struct registry_key *root;
58 error = reg_get_predefined_key(rctx, 1337, &root);
59 torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
60 "getting predefined key failed");
64 static bool test_predef_key_by_name(struct torture_context *tctx,
67 const struct registry_context *rctx =
68 (const struct registry_context *)_data;
69 struct registry_key *root;
72 error = reg_get_predefined_key_by_name(rctx, "HKEY_CLASSES_ROOT",
74 torture_assert_werr_ok(tctx, error,
75 "getting predefined key failed");
77 error = reg_get_predefined_key_by_name(rctx, "HKEY_classes_ROOT",
79 torture_assert_werr_ok(tctx, error,
80 "getting predefined key case insensitively failed");
85 static bool test_predef_key_by_name_invalid(struct torture_context *tctx,
88 const struct registry_context *rctx =
89 (const struct registry_context *)_data;
90 struct registry_key *root;
93 error = reg_get_predefined_key_by_name(rctx, "BLA", &root);
94 torture_assert_werr_equal(tctx, error, WERR_BADFILE,
95 "getting predefined key failed");
100 * Test creating a new subkey
102 static bool test_create_subkey(struct torture_context *tctx,
105 const struct registry_context *rctx =
106 (const struct registry_context *)_data;
107 struct registry_key *root, *newkey;
110 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
111 torture_assert_werr_ok(tctx, error,
112 "getting predefined key failed");
114 error = reg_key_add_name(rctx, root, "Bad Bentheim", NULL, NULL,
116 torture_assert_werr_ok(tctx, error, "Creating key return code");
117 torture_assert(tctx, newkey != NULL, "Creating new key");
123 * Test creating a new nested subkey
125 static bool test_create_nested_subkey(struct torture_context *tctx,
128 const struct registry_context *rctx =
129 (const struct registry_context *)_data;
130 struct registry_key *root, *newkey1, *newkey2;
133 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
134 torture_assert_werr_ok(tctx, error,
135 "getting predefined key failed");
137 error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL,
139 torture_assert_werr_ok(tctx, error, "Creating key return code");
140 torture_assert(tctx, newkey1 != NULL, "Creating new key");
142 error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL,
144 torture_assert_werr_ok(tctx, error, "Creating key return code");
145 torture_assert(tctx, newkey2 != NULL, "Creating new key");
151 * Test creating a new subkey
153 static bool test_key_add_abs_top(struct torture_context *tctx,
156 const struct registry_context *rctx =
157 (const struct registry_context *)_data;
158 struct registry_key *root;
161 error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT", 0, NULL,
163 torture_assert_werr_equal(tctx, error, WERR_ALREADY_EXISTS,
170 * Test creating a new subkey
172 static bool test_key_add_abs(struct torture_context *tctx,
176 const struct registry_context *rctx =
177 (const struct registry_context *)_data;
178 struct registry_key *root, *result1, *result2;
180 error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT\\bloe", 0, NULL,
182 torture_assert_werr_ok(tctx, error, "create lowest");
184 error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT\\bloe\\bla", 0,
186 torture_assert_werr_ok(tctx, error, "create nested");
188 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
189 torture_assert_werr_ok(tctx, error,
190 "getting predefined key failed");
192 error = reg_open_key(tctx, root, "bloe", &result2);
193 torture_assert_werr_ok(tctx, error, "opening key");
195 error = reg_open_key(tctx, root, "bloe\\bla", &result2);
196 torture_assert_werr_ok(tctx, error, "opening key");
202 static bool test_del_key(struct torture_context *tctx, const void *_data)
204 const struct registry_context *rctx =
205 (const struct registry_context *)_data;
206 struct registry_key *root, *newkey;
209 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
210 torture_assert_werr_ok(tctx, error,
211 "getting predefined key failed");
213 error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL, &newkey);
215 torture_assert_werr_ok(tctx, error, "Creating key return code");
216 torture_assert(tctx, newkey != NULL, "Creating new key");
218 error = reg_key_del(root, "Hamburg");
219 torture_assert_werr_ok(tctx, error, "Delete key");
221 error = reg_key_del(root, "Hamburg");
222 torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
223 "Delete missing key");
229 * Convenience function for opening the HKEY_CLASSES_ROOT hive and
230 * creating a single key for testing purposes.
232 static bool create_test_key(struct torture_context *tctx,
233 const struct registry_context *rctx,
235 struct registry_key **root,
236 struct registry_key **subkey)
240 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, root);
241 torture_assert_werr_ok(tctx, error,
242 "getting predefined key failed");
244 error = reg_key_add_name(rctx, *root, name, NULL, NULL, subkey);
245 torture_assert_werr_ok(tctx, error, "Creating key return code");
251 static bool test_flush_key(struct torture_context *tctx, const void *_data)
253 const struct registry_context *rctx =
254 (const struct registry_context *)_data;
255 struct registry_key *root, *subkey;
258 if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey))
261 error = reg_key_flush(subkey);
262 torture_assert_werr_ok(tctx, error, "flush key");
264 torture_assert_werr_equal(tctx, reg_key_flush(NULL),
265 WERR_INVALID_PARAM, "flush key");
270 static bool test_query_key(struct torture_context *tctx, const void *_data)
272 const struct registry_context *rctx =
273 (const struct registry_context *)_data;
274 struct registry_key *root, *subkey;
276 NTTIME last_changed_time;
277 uint32_t num_subkeys, num_values;
278 const char *classname;
280 if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey))
283 error = reg_key_get_info(tctx, subkey, &classname,
284 &num_subkeys, &num_values,
287 torture_assert_werr_ok(tctx, error, "get info key");
288 torture_assert(tctx, classname == NULL, "classname");
289 torture_assert_int_equal(tctx, num_subkeys, 0, "num subkeys");
290 torture_assert_int_equal(tctx, num_values, 0, "num values");
295 static bool test_query_key_nums(struct torture_context *tctx, const void *_data)
297 const struct registry_context *rctx =
298 (const struct registry_context *)_data;
299 struct registry_key *root, *subkey1, *subkey2;
301 uint32_t num_subkeys, num_values;
304 if (!create_test_key(tctx, rctx, "Berlin", &root, &subkey1))
307 error = reg_key_add_name(rctx, subkey1, "Bentheim", NULL, NULL,
309 torture_assert_werr_ok(tctx, error, "Creating key return code");
311 error = reg_val_set(subkey1, "Answer", REG_DWORD,
312 data_blob_talloc(tctx, &data, sizeof(data)));
313 torture_assert_werr_ok(tctx, error, "set value");
315 error = reg_key_get_info(tctx, subkey1, NULL, &num_subkeys,
318 torture_assert_werr_ok(tctx, error, "get info key");
319 torture_assert_int_equal(tctx, num_subkeys, 1, "num subkeys");
320 torture_assert_int_equal(tctx, num_values, 1, "num values");
326 * Test that the subkeys of a key can be enumerated, that
327 * the returned parameters for get_subkey_by_index are optional and
328 * that enumerating the parents of a non-top-level node works.
330 static bool test_list_subkeys(struct torture_context *tctx, const void *_data)
332 const struct registry_context *rctx =
333 (const struct registry_context *)_data;
334 struct registry_key *subkey = NULL, *root;
336 NTTIME last_mod_time;
337 const char *classname, *name;
339 if (!create_test_key(tctx, rctx, "Goettingen", &root, &subkey))
342 error = reg_key_get_subkey_by_index(tctx, root, 0, &name, &classname,
345 torture_assert_werr_ok(tctx, error, "Enum keys return code");
346 torture_assert_str_equal(tctx, name, "Goettingen", "Enum keys data");
349 error = reg_key_get_subkey_by_index(tctx, root, 0, NULL, NULL, NULL);
351 torture_assert_werr_ok(tctx, error,
352 "Enum keys with NULL arguments return code");
354 error = reg_key_get_subkey_by_index(tctx, root, 1, NULL, NULL, NULL);
356 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
357 "Invalid error for no more items");
359 error = reg_key_get_subkey_by_index(tctx, subkey, 0, NULL, NULL, NULL);
361 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
362 "Invalid error for no more items");
368 * Test setting a value
370 static bool test_set_value(struct torture_context *tctx, const void *_data)
372 const struct registry_context *rctx =
373 (const struct registry_context *)_data;
374 struct registry_key *subkey = NULL, *root;
378 if (!create_test_key(tctx, rctx, "Dusseldorf", &root, &subkey))
381 error = reg_val_set(subkey, "Answer", REG_DWORD,
382 data_blob_talloc(tctx, &data, sizeof(data)));
383 torture_assert_werr_ok (tctx, error, "setting value");
389 * Test getting/setting security descriptors
391 static bool test_security(struct torture_context *tctx, const void *_data)
393 const struct registry_context *rctx =
394 (const struct registry_context *)_data;
395 struct registry_key *subkey = NULL, *root;
397 struct security_descriptor *osd, *nsd;
399 if (!create_test_key(tctx, rctx, "Düsseldorf", &root, &subkey))
402 osd = security_descriptor_dacl_create(tctx,
405 SID_NT_AUTHENTICATED_USERS,
406 SEC_ACE_TYPE_ACCESS_ALLOWED,
408 SEC_ACE_FLAG_OBJECT_INHERIT,
411 error = reg_set_security(subkey, osd);
412 torture_assert_werr_ok(tctx, error, "setting security");
414 error = reg_get_security(tctx, subkey, &nsd);
415 torture_assert_werr_ok (tctx, error, "setting security");
417 torture_assert(tctx, security_descriptor_equal(osd, nsd),
418 "security descriptor changed!");
424 * Test getting a value
426 static bool test_get_value(struct torture_context *tctx, const void *_data)
428 const struct registry_context *rctx =
429 (const struct registry_context *)_data;
430 struct registry_key *subkey = NULL, *root;
436 if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey))
439 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type,
441 torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
442 "getting missing value");
444 error = reg_val_set(subkey, __FUNCTION__, REG_DWORD,
445 data_blob_talloc(tctx, &value, 4));
446 torture_assert_werr_ok(tctx, error, "setting value");
448 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type,
450 torture_assert_werr_ok(tctx, error, "getting value");
452 torture_assert_int_equal(tctx, 4, data.length, "value length ok");
453 torture_assert(tctx, memcmp(data.data, &value, 4) == 0,
455 torture_assert_int_equal(tctx, REG_DWORD, type, "value type");
461 * Test unsetting a value
463 static bool test_del_value(struct torture_context *tctx, const void *_data)
465 const struct registry_context *rctx =
466 (const struct registry_context *)_data;
467 struct registry_key *subkey = NULL, *root;
473 if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey))
476 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type,
478 torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
479 "getting missing value");
481 error = reg_val_set(subkey, __FUNCTION__, REG_DWORD,
482 data_blob_talloc(tctx, &value, 4));
483 torture_assert_werr_ok (tctx, error, "setting value");
485 error = reg_del_value(subkey, __FUNCTION__);
486 torture_assert_werr_ok (tctx, error, "unsetting value");
488 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__,
490 torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
491 "getting missing value");
497 * Test listing values
499 static bool test_list_values(struct torture_context *tctx, const void *_data)
501 const struct registry_context *rctx =
502 (const struct registry_context *)_data;
503 struct registry_key *subkey = NULL, *root;
510 if (!create_test_key(tctx, rctx, "Bonn", &root, &subkey))
513 error = reg_val_set(subkey, "bar", REG_DWORD,
514 data_blob_talloc(tctx, &value, 4));
515 torture_assert_werr_ok (tctx, error, "setting value");
517 error = reg_key_get_value_by_index(tctx, subkey, 0, &name,
519 torture_assert_werr_ok(tctx, error, "getting value");
521 torture_assert_str_equal(tctx, name, "bar", "value name");
522 torture_assert_int_equal(tctx, 4, data.length, "value length");
523 torture_assert(tctx, memcmp(data.data, &value, 4) == 0,
525 torture_assert_int_equal(tctx, REG_DWORD, type, "value type");
527 error = reg_key_get_value_by_index(tctx, subkey, 1, &name,
529 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
530 "getting missing value");
535 static bool setup_local_registry(struct torture_context *tctx, void **data)
537 struct registry_context *rctx;
541 struct hive_key *hive_key;
542 const char *filename;
544 error = reg_open_local(tctx, &rctx, NULL, NULL);
545 torture_assert_werr_ok(tctx, error, "Opening local registry failed");
547 status = torture_temp_dir(tctx, "registry-local", &tempdir);
548 torture_assert_ntstatus_ok(tctx, status, "Creating temp dir failed");
550 filename = talloc_asprintf(tctx, "%s/classes_root.ldb", tempdir);
551 error = reg_open_ldb_file(tctx, filename, NULL, NULL, &hive_key);
552 torture_assert_werr_ok(tctx, error, "Opening classes_root file failed");
554 error = reg_mount_hive(rctx, hive_key, HKEY_CLASSES_ROOT, NULL);
555 torture_assert_werr_ok(tctx, error, "Mounting hive failed");
562 static void tcase_add_tests(struct torture_tcase *tcase)
564 torture_tcase_add_simple_test(tcase, "list_subkeys",
566 torture_tcase_add_simple_test(tcase, "get_predefined_key",
567 test_get_predefined);
568 torture_tcase_add_simple_test(tcase, "get_predefined_key",
569 test_get_predefined_unknown);
570 torture_tcase_add_simple_test(tcase, "create_key",
572 torture_tcase_add_simple_test(tcase, "create_key",
573 test_create_nested_subkey);
574 torture_tcase_add_simple_test(tcase, "key_add_abs",
576 torture_tcase_add_simple_test(tcase, "key_add_abs_top",
577 test_key_add_abs_top);
578 torture_tcase_add_simple_test(tcase, "set_value",
580 torture_tcase_add_simple_test(tcase, "get_value",
582 torture_tcase_add_simple_test(tcase, "list_values",
584 torture_tcase_add_simple_test(tcase, "del_key",
586 torture_tcase_add_simple_test(tcase, "del_value",
588 torture_tcase_add_simple_test(tcase, "flush_key",
590 torture_tcase_add_simple_test(tcase, "query_key",
592 torture_tcase_add_simple_test(tcase, "query_key_nums",
593 test_query_key_nums);
594 torture_tcase_add_simple_test(tcase, "test_predef_key_by_name",
595 test_predef_key_by_name);
596 torture_tcase_add_simple_test(tcase, "security",
598 torture_tcase_add_simple_test(tcase, "test_predef_key_by_name_invalid",
599 test_predef_key_by_name_invalid);
602 struct torture_suite *torture_registry_registry(TALLOC_CTX *mem_ctx)
604 struct torture_tcase *tcase;
605 struct torture_suite *suite = torture_suite_create(mem_ctx, "REGISTRY");
607 tcase = torture_suite_add_tcase(suite, "local");
608 torture_tcase_set_fixture(tcase, setup_local_registry, NULL);
609 tcase_add_tests(tcase);