r24674: Make sure results are always on a new line, fix typo in test name.
[kai/samba-autobuild/.git] / source4 / lib / registry / tests / registry.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of registry library - registry backend
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 "lib/cmdline/popt_common.h"
26 #include "torture/torture.h"
27 #include "librpc/gen_ndr/winreg.h"
28 #include "system/filesys.h"
29
30 NTSTATUS torture_temp_dir(struct torture_context *tctx, const char *prefix, 
31                                                                    const char **tempdir);
32
33 /**
34  * Test obtaining a predefined key.
35  */
36 static bool test_get_predefined(struct torture_context *tctx,
37                                                                 const void *_data)
38 {
39         const struct registry_context *rctx = _data;
40         struct registry_key *root;
41         WERROR error;
42
43         error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
44         torture_assert_werr_ok(tctx, error, 
45                                                    "getting predefined key failed");
46         return true;
47 }
48
49 /**
50  * Test obtaining a predefined key.
51  */
52 static bool test_get_predefined_unknown(struct torture_context *tctx,
53                                                                 const void *_data)
54 {
55         const struct registry_context *rctx = _data;
56         struct registry_key *root;
57         WERROR error;
58
59         error = reg_get_predefined_key(rctx, 1337, &root);
60         torture_assert_werr_equal(tctx, error, WERR_BADFILE,
61                                                    "getting predefined key failed");
62         return true;
63 }
64
65 /**
66  * Test creating a new subkey
67  */
68 static bool test_create_subkey(struct torture_context *tctx,
69                                                       const void *_data)
70 {
71         const struct registry_context *rctx = _data;
72         struct registry_key *root, *newkey;
73         WERROR error;
74
75         error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
76         torture_assert_werr_ok(tctx, error, 
77                                                    "getting predefined key failed");
78
79         error = reg_key_add_name(rctx, root, "Bad Bentheim", NULL, NULL, &newkey);
80         torture_assert_werr_ok(tctx, error, "Creating key return code");
81         torture_assert(tctx, newkey != NULL, "Creating new key");
82
83         return true;
84 }
85
86 /**
87  * Test creating a new nested subkey
88  */
89 static bool test_create_nested_subkey(struct torture_context *tctx,
90                                                       const void *_data)
91 {
92         const struct registry_context *rctx = _data;
93         struct registry_key *root, *newkey1, *newkey2;
94         WERROR error;
95
96         error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
97         torture_assert_werr_ok(tctx, error, 
98                                                    "getting predefined key failed");
99
100         error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL, 
101                                                          &newkey1);
102         torture_assert_werr_ok(tctx, error, "Creating key return code");
103         torture_assert(tctx, newkey2 != NULL, "Creating new key");
104
105         error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL, 
106                                                          &newkey2);
107         torture_assert_werr_ok(tctx, error, "Creating key return code");
108         torture_assert(tctx, newkey2 != NULL, "Creating new key");
109
110         return true;
111 }
112
113 /**
114  * Test creating a new subkey
115  */
116 static bool test_key_add_abs_top(struct torture_context *tctx,
117                                                          const void *_data)
118 {
119         const struct registry_context *rctx = _data;
120         struct registry_key *root;
121         WERROR error;
122
123         error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT", 0, NULL, &root);
124         torture_assert_werr_equal(tctx, error, WERR_ALREADY_EXISTS, "create top level");
125
126         return true;
127 }
128
129 /**
130  * Test creating a new subkey
131  */
132 static bool test_key_add_abs(struct torture_context *tctx,
133                                                          const void *_data)
134 {
135         WERROR error;
136         const struct registry_context *rctx = _data;
137         struct registry_key *root, *result1, *result2;
138
139         error = reg_key_add_abs(tctx, rctx,  "HKEY_CLASSES_ROOT\\bloe", 0, NULL, &result1);
140         torture_assert_werr_ok(tctx, error, "create lowest");
141
142         error = reg_key_add_abs(tctx, rctx,  "HKEY_CLASSES_ROOT\\bloe\\bla", 0, NULL, &result1);
143         torture_assert_werr_ok(tctx, error, "create nested");
144
145         error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
146         torture_assert_werr_ok(tctx, error, 
147                                                    "getting predefined key failed");
148
149         error = reg_open_key(tctx, root, "bloe", &result2);
150         torture_assert_werr_ok(tctx, error, "opening key");
151
152         error = reg_open_key(tctx, root, "bloe\\bla", &result2);
153         torture_assert_werr_ok(tctx, error, "opening key");
154
155         return true;
156 }
157
158
159 static bool test_del_key(struct torture_context *tctx, const void *_data)
160 {
161         const struct registry_context *rctx = _data;
162         struct registry_key *root, *newkey;
163         WERROR error;
164
165         error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
166         torture_assert_werr_ok(tctx, error, 
167                                                    "getting predefined key failed");
168
169         error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL, &newkey);
170
171         torture_assert_werr_ok(tctx, error, "Creating key return code");
172         torture_assert(tctx, newkey != NULL, "Creating new key");
173
174         error = reg_key_del(root, "Hamburg");
175         torture_assert_werr_ok(tctx, error, "Delete key");
176
177         error = reg_key_del(root, "Hamburg");
178         torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, 
179                                                           "Delete missing key");
180
181         return true;
182 }
183
184 /**
185  * Convenience function for opening the HKEY_CLASSES_ROOT hive and 
186  * creating a single key for testing purposes.
187  */
188 static bool create_test_key(struct torture_context *tctx, 
189                                                         const struct registry_context *rctx,
190                                                         const char *name, 
191                                                         struct registry_key **root,
192                                                         struct registry_key **subkey)
193 {
194         WERROR error;
195
196         error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, root);
197         torture_assert_werr_ok(tctx, error, 
198                                                    "getting predefined key failed");
199
200         error = reg_key_add_name(rctx, *root, name, NULL, NULL, subkey);
201         torture_assert_werr_ok(tctx, error, "Creating key return code");
202
203         return true;
204 }
205
206
207 static bool test_flush_key(struct torture_context *tctx, const void *_data)
208 {
209         const struct registry_context *rctx = _data;
210         struct registry_key *root, *subkey;
211         WERROR error;
212
213         if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey))
214                 return false;
215
216         error = reg_key_flush(subkey);
217         torture_assert_werr_ok(tctx, error, "flush key");
218
219         torture_assert_werr_equal(tctx, reg_key_flush(NULL), 
220                                                           WERR_INVALID_PARAM, "flush key");
221
222         return true;
223 }
224
225 static bool test_query_key(struct torture_context *tctx, const void *_data)
226 {
227         const struct registry_context *rctx = _data;
228         struct registry_key *root, *subkey;
229         WERROR error;
230         NTTIME last_changed_time;
231         uint32_t num_subkeys, num_values;
232         const char *classname;
233
234         if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey))
235                 return false;
236
237         error = reg_key_get_info(tctx, subkey, &classname,
238                                                          &num_subkeys, &num_values,
239                                                          &last_changed_time);
240
241         torture_assert_werr_ok(tctx, error, "get info key");
242         torture_assert(tctx, classname == NULL, "classname");
243         torture_assert_int_equal(tctx, num_subkeys, 0, "num subkeys");
244         torture_assert_int_equal(tctx, num_values, 0, "num values");
245
246         return true;
247 }
248
249 static bool test_query_key_nums(struct torture_context *tctx, const void *_data)
250 {
251         const struct registry_context *rctx = _data;
252         struct registry_key *root, *subkey1, *subkey2;
253         WERROR error;
254         uint32_t num_subkeys, num_values;
255         uint32_t data = 42;
256
257         if (!create_test_key(tctx, rctx, "Berlin", &root, &subkey1))
258                 return false;
259
260         error = reg_key_add_name(rctx, subkey1, "Bentheim", NULL, NULL, &subkey2);
261         torture_assert_werr_ok(tctx, error, "Creating key return code");
262
263         error = reg_val_set(subkey1, "Answer", REG_DWORD, 
264                                                 data_blob_talloc(tctx, &data, sizeof(data)));
265         torture_assert_werr_ok(tctx, error, "set value");
266
267         error = reg_key_get_info(tctx, subkey1, NULL, &num_subkeys,
268                                                          &num_values, NULL);
269
270         torture_assert_werr_ok(tctx, error, "get info key");
271         torture_assert_int_equal(tctx, num_subkeys, 1, "num subkeys");
272         torture_assert_int_equal(tctx, num_values, 1, "num values");
273
274         return true;
275 }
276
277 /**
278  * Test that the subkeys of a key can be enumerated, that 
279  * the returned parameters for get_subkey_by_index are optional and 
280  * that enumerating the parents of a non-top-level node works.
281  */
282 static bool test_list_subkeys(struct torture_context *tctx, const void *_data)
283 {
284         const struct registry_context *rctx = _data;
285         struct registry_key *subkey = NULL, *root;
286         WERROR error;
287         NTTIME last_mod_time;
288         const char *classname, *name;
289
290         if (!create_test_key(tctx, rctx, "Goettingen", &root, &subkey))
291                 return false;
292
293         error = reg_key_get_subkey_by_index(tctx, root, 0, &name, &classname, 
294                                                                 &last_mod_time);
295
296         torture_assert_werr_ok(tctx, error, "Enum keys return code");
297         torture_assert_str_equal(tctx, name, "Goettingen", "Enum keys data");
298
299
300         error = reg_key_get_subkey_by_index(tctx, root, 0, NULL, NULL, NULL);
301
302         torture_assert_werr_ok(tctx, error, "Enum keys with NULL arguments return code");
303
304         error = reg_key_get_subkey_by_index(tctx, root, 1, NULL, NULL, NULL);
305         
306         torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 
307                                                           "Invalid error for no more items");
308
309         error = reg_key_get_subkey_by_index(tctx, subkey, 0, NULL, NULL, NULL);
310         
311         torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 
312                                                           "Invalid error for no more items");
313
314         return true;
315 }
316
317 /**
318  * Test setting a value
319  */
320 static bool test_set_value(struct torture_context *tctx, const void *_data)
321 {
322         const struct registry_context *rctx = _data;
323         struct registry_key *subkey = NULL, *root;
324         WERROR error;
325         uint32_t data = 42;
326
327         if (!create_test_key(tctx, rctx, "Dusseldorf", &root, &subkey))
328                 return false;
329
330         error = reg_val_set(subkey, "Answer", REG_DWORD, 
331                                                 data_blob_talloc(tctx, &data, sizeof(data)));
332         torture_assert_werr_ok (tctx, error, "setting value");
333
334         return true;
335 }
336
337 /**
338  * Test getting a value
339  */
340 static bool test_get_value(struct torture_context *tctx, const void *_data)
341 {
342         const struct registry_context *rctx = _data;
343         struct registry_key *subkey = NULL, *root;
344         WERROR error;
345         DATA_BLOB data;
346         uint32_t value = 42;
347         uint32_t type;
348
349         if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey))
350                 return false;
351
352         error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, 
353                                                                           &data);
354         torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, 
355                                                           "getting missing value");
356
357         error = reg_val_set(subkey, __FUNCTION__, REG_DWORD, 
358                                                 data_blob_talloc(tctx, &value, 4));
359         torture_assert_werr_ok (tctx, error, "setting value");
360
361         error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, 
362                                                                           &data);
363         torture_assert_werr_ok(tctx, error, "getting value");
364
365         torture_assert_int_equal(tctx, 4, data.length, "value length ok");
366         torture_assert(tctx, memcmp(data.data, &value, 4) == 0, "value content ok");
367         torture_assert_int_equal(tctx, REG_DWORD, type, "value type");
368
369         return true;
370 }
371
372 /**
373  * Test unsetting a value
374  */
375 static bool test_del_value(struct torture_context *tctx, const void *_data)
376 {
377         const struct registry_context *rctx = _data;
378         struct registry_key *subkey = NULL, *root;
379         WERROR error;
380         DATA_BLOB data;
381         uint32_t value = 42;
382         uint32_t type;
383
384         if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey))
385                 return false;
386
387         error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, 
388                                                                           &data);
389         torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, 
390                                                           "getting missing value");
391
392         error = reg_val_set(subkey, __FUNCTION__, REG_DWORD, 
393                                                 data_blob_talloc(tctx, &value, 4));
394         torture_assert_werr_ok (tctx, error, "setting value");
395
396         error = reg_del_value(subkey, __FUNCTION__);
397         torture_assert_werr_ok (tctx, error, "unsetting value");
398
399         error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, &data);
400         torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, 
401                                                           "getting missing value");
402
403         return true;
404 }
405
406 /**
407  * Test listing values
408  */
409 static bool test_list_values(struct torture_context *tctx, const void *_data)
410 {
411         const struct registry_context *rctx = _data;
412         struct registry_key *subkey = NULL, *root;
413         WERROR error;
414         DATA_BLOB data;
415         uint32_t value = 42;
416         uint32_t type;
417         const char *name;
418
419         if (!create_test_key(tctx, rctx, "Bonn", &root, &subkey))
420                 return false;
421
422         error = reg_val_set(subkey, "bar", REG_DWORD, 
423                                                 data_blob_talloc(tctx, &value, 4));
424         torture_assert_werr_ok (tctx, error, "setting value");
425
426         error = reg_key_get_value_by_index(tctx, subkey, 0, &name, &type, &data);
427         torture_assert_werr_ok(tctx, error, "getting value");
428
429         torture_assert_str_equal(tctx, name, "bar", "value name");
430         torture_assert_int_equal(tctx, 4, data.length, "value length");
431         torture_assert(tctx, memcmp(data.data, &value, 4) == 0, "value content");
432         torture_assert_int_equal(tctx, REG_DWORD, type, "value type");
433
434         error = reg_key_get_value_by_index(tctx, subkey, 1, &name, &type, &data);
435         torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 
436                                                           "getting missing value");
437
438         return true;
439 }
440
441 static bool setup_local_registry(struct torture_context *tctx, void **data)
442 {
443         struct registry_context *rctx;
444         WERROR error;
445         const char *tempdir;
446         NTSTATUS status;
447         struct hive_key *hive_key;
448
449         error = reg_open_local(tctx, &rctx, NULL, NULL);
450         if (!W_ERROR_IS_OK(error))
451                 return false;
452
453         status = torture_temp_dir(tctx, "registry-local", &tempdir);
454         if (!NT_STATUS_IS_OK(status))
455                 return false;
456
457         error = reg_open_ldb_file(tctx, 
458                                           talloc_asprintf(tctx, "%s/classes_root.ldb", tempdir),
459                                           NULL,
460                                           NULL,
461                                           &hive_key);
462         if (!W_ERROR_IS_OK(error))
463                 return false;
464
465         error = reg_mount_hive(rctx, hive_key, HKEY_CLASSES_ROOT, NULL);
466         if (!W_ERROR_IS_OK(error))
467                 return false;
468
469         *data = rctx;
470
471         return true;
472 }
473
474 static void tcase_add_tests(struct torture_tcase *tcase)
475 {
476         torture_tcase_add_simple_test(tcase, "list_subkeys", test_list_subkeys);
477         torture_tcase_add_simple_test(tcase, "get_predefined_key",
478                                                                         test_get_predefined);
479         torture_tcase_add_simple_test(tcase, "get_predefined_key",
480                                                                         test_get_predefined_unknown);
481         torture_tcase_add_simple_test(tcase, "create_key", test_create_subkey);
482         torture_tcase_add_simple_test(tcase, "create_key", 
483                                                                   test_create_nested_subkey);
484         torture_tcase_add_simple_test(tcase, "key_add_abs", test_key_add_abs);
485         torture_tcase_add_simple_test(tcase, "key_add_abs_top", test_key_add_abs_top);
486         torture_tcase_add_simple_test(tcase, "set_value", test_set_value);
487         torture_tcase_add_simple_test(tcase, "get_value", test_get_value);
488         torture_tcase_add_simple_test(tcase, "list_values", test_list_values);
489         torture_tcase_add_simple_test(tcase, "del_key", test_del_key);
490         torture_tcase_add_simple_test(tcase, "del_value", test_del_value);
491         torture_tcase_add_simple_test(tcase, "flush_key", test_flush_key);
492         torture_tcase_add_simple_test(tcase, "query_key", test_query_key);
493         torture_tcase_add_simple_test(tcase, "query_key_nums", test_query_key_nums);
494 }
495
496 struct torture_suite *torture_registry_registry(TALLOC_CTX *mem_ctx) 
497 {
498         struct torture_tcase *tcase;
499         struct torture_suite *suite = torture_suite_create(mem_ctx, 
500                                                                                                            "REGISTRY");
501         
502         tcase = torture_suite_add_tcase(suite, "local");
503         torture_tcase_set_fixture(tcase, setup_local_registry, NULL);
504         tcase_add_tests(tcase);
505
506         return suite;
507 }