Imported Upstream version 3.3.0
[debian/amanda] / installcheck / Amanda_Config.pl
1 # Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc.  All Rights Reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License version 2 as published
5 # by the Free Software Foundation.
6 #
7 # This program is distributed in the hope that it will be useful, but
8 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
10 # for more details.
11 #
12 # You should have received a copy of the GNU General Public License along
13 # with this program; if not, write to the Free Software Foundation, Inc.,
14 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 #
16 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
17 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
18
19 use Test::More tests => 224;
20 use strict;
21 use warnings;
22 use Data::Dumper;
23
24 use lib "@amperldir@";
25 use Installcheck::Config;
26 use Amanda::Paths;
27 use Amanda::Tests;
28 use Amanda::Config qw( :init :getconf string_to_boolean amandaify_property_name );
29 use Amanda::Debug;
30
31 my $testconf;
32 my $config_overrides;
33
34 Amanda::Debug::dbopen("installcheck");
35 Installcheck::log_test_output();
36
37 # utility function
38
39 sub diag_config_errors {
40     my ($level, @errors) = Amanda::Config::config_errors();
41     for my $errmsg (@errors) {
42         diag $errmsg;
43     }
44 }
45
46 ##
47 # Try starting with no configuration at all
48
49 is(config_init(0, ''), $CFGERR_OK,
50     "Initialize with no configuration")
51     or diag_config_errors();
52
53 config_uninit();
54 $config_overrides = new_config_overrides(1);
55 add_config_override($config_overrides, "tapedev", "null:TEST");
56 set_config_overrides($config_overrides);
57
58 is(config_init(0, undef), $CFGERR_OK,
59     "Initialize with no configuration, passing a NULL config name")
60     or diag_config_errors();
61
62 is(getconf($CNF_TAPEDEV), "null:TEST",
63     "config overwrites work with null config");
64
65 ##
66 # Check out error handling
67
68 $testconf = Installcheck::Config->new();
69 $testconf->add_param('label_new_tapes', '"xx"'); # a deprecated keyword -> warning
70 $testconf->write();
71
72 {
73     is(config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"), $CFGERR_WARNINGS,
74         "Deprecated keyword generates a warning");
75     my ($error_level, @errors) = Amanda::Config::config_errors();
76     like($errors[0], qr/is deprecated/, 
77         "config_get_errors returns the warning string");
78
79     Amanda::Config::config_clear_errors();
80     ($error_level, @errors) = Amanda::Config::config_errors();
81     is(scalar(@errors), 0, "config_clear_errors clears error list");
82 }
83
84 $testconf = Installcheck::Config->new();
85 $testconf->add_param('invalid-param', 'random-value'); # a deprecated keyword -> warning
86 $testconf->write();
87
88 is(config_init($CONFIG_INIT_EXPLICIT_NAME, "NO-SUCH-CONFIGURATION"), $CFGERR_ERRORS,
89     "Non-existent config generates an error");
90
91 is(config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"), $CFGERR_ERRORS,
92     "Invalid keyword generates an error");
93
94 ##
95 # try a client configuration
96
97 # (note use of uppercase letters to test lower-casing of property names)
98 $testconf = Installcheck::Config->new();
99 $testconf->add_client_param('property', '"client-prop" "yep"');
100 $testconf->add_client_param('property', 'priority "clIent-prop1" "foo"');
101 $testconf->add_client_param('property', 'append "clieNt-prop" "bar"');
102 $testconf->add_client_param('property', '"ANotHer_prOp" "baz"');
103 $testconf->add_client_param('property', 'append "ANOTHER-prop" "boo"');
104 $testconf->write();
105
106 my $cfg_result = config_init($CONFIG_INIT_CLIENT, undef);
107 is($cfg_result, $CFGERR_OK,
108     "Load test client configuration")
109     or diag_config_errors();
110
111 is_deeply(getconf($CNF_PROPERTY), { "client-prop1" => { priority => 1,
112                                                         append   => 0,
113                                                         values => [ "foo" ]},
114                                     "client-prop" => { priority => 0,
115                                                        append   => 1,
116                                                        values => [ "yep", "bar" ] },
117                                     "another-prop" => { priority => 0,
118                                                         append   => 1,
119                                                         values => [ "baz", "boo" ] }},
120     "Client PROPERTY parameter parsed correctly");
121
122 ##
123 # Parse up a basic configuration
124
125 # invent a "large" unsigned number, and make $size_t_num 
126 # depend on the length of size_t
127 my $int64_num = '171801575472'; # 0xA000B000C000 / 1024
128 my $size_t_num;
129 if (Amanda::Tests::sizeof_size_t() > 4) {
130     $size_t_num = $int64_num;
131 } else {
132     $size_t_num = '2147483647'; # 0x7fffffff
133 }
134
135 $testconf = Installcheck::Config->new();
136 $testconf->add_param('reserve', '75');
137 $testconf->add_param('autoflush', 'yes');
138 $testconf->add_param('usetimestamps', '0');
139 $testconf->add_param('tapedev', '"/dev/foo"');
140 $testconf->add_param('bumpsize', $int64_num);
141 $testconf->add_param('bumpmult', '1.4');
142 $testconf->add_param('reserved_udp-port', '100,200'); # note use of '-' and '_'
143 $testconf->add_param('device_output_buffer_size', $size_t_num);
144 $testconf->add_param('taperalgo', 'last');
145 $testconf->add_param('device_property', '"foo" "bar"');
146 $testconf->add_param('device_property', '"blUE" "car" "tar"');
147 $testconf->add_param('autolabel', 'non-amanda empty');
148 $testconf->add_param('displayunit', '"m"');
149 $testconf->add_param('debug_auth', '1');
150 $testconf->add_tapetype('mytapetype', [
151     'comment' => '"mine"',
152     'length' => '128 M',
153     'part_size' => '100M',
154     'part_cache_type' => 'disk',
155     'part_cache_dir' => '"/usr/bin"',
156     'part_cache_max_size' => '50M',
157 ]);
158 $testconf->add_dumptype('mydump-type', [    # note dash
159     'comment' => '"mine"',
160     'priority' => 'high',  # == 2
161     'bumpsize' => $int64_num,
162     'bumpmult' => 1.75,
163     'starttime' => 1829,
164     'holdingdisk' => 'required',
165     'compress' => 'client best',
166     'encrypt' => 'server',
167     'strategy' => 'incronly',
168     'comprate' => '0.25,0.75',
169     'exclude list' => '"foo" "bar"',
170     'exclude list append' => '"true" "star"',
171     'exclude file' => '"foolist"',
172     'include list' => '"bing" "ting"',
173     'include list append' => '"string" "fling"',
174     'include file optional' => '"rhyme"',
175     'property' => '"prop" "erty"',
176     'property' => '"DROP" "qwerty" "asdfg"',
177     'estimate' => 'server calcsize client',
178     'allow_split' => 'no',
179     'allow_split' => 'no',
180 ]);
181 $testconf->add_dumptype('second_dumptype', [ # note underscore
182     '' => 'mydump-type',
183     'comment' => '"refers to mydump-type with a dash"',
184 ]);
185 $testconf->add_dumptype('third_dumptype', [
186     '' => 'second_dumptype',
187     'comment' => '"refers to second_dumptype with an underscore"',
188     'recovery-limit' => '"left" same-host "right"',
189 ]);
190 $testconf->add_interface('ethernet', [
191     'comment' => '"mine"',
192     'use' => '100',
193 ]);
194 $testconf->add_interface('nic', [
195     'comment' => '"empty"',
196 ]);
197 $testconf->add_holdingdisk('hd1', [
198     'comment' => '"mine"',
199     'directory' => '"/mnt/hd1"',
200     'use' => '100M',
201     'chunksize' => '1024k',
202 ]);
203 $testconf->add_holdingdisk('hd2', [
204     'comment' => '"empty"',
205 ]);
206 $testconf->add_application('my_app', [
207     'comment' => '"my_app_comment"',
208     'plugin' => '"amgtar"',
209 ]);
210 $testconf->add_script('my_script', [
211   'comment' => '"my_script_comment"',
212   'plugin' => '"script-email"',
213   'execute-on' => 'pre-host-backup, post-host-backup',
214   'execute-where' => 'client',
215   'property' => '"mailto" "amandabackup" "amanda"',
216 ]);
217 $testconf->add_device('my_device', [
218   'comment' => '"my device is mine, not yours"',
219   'tapedev' => '"tape:/dev/nst0"',
220   'device_property' => '"BLOCK_SIZE" "128k"',
221   'device_property' => '"CoMmENT" "what up?"',
222 ]);
223 $testconf->add_changer('my_changer', [
224   'comment' => '"my changer is mine, not yours"',
225   'tpchanger' => '"chg-foo"',
226   'changerdev' => '"/dev/sg0"',
227   'changerfile' => '"chg.state"',
228   'property' => '"testprop" "testval"',
229   'device_property' => '"testdprop" "testdval"',
230 ]);
231 $testconf->add_interactivity('my_interactivity', [
232   'comment' => '"my interactivity is mine, not yours"',
233   'plugin'  => '"MY-interactivity"',
234   'property' => '"testprop" "testval"',
235 ]);
236
237 $testconf->add_taperscan('my_taperscan', [
238   'comment' => '"my taperscan is mine, not yours"',
239   'plugin'  => '"MY-taperscan"',
240   'property' => '"testprop" "testval"',
241 ]);
242
243 $testconf->write();
244
245 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
246 if (!is($cfg_result, $CFGERR_OK,
247     "Load test configuration")) {
248     diag_config_errors();
249     die "aborting after config errors";
250 }
251
252 is(Amanda::Config::get_config_name(), "TESTCONF",
253     "config_name set");
254 is(Amanda::Config::get_config_dir(), "$CONFIG_DIR/TESTCONF",
255     "config_dir set");
256 is(Amanda::Config::get_config_filename(),
257     "$CONFIG_DIR/TESTCONF/amanda.conf",
258     "config_filename set");
259
260 is(getconf($CNF_RESERVE), 75,
261     "integer global confparm");
262 is(getconf($CNF_BUMPSIZE), $int64_num+0,
263     "int64 global confparm");
264 is(getconf($CNF_TAPEDEV), "/dev/foo",
265     "string global confparm");
266 is(getconf($CNF_DEVICE_OUTPUT_BUFFER_SIZE), $size_t_num+0,
267     "size global confparm");
268 ok(getconf($CNF_AUTOFLUSH),
269     "boolean global confparm");
270 is(getconf($CNF_USETIMESTAMPS), 0,
271     "boolean global confparm, passing an integer (0)");
272 is(getconf($CNF_TAPERALGO), $Amanda::Config::ALGO_LAST,
273     "taperalgo global confparam");
274 is_deeply([getconf($CNF_RESERVED_UDP_PORT)], [100,200],
275     "intrange global confparm");
276 is(getconf($CNF_DISPLAYUNIT), "M",
277     "displayunit is correctly uppercased");
278 is_deeply(getconf($CNF_DEVICE_PROPERTY),
279           { "foo" => { priority => 0, append => 0, values => ["bar"]},
280             "blue" => { priority => 0, append => 0,
281                         values => ["car", "tar"]} },
282         "proplist global confparm");
283 is_deeply(getconf($CNF_AUTOLABEL),
284         { template => undef, other_config => '',
285           non_amanda => 1, volume_error => '', empty => 1 },
286         "'autolabel non-amanda empty' represented correctly");
287 ok(getconf_seen($CNF_TAPEDEV),
288     "'tapedev' parm was seen");
289 ok(!getconf_seen($CNF_CHANGERFILE),
290     "'changerfile' parm was not seen");
291
292 is(Amanda::Config::getconf_unit_divisor(), 1024,
293     "correct unit divisor (from displayunit -> KB)");
294 ok($Amanda::Config::debug_auth,
295     "debug_auth setting reflected in global variable");
296 ok(!$Amanda::Config::debug_amandad,
297     "debug_amandad defaults to false");
298
299 my $ttyp = lookup_tapetype("mytapetype");
300 ok($ttyp, "found mytapetype");
301 is(tapetype_getconf($ttyp, $TAPETYPE_COMMENT), 'mine',
302     "tapetype comment");
303 is(tapetype_getconf($ttyp, $TAPETYPE_LENGTH), 128 * 1024,
304     "tapetype comment");
305
306 ok(tapetype_seen($ttyp, $TAPETYPE_COMMENT),
307     "tapetype comment was seen");
308 ok(!tapetype_seen($ttyp, $TAPETYPE_LBL_TEMPL),
309     "tapetype lbl_templ was not seen");
310
311 is(tapetype_getconf($ttyp, $TAPETYPE_PART_SIZE), 100*1024,
312     "tapetype part_size");
313 is(tapetype_getconf($ttyp, $TAPETYPE_PART_CACHE_TYPE), $PART_CACHE_TYPE_DISK,
314     "tapetype part_cache_type");
315 is(tapetype_getconf($ttyp, $TAPETYPE_PART_CACHE_DIR), "/usr/bin",
316     "tapetype part_cache_dir");
317 is(tapetype_getconf($ttyp, $TAPETYPE_PART_CACHE_MAX_SIZE), 50*1024,
318     "tapetype part_cache_max_size");
319
320 is_deeply([ sort(+getconf_list("tapetype")) ],
321           [ sort("mytapetype", "TEST-TAPE") ],
322     "getconf_list lists all tapetypes");
323
324 my $dtyp = lookup_dumptype("mydump-type");
325 ok($dtyp, "found mydump-type");
326 is(dumptype_getconf($dtyp, $DUMPTYPE_COMMENT), 'mine',
327     "dumptype string");
328 is(dumptype_getconf($dtyp, $DUMPTYPE_PRIORITY), 2,
329     "dumptype priority");
330 is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), $int64_num+0,
331     "dumptype size");
332 is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPMULT), 1.75,
333     "dumptype real");
334 is(dumptype_getconf($dtyp, $DUMPTYPE_STARTTIME), 1829,
335     "dumptype time");
336 is(dumptype_getconf($dtyp, $DUMPTYPE_HOLDINGDISK), $HOLD_REQUIRED,
337     "dumptype holdingdisk");
338 is(dumptype_getconf($dtyp, $DUMPTYPE_COMPRESS), $COMP_BEST,
339     "dumptype compress");
340 is(dumptype_getconf($dtyp, $DUMPTYPE_ENCRYPT), $ENCRYPT_SERV_CUST,
341     "dumptype encrypt");
342 is(dumptype_getconf($dtyp, $DUMPTYPE_STRATEGY), $DS_INCRONLY,
343     "dumptype strategy");
344 is_deeply([dumptype_getconf($dtyp, $DUMPTYPE_COMPRATE)], [0.25, 0.75],
345     "dumptype comprate");
346 is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_INCLUDE),
347     { 'file' => [ 'rhyme' ],
348       'list' => [ 'bing', 'ting', 'string', 'fling' ],
349       'optional' => 1 },
350     "dumptype include list");
351 is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE),
352     { 'file' => [ 'foolist' ],
353       'list' => [ 'foo', 'bar', 'true', 'star' ],
354       'optional' => 0 },
355     "dumptype exclude list");
356 is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_ESTIMATELIST),
357           [ $ES_SERVER, $ES_CALCSIZE, $ES_CLIENT ],
358     "dumptype estimate list");
359 is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_PROPERTY),
360           { "prop" => { priority => 0, append => 0, values => ["erty"]},
361             "drop" => { priority => 0, append => 0,
362                         values => ["qwerty", "asdfg"] }},
363         "dumptype proplist");
364 is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
365     [],
366     "dumptype recovery limit with no limit specified => empty");
367
368 ok(dumptype_seen($dtyp, $DUMPTYPE_EXCLUDE),
369     "'exclude' parm was seen");
370 ok(!dumptype_seen($dtyp, $DUMPTYPE_RECORD),
371     "'record' parm was not seen");
372
373 is_deeply([ sort(+getconf_list("dumptype")) ],
374           [ sort(qw(
375             mydump-type second_dumptype third_dumptype
376             NO-COMPRESS COMPRESS-FAST COMPRESS-BEST COMPRESS-CUST
377             SRVCOMPRESS BSD-AUTH BSDTCP-AUTH NO-RECORD NO-HOLD
378             NO-FULL
379             )) ],
380     "getconf_list lists all dumptypes (including defaults)");
381 is(dumptype_getconf($dtyp, $DUMPTYPE_ALLOW_SPLIT), 0,
382     "dumptype allow_split");
383
384 my $iface = lookup_interface("ethernet");
385 ok($iface, "found ethernet");
386 is(interface_name($iface), "ethernet",
387     "interface knows its name");
388 is(interface_getconf($iface, $INTER_COMMENT), 'mine',
389     "interface comment");
390 is(interface_getconf($iface, $INTER_MAXUSAGE), 100,
391     "interface maxusage");
392
393 $iface = lookup_interface("nic");
394 ok($iface, "found nic");
395 ok(interface_seen($iface, $INTER_COMMENT),
396     "seen set for parameters that appeared");
397 ok(!interface_seen($iface, $INTER_MAXUSAGE),
398     "seen not set for parameters that did not appear");
399
400 is_deeply([ sort(+getconf_list("interface")) ],
401           [ sort('ethernet', 'nic', 'default') ],
402     "getconf_list lists all interfaces (in any order)");
403
404 skip "error loading config", 13 unless $cfg_result == $CFGERR_OK;
405 my $hdisk = lookup_holdingdisk("hd1");
406 ok($hdisk, "found hd1");
407 is(holdingdisk_name($hdisk), "hd1",
408     "hd1 knows its name");
409 is(holdingdisk_getconf($hdisk, $HOLDING_COMMENT), 'mine',
410     "holdingdisk comment");
411 is(holdingdisk_getconf($hdisk, $HOLDING_DISKDIR), '/mnt/hd1',
412     "holdingdisk diskdir (directory)");
413 is(holdingdisk_getconf($hdisk, $HOLDING_DISKSIZE), 100*1024,
414     "holdingdisk disksize (use)");
415 is(holdingdisk_getconf($hdisk, $HOLDING_CHUNKSIZE), 1024,
416     "holdingdisk chunksize");
417
418 $hdisk = lookup_holdingdisk("hd2");
419 ok($hdisk, "found hd2");
420 ok(holdingdisk_seen($hdisk, $HOLDING_COMMENT),
421     "seen set for parameters that appeared");
422 ok(!holdingdisk_seen($hdisk, $HOLDING_CHUNKSIZE),
423     "seen not set for parameters that did not appear");
424
425 # only holdingdisks have this linked-list structure
426 # exposed
427 my $hdisklist = getconf($CNF_HOLDINGDISK);
428 my $first_disk = @$hdisklist[0];
429 $hdisk = lookup_holdingdisk($first_disk);
430 like(holdingdisk_name($hdisk), qr/hd[12]/,
431     "one disk is first in list of holdingdisks");
432 $hdisk = lookup_holdingdisk(@$hdisklist[1]);
433 like(holdingdisk_name($hdisk), qr/hd[12]/,
434     "another is second in list of holdingdisks");
435 ok($#$hdisklist == 1,
436     "no third holding disk");
437
438 is_deeply([ sort(+getconf_list("holdingdisk")) ],
439           [ sort('hd1', 'hd2') ],
440     "getconf_list lists all holdingdisks (in any order)");
441
442 skip "error loading config", 5 unless $cfg_result == $CFGERR_OK;
443 my $app = lookup_application("my_app");
444 ok($app, "found my_app");
445 is(application_name($app), "my_app",
446     "my_app knows its name");
447 is(application_getconf($app, $APPLICATION_COMMENT), 'my_app_comment',
448     "application comment");
449 is(application_getconf($app, $APPLICATION_PLUGIN), 'amgtar',
450     "application plugin (amgtar)");
451
452 is_deeply([ sort(+getconf_list("application-tool")) ],
453           [ sort("my_app") ],
454     "getconf_list lists all applications");
455 # test backward compatibility
456 is_deeply([ sort(+getconf_list("application")) ],
457           [ sort("my_app") ],
458     "getconf_list works for 'application-tool', too");
459
460 my $sc = lookup_pp_script("my_script");
461 ok($sc, "found my_script");
462 is(pp_script_name($sc), "my_script",
463     "my_script knows its name");
464 is(pp_script_getconf($sc, $PP_SCRIPT_COMMENT), 'my_script_comment',
465     "script comment");
466 is(pp_script_getconf($sc, $PP_SCRIPT_PLUGIN), 'script-email',
467     "script plugin (script-email)");
468 is(pp_script_getconf($sc, $PP_SCRIPT_EXECUTE_WHERE), $ES_CLIENT,
469     "script execute_where (client)");
470 is(pp_script_getconf($sc, $PP_SCRIPT_EXECUTE_ON),
471     $EXECUTE_ON_PRE_HOST_BACKUP|$EXECUTE_ON_POST_HOST_BACKUP,
472     "script execute_on");
473
474 is_deeply([ sort(+getconf_list("script")) ],
475           [ sort("my_script") ],
476     "getconf_list lists all script");
477
478 is_deeply([ sort(+getconf_list("script-tool")) ],
479           [ sort("my_script") ],
480     "getconf_list works for 'script-tool', too");
481
482 my $dc = lookup_device_config("my_device");
483 ok($dc, "found my_device");
484 is(device_config_name($dc), "my_device",
485     "my_device knows its name");
486 is(device_config_getconf($dc, $DEVICE_CONFIG_COMMENT), 'my device is mine, not yours',
487     "device comment");
488 is(device_config_getconf($dc, $DEVICE_CONFIG_TAPEDEV), 'tape:/dev/nst0',
489     "device tapedev");
490 # TODO do we really need all of this equipment for device properties?
491 is_deeply(device_config_getconf($dc, $DEVICE_CONFIG_DEVICE_PROPERTY),
492       { "block-size" => { 'priority' => 0, 'values' => ["128k"], 'append' => 0 },
493         "comment" => { 'priority' => 0, 'values' => ["what up?"], 'append' => 0 }, },
494     "device config proplist");
495
496 is_deeply([ sort(+getconf_list("device")) ],
497           [ sort("my_device") ],
498     "getconf_list lists all devices");
499
500 skip "error loading config", 7 unless $cfg_result == $CFGERR_OK;
501 $dc = lookup_changer_config("my_changer");
502 ok($dc, "found my_changer");
503 is(changer_config_name($dc), "my_changer",
504     "my_changer knows its name");
505 is(changer_config_getconf($dc, $CHANGER_CONFIG_COMMENT), 'my changer is mine, not yours',
506     "changer comment");
507 is(changer_config_getconf($dc, $CHANGER_CONFIG_CHANGERDEV), '/dev/sg0',
508     "changer tapedev");
509 is_deeply(changer_config_getconf($dc, $CHANGER_CONFIG_PROPERTY),
510     { 'testprop' => {
511             'priority' => 0,
512             'values' => [ 'testval' ],
513             'append' => 0,
514         }
515     }, "changer properties represented correctly");
516
517 is_deeply(changer_config_getconf($dc, $CHANGER_CONFIG_DEVICE_PROPERTY),
518     { 'testdprop' => {
519             'priority' => 0,
520             'values' => [ 'testdval' ],
521             'append' => 0,
522         }
523     }, "changer device properties represented correctly");
524
525 is_deeply([ sort(+getconf_list("changer")) ],
526           [ sort("my_changer") ],
527     "getconf_list lists all changers");
528
529 $dc = lookup_interactivity("my_interactivity");
530 ok($dc, "found my_interactivity");
531 is(interactivity_name($dc), "my_interactivity",
532     "my_interactivity knows its name");
533 is(interactivity_getconf($dc, $INTERACTIVITY_COMMENT), 'my interactivity is mine, not yours',
534     "interactivity comment");
535 is(interactivity_getconf($dc, $INTERACTIVITY_PLUGIN), 'MY-interactivity',
536     "interactivity plugin");
537 is_deeply(interactivity_getconf($dc, $INTERACTIVITY_PROPERTY),
538     { 'testprop' => {
539             'priority' => 0,
540             'values' => [ 'testval' ],
541             'append' => 0,
542         }
543     }, "interactivity properties represented correctly");
544
545 is_deeply([ sort(+getconf_list("interactivity")) ],
546           [ sort("my_interactivity") ],
547     "getconf_list lists all interactivity");
548
549 $dc = lookup_taperscan("my_taperscan");
550 ok($dc, "found my_taperscan");
551 is(taperscan_name($dc), "my_taperscan",
552     "my_taperscan knows its name");
553 is(taperscan_getconf($dc, $TAPERSCAN_COMMENT), 'my taperscan is mine, not yours',
554     "taperscan comment");
555 is(taperscan_getconf($dc, $TAPERSCAN_PLUGIN), 'MY-taperscan',
556     "taperscan plugin");
557 is_deeply(taperscan_getconf($dc, $TAPERSCAN_PROPERTY),
558     { 'testprop' => {
559             'priority' => 0,
560             'values' => [ 'testval' ],
561             'append' => 0,
562         }
563     }, "taperscan properties represented correctly");
564
565 is_deeply([ sort(+getconf_list("taperscan")) ],
566           [ sort("my_taperscan") ],
567     "getconf_list lists all taperscan");
568
569
570 ##
571 # Test config overwrites (using the config from above)
572
573 config_uninit();
574 $config_overrides = new_config_overrides(1); # note estimate is too small
575 add_config_override($config_overrides, "tapedev", "null:TEST");
576 add_config_override($config_overrides, "tpchanger", "chg-test");
577 add_config_override_opt($config_overrides, "org=KAOS");
578 set_config_overrides($config_overrides);
579 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
580
581 is(getconf($CNF_TAPEDEV), "null:TEST",
582     "config overwrites work with real config");
583 is(getconf($CNF_ORG), "KAOS",
584     "add_config_override_opt parsed correctly");
585
586 # introduce an error
587 config_uninit();
588 $config_overrides = new_config_overrides(1);
589 add_config_override($config_overrides, "bogusparam", "foo");
590 set_config_overrides($config_overrides);
591 config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
592
593 my ($error_level, @errors) = Amanda::Config::config_errors();
594 is($error_level, $CFGERR_ERRORS, "bogus config overwrite flagged as an error");
595
596 ##
597 # Test configuration dumping
598
599 # (uses the config from the previous section)
600
601 # fork a child and capture its stdout
602 my $pid = open(my $kid, "-|");
603 die "Can't fork: $!" unless defined($pid);
604 if (!$pid) {
605     Amanda::Config::dump_configuration();
606     exit 1;
607 }
608 my $dump_first_line = <$kid>;
609 my $dump = join'', $dump_first_line, <$kid>;
610 close $kid;
611 waitpid $pid, 0;
612
613 my $fn = Amanda::Config::get_config_filename();
614 my $dump_filename = $dump_first_line;
615 chomp $dump_filename;
616 $dump_filename =~ s/^# AMANDA CONFIGURATION FROM FILE "//g;
617 $dump_filename =~ s/":$//g;
618 is($dump_filename, $fn, 
619     "config filename is included correctly");
620
621 like($dump, qr/DEVICE-PROPERTY\s+"foo" "bar"\n/i,
622     "DEVICE-PROPERTY appears in dump output");
623
624 like($dump, qr/AMRECOVER-CHECK-LABEL\s+(yes|no)/i,
625     "AMRECOVER-CHECK-LABEL has a trailing space");
626
627 like($dump, qr/AMRECOVER-CHECK-LABEL\s+(yes|no)/i,
628     "AMRECOVER-CHECK-LABEL has a trailing space");
629
630 like($dump, qr/EXCLUDE\s+LIST "foo" "bar" "true" "star"/i,
631     "EXCLUDE LIST is in the dump");
632 like($dump, qr/EXCLUDE\s+FILE "foolist"/i,
633     "EXCLUDE FILE is in the dump");
634 like($dump, qr/INCLUDE\s+LIST OPTIONAL "bing" "ting" "string" "fling"/i,
635     "INCLUDE LIST is in the dump");
636 like($dump, qr/INCLUDE\s+FILE OPTIONAL "rhyme"/i,
637     "INCLUDE FILE is in the dump");
638 like($dump, qr/RECOVERY-LIMIT.*SAME-HOST/i,
639     "RECOVERY-LIST is in the dump");
640
641 ##
642 # Test nested definitions inside a dumptype
643
644 $testconf = Installcheck::Config->new();
645 $testconf->add_dumptype('nested_stuff', [
646     'comment' => '"contains a nested application, pp_script"',
647     'application' => '{
648         comment "my app"
649         plugin "amfun"
650 }',
651     'script' => '{
652         comment "my script"
653         plugin "ppfun"
654 }',
655 ]);
656
657 $testconf->write();
658
659 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
660 is($cfg_result, $CFGERR_OK, 
661     "parsing nested config loaded")
662     or diag_config_errors();
663 SKIP: {
664     skip "error loading config", 8 unless $cfg_result == $CFGERR_OK;
665
666     my $dtyp = lookup_dumptype("nested_stuff");
667     ok($dtyp, "found nested_stuff");
668
669     my $appname = dumptype_getconf($dtyp, $DUMPTYPE_APPLICATION);
670     like($appname, qr/^custom\(/,
671         "DUMPTYPE_APPLICATION is the generated name of an application subsection");
672
673     my $app = lookup_application($appname);
674     ok($app, ".. and that name leads to an application object");
675     is(application_getconf($app, $APPLICATION_COMMENT), "my app",
676         ".. that has the right comment");
677
678     my $sc = dumptype_getconf($dtyp, $DUMPTYPE_SCRIPTLIST);
679     ok(ref($sc) eq 'ARRAY' && @$sc == 1, "DUMPTYPE_SCRIPTLIST returns a 1-element list");
680     like($sc->[0], qr/^custom\(/,
681         ".. and the first element is the generated name of a script subsection");
682
683     $sc = lookup_pp_script($sc->[0]);
684     ok($sc, ".. and that name leads to a pp_script object");
685     is(pp_script_getconf($sc, $PP_SCRIPT_COMMENT), "my script",
686         ".. that has the right comment");
687 }
688
689 ##
690 # Explore a quirk of exinclude parsing.  Only the last
691 # exclude (or include) directive affects the 'optional' flag.
692 # We may want to change this, but we should do so intentionally.
693 # This is also tested by the 'amgetconf' installcheck.
694
695 $testconf = Installcheck::Config->new();
696 $testconf->add_dumptype('mydump-type', [
697     'exclude list' => '"foo" "bar"',
698     'exclude list optional append' => '"true" "star"',
699     'exclude list append' => '"true" "star"',
700 ]);
701 $testconf->write();
702
703 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
704 is($cfg_result, $CFGERR_OK, 
705     "first exinclude parsing config loaded")
706     or diag_config_errors();
707 SKIP: {
708     skip "error loading config", 2 unless $cfg_result == $CFGERR_OK;
709
710     my $dtyp = lookup_dumptype("mydump-type");
711     ok($dtyp, "found mydump-type");
712     is(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE)->{'optional'}, 0,
713         "'optional' has no effect when not on the last occurrence");
714 }
715
716 ##
717 # Check out recovery-limit parsing
718
719 $testconf = Installcheck::Config->new();
720 $testconf->add_param('recovery-limit', '"foo" "bar"');
721 $testconf->add_dumptype('rl1', [
722     'recovery-limit' => 'same-host server',
723 ]);
724 $testconf->add_dumptype('rl2', [
725     'recovery-limit' => '"somehost"',
726 ]);
727 $testconf->add_dumptype('rl3', [
728     'recovery-limit' => 'same-host server "somehost"',
729 ]);
730 $testconf->add_dumptype('rl4', [
731     'recovery-limit' => '"foohost" same-host',
732 ]);
733 $testconf->write();
734
735 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
736 is($cfg_result, $CFGERR_OK,
737     "recovery-limit config loaded")
738     or diag_config_errors();
739 SKIP: {
740     skip "error loading config", 5 unless $cfg_result == $CFGERR_OK;
741     my $dtyp;
742
743     is_deeply(getconf($CNF_RECOVERY_LIMIT),
744         [ 'foo', 'bar' ],
745         "global recovery-limit parameter");
746
747     $dtyp = lookup_dumptype("rl1");
748     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
749         [ "SAMEHOST-SAMEHOST-SAMEHOST", "SERVER-SERVER-SERVER"  ],
750         "same-host => undef in list");
751
752     $dtyp = lookup_dumptype("rl2");
753     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
754         [ "somehost" ],
755         "hostname => match pattern");
756
757     $dtyp = lookup_dumptype("rl3");
758     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
759         [ "SAMEHOST-SAMEHOST-SAMEHOST", "SERVER-SERVER-SERVER", "somehost" ],
760         "hostname and same-host parsed correctly");
761
762     $dtyp = lookup_dumptype("rl4");
763     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
764         [ "SAMEHOST-SAMEHOST-SAMEHOST", "foohost" ], # note that the order is an implementation detail
765         ".. even if same-host comes last");
766 }
767
768 ##
769 # Check out dump-limit parsing
770
771 $testconf = Installcheck::Config->new();
772 $testconf->add_dumptype('dl1', [
773     'dump-limit' => 'same-host',
774 ]);
775 $testconf->add_dumptype('dl2', [
776     'dump-limit' => 'server',
777 ]);
778 $testconf->add_dumptype('dl3', [
779     'dump-limit' => 'same-host server',
780 ]);
781 $testconf->write();
782
783 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
784 is($cfg_result, $CFGERR_OK,
785     "dump-limit config loaded")
786     or diag_config_errors();
787 SKIP: {
788     skip "error loading config", 5 unless $cfg_result == $CFGERR_OK;
789     my $dtyp;
790
791     $dtyp = lookup_dumptype("dl1");
792     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_DUMP_LIMIT),
793         [ "SAMEHOST-SAMEHOST-SAMEHOST" ],
794         "same-host => \"SAMEHOST-SAMEHOST-SAMEHOST\" in list");
795
796     $dtyp = lookup_dumptype("dl2");
797     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_DUMP_LIMIT),
798         [ "SERVER-SERVER-SERVER"  ],
799         "server => \"SERVER-SERVER-SERVER\" in list");
800
801     $dtyp = lookup_dumptype("dl3");
802     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_DUMP_LIMIT),
803         [ "SAMEHOST-SAMEHOST-SAMEHOST", "SERVER-SERVER-SERVER"  ],
804         "same-host and server");
805 }
806
807 $testconf->add_dumptype('dl4', [
808     'dump-limit' => 'same-host server "somehost"',
809 ]);
810 $testconf->write();
811 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
812 isnt($cfg_result, $CFGERR_OK,
813     "dump-limit do not accept hostname");
814
815 ##
816 # Try an autolabel with a template and 'any'
817
818 $testconf = Installcheck::Config->new();
819 $testconf->add_param('autolabel', '"FOO%%%BAR" any');
820 $testconf->write();
821
822 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
823 is($cfg_result, $CFGERR_OK, 
824     "first exinclude parsing config loaded")
825     or diag_config_errors();
826 SKIP: {
827     skip "error loading config", 1 unless $cfg_result == $CFGERR_OK;
828     is_deeply(getconf($CNF_AUTOLABEL),
829             { template => "FOO%%%BAR", other_config => 1,
830               non_amanda => 1, volume_error => 1, empty => 1 },
831             "'autolabel \"FOO%%%BAR\" any' represented correctly");
832 }
833
834 ##
835 # Check out where quoting is and is not required.
836
837 $testconf = Installcheck::Config->new();
838
839 # make sure an unquoted tapetype is OK
840 $testconf->add_param('tapetype', 'TEST-TAPE'); # unquoted (Installcheck::Config uses quoted)
841
842 # strings can optionally be quoted
843 $testconf->add_param('dumporder', '"STSTST"');
844
845 # enumerations (e.g., taperalgo) must not be quoted; implicitly tested above
846
847 # definitions
848 $testconf->add_dumptype('"parent"', [ # note quotes
849     'bumpsize' => '10240',
850 ]);
851 $testconf->add_dumptype('child', [
852     '' => '"parent"', # note quotes
853 ]);
854 $testconf->add_dumptype('child2', [
855     '' => 'parent',
856 ]);
857 $testconf->write();
858
859 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
860 is($cfg_result, $CFGERR_OK,
861     "parsed config to test strings vs. identifiers")
862     or diag_config_errors();
863 SKIP: {
864     skip "error loading config", 3 unless $cfg_result == $CFGERR_OK;
865
866     my $dtyp = lookup_dumptype("parent");
867     ok($dtyp, "found parent");
868     $dtyp = lookup_dumptype("child");
869     ok($dtyp, "found child");
870     is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), 10240,
871         "child dumptype correctly inherited bumpsize");
872 }
873
874 ##
875 # Explore a quirk of read_int_or_str parsing.
876
877 $testconf = Installcheck::Config->new();
878 $testconf->add_dumptype('mydump-type1', [
879     'client_port' => '12345',
880 ]);
881 $testconf->add_dumptype('mydump-type2', [
882     'client_port' => '"newamanda"',
883 ]);
884 $testconf->add_dumptype('mydump-type3', [
885     'client_port' => '"67890"',
886 ]);
887 $testconf->write();
888
889 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
890 is($cfg_result, $CFGERR_OK, 
891     "read_int_or_str parsing config loaded")
892     or diag_config_errors();
893 SKIP: {
894     skip "error loading config", 6 unless $cfg_result == $CFGERR_OK;
895
896     my $dtyp = lookup_dumptype("mydump-type1");
897     ok($dtyp, "found mydump-type1");
898     is(dumptype_getconf($dtyp, $DUMPTYPE_CLIENT_PORT), "12345",
899         "client_port set to 12345");
900
901     $dtyp = lookup_dumptype("mydump-type2");
902     ok($dtyp, "found mydump-type1");
903     is(dumptype_getconf($dtyp, $DUMPTYPE_CLIENT_PORT), "newamanda",
904         "client_port set to \"newamanda\"");
905
906     $dtyp = lookup_dumptype("mydump-type3");
907     ok($dtyp, "found mydump-type1");
908     is(dumptype_getconf($dtyp, $DUMPTYPE_CLIENT_PORT), "67890",
909         "client_port set to \"67890\"");
910 }
911
912 ##
913 # Check property inheritance
914
915 $testconf = Installcheck::Config->new();
916 $testconf->add_application('app1', [
917     'property' => '"prop1" "val1"'
918 ]);
919 $testconf->add_application('app2', [
920     'property' => 'append "prop2" "val2"'
921 ]);
922 $testconf->add_application('app3', [
923     'property' => '"prop3" "val3"'
924 ]);
925 $testconf->add_application('app1a', [
926     'property' => '"prop4" "val4"',
927     'property' => '"prop1" "val1a"',
928     'app1' => undef
929 ]);
930 $testconf->add_application('app2a', [
931     'property' => '"prop5" "val5"',
932     'property' => '"prop2" "val2a"',
933     'app2' => undef
934 ]);
935 $testconf->add_application('app3a', [
936     'property' => '"prop6" "val6"',
937     'app3' => undef,
938     'property' => '"prop7" "val7"'
939 ]);
940 $testconf->add_application('app1b', [
941     'property' => '"prop4" "val4"',
942     'property' => '"prop1" "val1a"',
943     'app1' => undef,
944     'property' => '"prop1" "val1b"',
945 ]);
946 $testconf->add_application('app2b', [
947     'property' => '"prop5" "val5"',
948     'property' => '"prop2" "val2a"',
949     'app2' => undef,
950     'property' => 'append "prop2" "val2b"',
951 ]);
952 $testconf->write();
953
954 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
955 is($cfg_result, $CFGERR_OK, 
956     "application properties inheritance")
957     or diag_config_errors();
958 SKIP: {
959     skip "error loading config", 15 unless $cfg_result == $CFGERR_OK;
960
961     my $app = lookup_application("app1a");
962     ok($app, "found app1a");
963     is(application_name($app), "app1a",
964         "app1a knows its name");
965     my $prop = application_getconf($app, $APPLICATION_PROPERTY);
966     is_deeply($prop, { "prop4" => { priority => 0,
967                                     append   => 0,
968                                     values => [ "val4" ]},
969                        "prop1" => { priority => 0,
970                                     append   => 0,
971                                     values => [ "val1" ] }},
972     "PROPERTY parameter of app1a parsed correctly");
973
974     $app = lookup_application("app2a");
975     ok($app, "found app2a");
976     is(application_name($app), "app2a",
977         "app2a knows its name");
978     $prop = application_getconf($app, $APPLICATION_PROPERTY);
979     is_deeply($prop, { "prop5" => { priority => 0,
980                                     append   => 0,
981                                     values => [ "val5" ]},
982                        "prop2" => { priority => 0,
983                                     append   => 0,
984                                     values => [ "val2a", "val2" ] }},
985     "PROPERTY parameter of app2a parsed correctly");
986
987     $app = lookup_application("app3a");
988     ok($app, "found app3a");
989     is(application_name($app), "app3a",
990         "app3a knows its name");
991     $prop = application_getconf($app, $APPLICATION_PROPERTY);
992     is_deeply($prop, { "prop3" => { priority => 0,
993                                     append   => 0,
994                                     values => [ "val3" ]},
995                        "prop6" => { priority => 0,
996                                     append   => 0,
997                                     values => [ "val6" ] },
998                        "prop7" => { priority => 0,
999                                     append   => 0,
1000                                     values => [ "val7" ] }},
1001     "PROPERTY parameter of app3a parsed correctly");
1002
1003     $app = lookup_application("app1b");
1004     ok($app, "found app1b");
1005     is(application_name($app), "app1b",
1006         "app1b knows its name");
1007     $prop = application_getconf($app, $APPLICATION_PROPERTY);
1008     is_deeply($prop, { "prop4" => { priority => 0,
1009                                     append   => 0,
1010                                     values => [ "val4" ]},
1011                        "prop1" => { priority => 0,
1012                                     append   => 0,
1013                                     values => [ "val1b" ] }},
1014     "PROPERTY parameter of app1b parsed correctly");
1015
1016     $app = lookup_application("app2b");
1017     ok($app, "found app2b");
1018     is(application_name($app), "app2b",
1019         "app2b knows its name");
1020     $prop = application_getconf($app, $APPLICATION_PROPERTY);
1021     is_deeply($prop, { "prop5" => { priority => 0,
1022                                     append   => 0,
1023                                     values => [ "val5" ]},
1024                        "prop2" => { priority => 0,
1025                                     append   => 1,
1026                                     values => [ "val2a", "val2", "val2b" ] }},
1027     "PROPERTY parameter of app2b parsed correctly");
1028 }
1029
1030
1031 ##
1032 # Check getconf_byname and getconf_byname_strs
1033
1034 $testconf = Installcheck::Config->new();
1035 $testconf->add_param('tapedev', '"thats a funny name"');
1036 $testconf->add_application('app1', [
1037     'comment' => '"one"',
1038 ]);
1039 $testconf->add_script('scr1', [
1040     'comment' => '"one"',
1041 ]);
1042 # check old names, too
1043 $testconf->add_text(<<EOF);
1044 define application-tool "app2" {
1045     comment "two"
1046 }
1047 EOF
1048 $testconf->add_text(<<EOF);
1049 define script-tool "scr2" {
1050     comment "two"
1051 }
1052 EOF
1053 $testconf->write();
1054
1055 $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
1056 is($cfg_result, $CFGERR_OK,
1057     "getconf_byname")
1058     or diag_config_errors();
1059 SKIP: {
1060     skip "error loading config", 7 unless $cfg_result == $CFGERR_OK;
1061
1062     is(getconf_byname("Tapedev"), "thats a funny name",
1063         "getconf_byname for global param");
1064     is_deeply([ getconf_byname_strs("Tapedev", 1) ],
1065         [ "\"thats a funny name\"" ],
1066         "getconf_byname_strs for global param with quotes");
1067     is_deeply([ getconf_byname_strs("Tapedev", 0) ],
1068         [ "thats a funny name" ],
1069         "getconf_byname_strs for global param without quotes");
1070
1071     # test * and *-tool (the old name)
1072     is(getconf_byname("application-tool:app1:comment"), "one",
1073         "getconf_byname for appplication-tool param");
1074     is(getconf_byname("application:app2:comment"), "two",
1075         "getconf_byname for application param");
1076     is(getconf_byname("script-tool:scr1:comment"), "one",
1077         "getconf_byname for appplication-tool param");
1078     is(getconf_byname("script:scr2:comment"), "two",
1079         "getconf_byname for script param");
1080 }
1081
1082 my @boolean_vals = (
1083     {'val' => '1', 'expected' => 1},
1084     {'val' => '0', 'expected' => 0},
1085     {'val' => 't', 'expected' => 1},
1086     {'val' => 'true', 'expected' => 1},
1087     {'val' => 'f', 'expected' => 0},
1088     {'val' => 'false', 'expected' => 0},
1089     {'val' => 'y', 'expected' => 1},
1090     {'val' => 'yes', 'expected' => 1},
1091     {'val' => 'n', 'expected' => 0},
1092     {'val' => 'no', 'expected' => 0},
1093     {'val' => 'on', 'expected' => 1},
1094     {'val' => 'off', 'expected' => 0},
1095     {'val' => 'oFf', 'expected' => 0},
1096     {'val' => 'foo', 'expected' => undef},
1097     );
1098
1099 for my $bv (@boolean_vals) {
1100     is(string_to_boolean($bv->{'val'}), $bv->{'expected'},
1101         "string_to_boolean('$bv->{'val'}') is right");
1102 }
1103
1104 my @prop_names = (
1105     {'val' => '', 'expected' => ''},
1106     {'val' => 'prop-name', 'expected' => 'prop-name'},
1107     {'val' => 'PRoP-NaME', 'expected' => 'prop-name'},
1108     {'val' => 'prop_name', 'expected' => 'prop-name'},
1109     {'val' => 'FaNCy_ProP', 'expected' => 'fancy-prop'},
1110     {'val' => '_under_', 'expected' => '-under-'},
1111     {'val' => '-dash-', 'expected' => '-dash-'},
1112     {'val' => '-', 'expected' => '-'},
1113     {'val' => '_', 'expected' => '-'},
1114     );
1115
1116 for my $pn (@prop_names) {
1117     is(amandaify_property_name($pn->{'val'}), $pn->{'expected'},
1118        "amandaify_property_name('$pn->{'val'}') is right");
1119 }
1120
1121 $testconf = Installcheck::Config->new();
1122 $testconf->add_param('property', '"PrOP_nAme" "VALUE"');
1123 $testconf->write();
1124 config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
1125 my $properties = getconf($CNF_PROPERTY);
1126
1127 @prop_names = (
1128     {'val' => 'prop-name'},
1129     {'val' => 'PRoP-NaME'},
1130     {'val' => 'prop_name'},
1131     {'val' => 'PROP_NAME'},
1132     {'val' => 'PRoP-NaME'},
1133     {'val' => 'prop_name'},
1134     );
1135
1136 for my $pn (@prop_names) {
1137     is_deeply($properties->{$pn->{'val'}}->{values}, [ "VALUE" ]);
1138 }
1139
1140 $testconf = Installcheck::Config->new();
1141 $testconf->add_client_config_param('amdump-server', '"amdump.localhost"');
1142 $testconf->add_client_config_param('index-server', '"index.localhost"');
1143 $testconf->add_client_config_param('tape-server', '"tape.localhost"');
1144 $testconf->write();
1145 config_init($CONFIG_INIT_CLIENT | $CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
1146 my $amdump_server = getconf($CNF_AMDUMP_SERVER);
1147 is ($amdump_server, "amdump.localhost", "amdump-server is \"amdump.localhost\"");
1148 my $index_server = getconf($CNF_INDEX_SERVER);
1149 is ($index_server, "index.localhost", "index-server is \"index.localhost\"");
1150 my $tape_server = getconf($CNF_TAPE_SERVER);
1151 is ($tape_server, "tape.localhost", "amdump is \"tape.localhost\"");
1152