1e56f125c5d168eac047c08a69328aff48881181
[jra/samba/.git] / source4 / lib / registry / tests / hive.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    local testing of registry library - hives
5
6    Copyright (C) Jelmer Vernooij 2005-2007
7
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.
12
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.
17
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.
21 */
22
23 #include "includes.h"
24 #include "lib/registry/registry.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/winreg.h"
27 #include "system/filesys.h"
28 #include "param/param.h"
29
30 static bool test_del_nonexistant_key(struct torture_context *tctx,
31                                      const void *test_data)
32 {
33         const struct hive_key *root = (const struct hive_key *)test_data;
34         WERROR error = hive_key_del(root, "bla");
35         torture_assert_werr_equal(tctx, error, WERR_BADFILE,
36                                   "invalid return code");
37
38         return true;
39 }
40
41 static bool test_keyinfo_root(struct torture_context *tctx,
42                               const void *test_data)
43 {
44         uint32_t num_subkeys, num_values;
45         const struct hive_key *root = (const struct hive_key *)test_data;
46         WERROR error;
47
48         /* This is a new backend. There should be no subkeys and no
49          * values */
50         error = hive_key_get_info(tctx, root, NULL, &num_subkeys, &num_values,
51                                   NULL, NULL, NULL, NULL);
52         torture_assert_werr_ok(tctx, error, "reg_key_num_subkeys()");
53
54         torture_assert_int_equal(tctx, num_subkeys, 0,
55                                  "New key has non-zero subkey count");
56
57         torture_assert_werr_ok(tctx, error, "reg_key_num_values");
58
59         torture_assert_int_equal(tctx, num_values, 0,
60                                  "New key has non-zero value count");
61
62         return true;
63 }
64
65 static bool test_keyinfo_nums(struct torture_context *tctx, void *test_data)
66 {
67         uint32_t num_subkeys, num_values;
68         struct hive_key *root = (struct hive_key *)test_data;
69         WERROR error;
70         struct hive_key *subkey;
71         uint32_t data = 42;
72
73         error = hive_key_add_name(tctx, root, "Nested Keyll", NULL,
74                                   NULL, &subkey);
75         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
76
77         error = hive_key_set_value(root, "Answer", REG_DWORD,
78                                data_blob_talloc(tctx, &data, sizeof(data)));
79         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
80
81         /* This is a new backend. There should be no subkeys and no
82          * values */
83         error = hive_key_get_info(tctx, root, NULL, &num_subkeys, &num_values,
84                                   NULL, NULL, NULL, NULL);
85         torture_assert_werr_ok(tctx, error, "reg_key_num_subkeys()");
86
87         torture_assert_int_equal(tctx, num_subkeys, 1, "subkey count");
88
89         torture_assert_werr_ok(tctx, error, "reg_key_num_values");
90
91         torture_assert_int_equal(tctx, num_values, 1, "value count");
92
93         return true;
94 }
95
96 static bool test_add_subkey(struct torture_context *tctx,
97                             const void *test_data)
98 {
99         WERROR error;
100         struct hive_key *subkey;
101         const struct hive_key *root = (const struct hive_key *)test_data;
102         TALLOC_CTX *mem_ctx = tctx;
103
104         error = hive_key_add_name(mem_ctx, root, "Nested Key", NULL,
105                                   NULL, &subkey);
106         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
107
108         error = hive_key_del(root, "Nested Key");
109         torture_assert_werr_ok(tctx, error, "reg_key_del");
110
111         return true;
112 }
113
114 static bool test_del_recursive(struct torture_context *tctx,
115                                const void *test_data)
116 {
117         WERROR error;
118         struct hive_key *subkey;
119         struct hive_key *subkey2;
120         const struct hive_key *root = (const struct hive_key *)test_data;
121         TALLOC_CTX *mem_ctx = tctx;
122         uint32_t data = 42;
123
124         /* Create a new key under the root */
125         error = hive_key_add_name(mem_ctx, root, "Parent Key", NULL,
126                                   NULL, &subkey);
127         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
128
129         /* Create a new key under "Parent Key" */
130         error = hive_key_add_name(mem_ctx, subkey, "Child Key", NULL,
131                                   NULL, &subkey2);
132         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
133
134         /* Create a new value under "Child Key" */
135         error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD,
136                                data_blob_talloc(mem_ctx, &data, sizeof(data)));
137         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
138
139         /* Deleting "Parent Key" will also delete "Child Key" and the value. */
140         error = hive_key_del(root, "Parent Key");
141         torture_assert_werr_ok(tctx, error, "hive_key_del");
142
143         return true;
144 }
145
146 static bool test_flush_key(struct torture_context *tctx, void *test_data)
147 {
148         struct hive_key *root = (struct hive_key *)test_data;
149
150         torture_assert_werr_ok(tctx, hive_key_flush(root), "flush key");
151
152         return true;
153 }
154
155 static bool test_del_key(struct torture_context *tctx, const void *test_data)
156 {
157         WERROR error;
158         struct hive_key *subkey;
159         const struct hive_key *root = (const struct hive_key *)test_data;
160         TALLOC_CTX *mem_ctx = tctx;
161
162         error = hive_key_add_name(mem_ctx, root, "Nested Key", NULL,
163                                   NULL, &subkey);
164         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
165
166         error = hive_key_del(root, "Nested Key");
167         torture_assert_werr_ok(tctx, error, "reg_key_del");
168
169         error = hive_key_del(root, "Nested Key");
170         torture_assert_werr_equal(tctx, error, WERR_BADFILE, "reg_key_del");
171
172         return true;
173 }
174
175 static bool test_set_value(struct torture_context *tctx,
176                            const void *test_data)
177 {
178         WERROR error;
179         struct hive_key *subkey;
180         const struct hive_key *root = (const struct hive_key *)test_data;
181         TALLOC_CTX *mem_ctx = tctx;
182         uint32_t data = 42;
183
184         error = hive_key_add_name(mem_ctx, root, "YA Nested Key", NULL,
185                                   NULL, &subkey);
186         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
187
188         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
189                                data_blob_talloc(mem_ctx, &data, sizeof(data)));
190         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
191
192         return true;
193 }
194
195 static bool test_get_value(struct torture_context *tctx, const void *test_data)
196 {
197         WERROR error;
198         struct hive_key *subkey;
199         const struct hive_key *root = (const struct hive_key *)test_data;
200         TALLOC_CTX *mem_ctx = tctx;
201         uint32_t data = 42;
202         uint32_t type;
203         DATA_BLOB value;
204
205         error = hive_key_add_name(mem_ctx, root, "EYA Nested Key", NULL,
206                                   NULL, &subkey);
207         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
208
209         error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
210         torture_assert_werr_equal(tctx, error, WERR_BADFILE,
211                                   "getting missing value");
212
213         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
214                                data_blob_talloc(mem_ctx, &data, sizeof(data)));
215         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
216
217         error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
218         torture_assert_werr_ok(tctx, error, "getting value");
219
220         torture_assert_int_equal(tctx, value.length, 4, "value length");
221         torture_assert_int_equal(tctx, type, REG_DWORD, "value type");
222
223         torture_assert_int_equal(tctx, data, IVAL(value.data, 0),
224                                  "value data");
225
226         return true;
227 }
228
229 static bool test_del_value(struct torture_context *tctx, const void *test_data)
230 {
231         WERROR error;
232         struct hive_key *subkey;
233         const struct hive_key *root = (const struct hive_key *)test_data;
234         TALLOC_CTX *mem_ctx = tctx;
235         uint32_t data = 42;
236         uint32_t type;
237         DATA_BLOB value;
238
239         error = hive_key_add_name(mem_ctx, root, "EEYA Nested Key", NULL,
240                                                          NULL, &subkey);
241         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
242
243         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
244                                data_blob_talloc(mem_ctx, &data, sizeof(data)));
245         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
246
247         error = hive_key_del_value(subkey, "Answer");
248         torture_assert_werr_ok(tctx, error, "deleting value");
249
250         error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
251         torture_assert_werr_equal(tctx, error, WERR_BADFILE, "getting value");
252
253         error = hive_key_del_value(subkey, "Answer");
254         torture_assert_werr_equal(tctx, error, WERR_BADFILE,
255                                   "deleting value");
256
257         return true;
258 }
259
260 static bool test_list_values(struct torture_context *tctx,
261                              const void *test_data)
262 {
263         WERROR error;
264         struct hive_key *subkey;
265         const struct hive_key *root = (const struct hive_key *)test_data;
266         TALLOC_CTX *mem_ctx = tctx;
267         uint32_t data = 42;
268         uint32_t type;
269         DATA_BLOB value;
270         const char *name;
271
272         error = hive_key_add_name(mem_ctx, root, "AYAYA Nested Key", NULL,
273                                   NULL, &subkey);
274         torture_assert_werr_ok(tctx, error, "hive_key_add_name");
275
276         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
277                                data_blob_talloc(mem_ctx, &data, sizeof(data)));
278         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
279
280         error = hive_get_value_by_index(mem_ctx, subkey, 0, &name,
281                                         &type, &value);
282         torture_assert_werr_ok(tctx, error, "getting value");
283
284         torture_assert_str_equal(tctx, name, "Answer", "value name");
285
286         torture_assert_int_equal(tctx, value.length, 4, "value length");
287         torture_assert_int_equal(tctx, type, REG_DWORD, "value type");
288         
289         
290         torture_assert_int_equal(tctx, data, IVAL(value.data, 0), "value data");
291
292         error = hive_get_value_by_index(mem_ctx, subkey, 1, &name,
293                                         &type, &value);
294         torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
295                                   "getting missing value");
296
297         return true;
298 }
299
300 static void tcase_add_tests(struct torture_tcase *tcase)
301 {
302         torture_tcase_add_simple_test_const(tcase, "del_nonexistant_key",
303                                                 test_del_nonexistant_key);
304         torture_tcase_add_simple_test_const(tcase, "add_subkey",
305                                                 test_add_subkey);
306         torture_tcase_add_simple_test(tcase, "flush_key",
307                                                 test_flush_key);
308         /* test_del_recursive() test must run before test_keyinfo_root().
309            test_keyinfo_root() checks the number of subkeys, which verifies
310            the recursive delete worked properly. */
311         torture_tcase_add_simple_test_const(tcase, "del_recursive",
312                                                 test_del_recursive);
313         torture_tcase_add_simple_test_const(tcase, "get_info",
314                                                 test_keyinfo_root);
315         torture_tcase_add_simple_test(tcase, "get_info_nums",
316                                                 test_keyinfo_nums);
317         torture_tcase_add_simple_test_const(tcase, "set_value",
318                                                 test_set_value);
319         torture_tcase_add_simple_test_const(tcase, "get_value",
320                                                 test_get_value);
321         torture_tcase_add_simple_test_const(tcase, "list_values",
322                                                 test_list_values);
323         torture_tcase_add_simple_test_const(tcase, "del_key",
324                                                 test_del_key);
325         torture_tcase_add_simple_test_const(tcase, "del_value",
326                                                 test_del_value);
327 }
328
329 static bool hive_setup_dir(struct torture_context *tctx, void **data)
330 {
331         struct hive_key *key;
332         WERROR error;
333         char *dirname;
334         NTSTATUS status;
335
336         status = torture_temp_dir(tctx, "hive-dir", &dirname);
337         if (!NT_STATUS_IS_OK(status))
338                 return false;
339
340         rmdir(dirname);
341
342         error = reg_create_directory(tctx, dirname, &key);
343         if (!W_ERROR_IS_OK(error)) {
344                 fprintf(stderr, "Unable to initialize dir hive\n");
345                 return false;
346         }
347
348         *data = key;
349
350         return true;
351 }
352
353 static bool hive_setup_ldb(struct torture_context *tctx, void **data)
354 {
355         struct hive_key *key;
356         WERROR error;
357         char *dirname;
358         NTSTATUS status;
359
360         status = torture_temp_dir(tctx, "hive-ldb", &dirname);
361         if (!NT_STATUS_IS_OK(status))
362                 return false;
363
364         rmdir(dirname);
365
366         error = reg_open_ldb_file(tctx, dirname, NULL, NULL, tctx->lp_ctx, &key);
367         if (!W_ERROR_IS_OK(error)) {
368                 fprintf(stderr, "Unable to initialize ldb hive\n");
369                 return false;
370         }
371
372         *data = key;
373
374         return true;
375 }
376
377 static bool hive_setup_regf(struct torture_context *tctx, void **data)
378 {
379         struct hive_key *key;
380         WERROR error;
381         char *dirname;
382         NTSTATUS status;
383
384         status = torture_temp_dir(tctx, "hive-dir", &dirname);
385         if (!NT_STATUS_IS_OK(status))
386                 return false;
387
388         rmdir(dirname);
389
390         error = reg_create_regf_file(tctx, lp_iconv_convenience(tctx->lp_ctx),
391                                      dirname, 5, &key);
392         if (!W_ERROR_IS_OK(error)) {
393                 fprintf(stderr, "Unable to create new regf file\n");
394                 return false;
395         }
396
397         *data = key;
398
399         return true;
400 }
401
402 static bool test_dir_refuses_null_location(struct torture_context *tctx)
403 {
404         torture_assert_werr_equal(tctx, WERR_INVALID_PARAM,
405                                   reg_open_directory(NULL, NULL, NULL),
406                                   "reg_open_directory accepts NULL location");
407         return true;
408 }
409
410 struct torture_suite *torture_registry_hive(TALLOC_CTX *mem_ctx)
411 {
412         struct torture_tcase *tcase;
413         struct torture_suite *suite = torture_suite_create(mem_ctx, "HIVE");
414
415         torture_suite_add_simple_test(suite, "dir-refuses-null-location",
416                                       test_dir_refuses_null_location);
417
418         tcase = torture_suite_add_tcase(suite, "dir");
419         torture_tcase_set_fixture(tcase, hive_setup_dir, NULL);
420         tcase_add_tests(tcase);
421
422         tcase = torture_suite_add_tcase(suite, "ldb");
423         torture_tcase_set_fixture(tcase, hive_setup_ldb, NULL);
424         tcase_add_tests(tcase);
425
426         tcase = torture_suite_add_tcase(suite, "regf");
427         torture_tcase_set_fixture(tcase, hive_setup_regf, NULL);
428         tcase_add_tests(tcase);
429
430         return suite;
431 }