Imported Upstream version 2.6.0p2
[debian/amanda] / installcheck / Amanda_Config.pl
1 # Copyright (c) 2006 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, 505 N Mathlida Ave, Suite 120
17 # Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
18
19 use Test::More qw(no_plan);
20 use Amconfig;
21 use strict;
22
23 use lib "@amperldir@";
24 use Amanda::Paths;
25 use Amanda::Config qw( :init :getconf );
26
27 my $testconf;
28
29 ##
30 # Try starting with no configuration at all
31 ok(config_init(0, ''), "Initialize with no configuration");
32
33 ##
34 # Parse up a basic configuration
35
36 # invent "large" values for CONFTYPE_AM64 and CONFTYPE_SIZE
37 my $am64_num = '171801575472'; # 0xA000B000C000 / 1024
38 my $size_t_num = '2147483647'; # 0x7fffffff
39
40 $testconf = Amconfig->new();
41 $testconf->add_param('reserve', '75');
42 $testconf->add_param('autoflush', 'yes');
43 $testconf->add_param('tapedev', '"/dev/foo"');
44 $testconf->add_param('bumpsize', $am64_num);
45 $testconf->add_param('bumpmult', '1.4');
46 $testconf->add_param('reserved-udp-port', '100,200');
47 $testconf->add_param('device_output_buffer_size', $size_t_num);
48 $testconf->add_param('taperalgo', 'last');
49 $testconf->add_param('device_property', '"foo" "bar"');
50 $testconf->add_param('device_property', '"blue" "car"');
51 $testconf->add_param('displayunit', '"m"');
52 $testconf->add_param('debug_auth', '1');
53 $testconf->add_tapetype('mytapetype', [
54     'comment' => '"mine"',
55     'length' => '128 M',
56 ]);
57 $testconf->add_dumptype('mydumptype', [
58     'comment' => '"mine"',
59     'priority' => 'high',  # == 2
60     'bumpsize' => $am64_num,
61     'bumpmult' => 1.75,
62     'starttime' => 1829,
63     'holdingdisk' => 'required',
64     'compress' => 'client best',
65     'encrypt' => 'server',
66     'strategy' => 'incronly',
67     'comprate' => '0.25,0.75',
68     'exclude list' => '"foo" "bar"',
69     'exclude list append' => '"true" "star"',
70     'exclude file' => '"foolist"',
71     'include list' => '"bing" "ting"',
72     'include list append' => '"string" "fling"',
73     'include file optional' => '"rhyme"',
74 ]);
75 $testconf->add_interface('inyoface', [
76     'comment' => '"mine"',
77     'use' => '100',
78 ]);
79 $testconf->add_interface('inherface', [
80     'comment' => '"empty"',
81 ]);
82 $testconf->add_holdingdisk('hd1', [
83     'comment' => '"mine"',
84     'directory' => '"/mnt/hd1"',
85     'use' => '100M',
86     'chunksize' => '1024k',
87 ]);
88 $testconf->add_holdingdisk('hd2', [
89     'comment' => '"empty"',
90 ]);
91 $testconf->write();
92
93 my $cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF');
94 ok($cfg_ok, "Load test configuration");
95
96 SKIP: {
97     skip "error loading config", unless $cfg_ok;
98
99     is(Amanda::Config::get_config_name(), "TESTCONF", 
100         "config_name set");
101     is(Amanda::Config::get_config_dir(), "$CONFIG_DIR/TESTCONF", 
102         "config_dir set");
103     is(Amanda::Config::get_config_filename(),
104         "$CONFIG_DIR/TESTCONF/amanda.conf", 
105         "config_filename set");
106 }
107
108 SKIP: { # global parameters
109     skip "error loading config", unless $cfg_ok;
110
111     is(getconf($CNF_RESERVE), 75,
112         "integer global confparm");
113     is(getconf($CNF_BUMPSIZE), $am64_num+0,
114         "am64 global confparm");
115     is(getconf($CNF_TAPEDEV), "/dev/foo",
116         "string global confparm");
117     is(getconf($CNF_DEVICE_OUTPUT_BUFFER_SIZE), $size_t_num+0,
118         "size global confparm");
119     ok(getconf($CNF_AUTOFLUSH),
120         "boolean global confparm");
121     is(getconf($CNF_TAPERALGO), $Amanda::Config::ALGO_LAST,
122         "taperalgo global confparam");
123     is_deeply([getconf($CNF_RESERVED_UDP_PORT)], [100,200],
124         "intrange global confparm");
125     is(getconf($CNF_DISPLAYUNIT), "M",
126         "displayunit is correctly uppercased");
127     is_deeply(getconf($CNF_DEVICE_PROPERTY),
128               { "foo" => "bar", "blue" => "car" },
129             "proplist global confparm");
130
131     ok(getconf_seen($CNF_TAPEDEV),
132         "'tapedev' parm was seen");
133     ok(!getconf_seen($CNF_NETUSAGE),
134         "'netusage' parm was not seen");
135 }
136
137 SKIP: { # derived values
138     skip "error loading config", unless $cfg_ok;
139
140     is(Amanda::Config::getconf_unit_divisor(), 1024, 
141         "correct unit divisor (from displayunit -> KB)");
142     ok($Amanda::Config::debug_auth, 
143         "debug_auth setting reflected in global variable");
144     ok(!$Amanda::Config::debug_amandad, 
145         "debug_amandad defaults to false");
146 }
147
148 SKIP: { # tapetypes
149     skip "error loading config", unless $cfg_ok;
150     my $ttyp = lookup_tapetype("mytapetype");
151     ok($ttyp, "found mytapetype");
152     is(tapetype_getconf($ttyp, $TAPETYPE_COMMENT), 'mine', 
153         "tapetype comment");
154     is(tapetype_getconf($ttyp, $TAPETYPE_LENGTH), 128 * 1024, 
155         "tapetype comment");
156
157     ok(tapetype_seen($ttyp, $TAPETYPE_COMMENT),
158         "tapetype comment was seen");
159     ok(!tapetype_seen($ttyp, $TAPETYPE_LBL_TEMPL),
160         "tapetype lbl_templ was not seen");
161
162     is_deeply([ sort(+getconf_list("tapetype")) ],
163               [ sort("mytapetype", "TEST-TAPE") ],
164         "getconf_list lists all tapetypes");
165 }
166
167 SKIP: { # dumptypes
168     skip "error loading config", unless $cfg_ok;
169
170     my $dtyp = lookup_dumptype("mydumptype");
171     ok($dtyp, "found mydumptype");
172     is(dumptype_getconf($dtyp, $DUMPTYPE_COMMENT), 'mine', 
173         "dumptype string");
174     is(dumptype_getconf($dtyp, $DUMPTYPE_PRIORITY), 2, 
175         "dumptype priority");
176     is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), $am64_num+0,
177         "dumptype size");
178     is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPMULT), 1.75,
179         "dumptype real");
180     is(dumptype_getconf($dtyp, $DUMPTYPE_STARTTIME), 1829,
181         "dumptype time");
182     is(dumptype_getconf($dtyp, $DUMPTYPE_HOLDINGDISK), $HOLD_REQUIRED,
183         "dumptype holdingdisk");
184     is(dumptype_getconf($dtyp, $DUMPTYPE_COMPRESS), $COMP_BEST,
185         "dumptype compress");
186     is(dumptype_getconf($dtyp, $DUMPTYPE_ENCRYPT), $ENCRYPT_SERV_CUST,
187         "dumptype encrypt");
188     is(dumptype_getconf($dtyp, $DUMPTYPE_STRATEGY), $DS_INCRONLY,
189         "dumptype strategy");
190     is_deeply([dumptype_getconf($dtyp, $DUMPTYPE_COMPRATE)], [0.25, 0.75],
191         "dumptype comprate");
192     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_INCLUDE),
193         { 'file' => [ 'rhyme' ],
194           'list' => [ 'bing', 'ting', 'string', 'fling' ],
195           'optional' => 1 },
196         "dumptype include list");
197     is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE),
198         { 'file' => [ 'foolist' ],
199           'list' => [ 'foo', 'bar', 'true', 'star' ],
200           'optional' => 0 },
201         "dumptype exclude list");
202
203     ok(dumptype_seen($dtyp, $DUMPTYPE_EXCLUDE),
204         "'exclude' parm was seen");
205     ok(!dumptype_seen($dtyp, $DUMPTYPE_RECORD),
206         "'record' parm was not seen");
207
208     is_deeply([ sort(+getconf_list("dumptype")) ],
209               [ sort(qw(
210                 mydumptype
211                 NO-COMPRESS COMPRESS-FAST COMPRESS-BEST COMPRESS-CUST
212                 SRVCOMPRESS BSD-AUTH KRB4-AUTH NO-RECORD NO-HOLD
213                 NO-FULL
214                 )) ],
215         "getconf_list lists all dumptypes (including defaults)");
216 }
217
218 SKIP: { # interfaces
219     skip "error loading config" unless $cfg_ok;
220     my $iface = lookup_interface("inyoface");
221     ok($iface, "found inyoface");
222     is(interface_name($iface), "inyoface",
223         "interface knows its name");
224     is(interface_getconf($iface, $INTER_COMMENT), 'mine', 
225         "interface comment");
226     is(interface_getconf($iface, $INTER_MAXUSAGE), 100, 
227         "interface maxusage");
228
229     $iface = lookup_interface("inherface");
230     ok($iface, "found inherface");
231     ok(interface_seen($iface, $INTER_COMMENT),
232         "seen set for parameters that appeared");
233     ok(!interface_seen($iface, $INTER_MAXUSAGE),
234         "seen not set for parameters that did not appear");
235
236     is_deeply([ sort(+getconf_list("interface")) ],
237               [ sort('inyoface', 'inherface', 'default') ],
238         "getconf_list lists all interfaces (in any order)");
239 }
240
241 SKIP: { # holdingdisks
242     skip "error loading config" unless $cfg_ok;
243     my $hdisk = lookup_holdingdisk("hd1");
244     ok($hdisk, "found hd1");
245     is(holdingdisk_name($hdisk), "hd1",
246         "hd1 knows its name");
247     is(holdingdisk_getconf($hdisk, $HOLDING_COMMENT), 'mine', 
248         "holdingdisk comment");
249     is(holdingdisk_getconf($hdisk, $HOLDING_DISKDIR), '/mnt/hd1',
250         "holdingdisk diskdir (directory)");
251     is(holdingdisk_getconf($hdisk, $HOLDING_DISKSIZE), 100*1024, 
252         "holdingdisk disksize (use)");
253     is(holdingdisk_getconf($hdisk, $HOLDING_CHUNKSIZE), 1024, 
254         "holdingdisk chunksize");
255
256     $hdisk = lookup_holdingdisk("hd2");
257     ok($hdisk, "found hd2");
258     ok(holdingdisk_seen($hdisk, $HOLDING_COMMENT),
259         "seen set for parameters that appeared");
260     ok(!holdingdisk_seen($hdisk, $HOLDING_CHUNKSIZE),
261         "seen not set for parameters that did not appear");
262
263     # only holdingdisks have this linked-list structure
264     # exposed
265     $hdisk = getconf_holdingdisks();
266     like(holdingdisk_name($hdisk), qr/hd[12]/,
267         "one disk is first in list of holdingdisks");
268     $hdisk = holdingdisk_next($hdisk);
269     like(holdingdisk_name($hdisk), qr/hd[12]/,
270         "another is second in list of holdingdisks");
271     ok(!holdingdisk_next($hdisk),
272         "no third holding disk");
273
274     is_deeply([ sort(+getconf_list("holdingdisk")) ],
275               [ sort('hd1', 'hd2') ],
276         "getconf_list lists all holdingdisks (in any order)");
277 }
278
279 ##
280 # Test configuration dumping
281
282 # (uses the config from the previous section)
283
284 # fork a child and capture its stdout
285 my $pid = open(my $kid, "-|");
286 die "Can't fork: $!" unless defined($pid);
287 if (!$pid) {
288     Amanda::Config::dump_configuration();
289     exit 1;
290 }
291 my $dump = join'', <$kid>;
292 close $kid;
293
294 my $fn = Amanda::Config::get_config_filename();
295 like($dump, qr/AMANDA CONFIGURATION FROM FILE "$fn"/,
296     "config filename is included correctly");
297
298 like($dump, qr/DEVICE_PROPERTY\s+"foo" "bar"\n/i,
299     "DEVICE_PROPERTY appears in dump output");
300
301 like($dump, qr/AMRECOVER_CHECK_LABEL\s+(yes|no)/i,
302     "AMRECOVER_CHECK_LABEL has a trailing space");
303
304 like($dump, qr/AMRECOVER_CHECK_LABEL\s+(yes|no)/i,
305     "AMRECOVER_CHECK_LABEL has a trailing space");
306
307 like($dump, qr/EXCLUDE\s+LIST "foo" "bar" "true" "star"/i,
308     "EXCLUDE LIST is in the dump");
309 like($dump, qr/EXCLUDE\s+FILE "foolist"/i,
310     "EXCLUDE FILE is in the dump");
311 like($dump, qr/INCLUDE\s+LIST OPTIONAL "bing" "ting" "string" "fling"/i,
312     "INCLUDE LIST is in the dump");
313 like($dump, qr/INCLUDE\s+FILE OPTIONAL "rhyme"/i,
314     "INCLUDE FILE is in the dump");
315
316 ##
317 # Explore a quirk of exinclude parsing.  Only the last
318 # exclude (or include) directive affects the 'optional' flag.
319 # We may want to change this, but we should do so intentionally.
320 # This is also tested by the 'amgetconf' installcheck.
321
322 $testconf = Amconfig->new();
323 $testconf->add_dumptype('mydumptype', [
324     'exclude list' => '"foo" "bar"',
325     'exclude list optional append' => '"true" "star"',
326     'exclude list append' => '"true" "star"',
327 ]);
328 $testconf->write();
329
330 $cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
331 SKIP: {
332     skip "error loading config", unless $cfg_ok;
333
334     my $dtyp = lookup_dumptype("mydumptype");
335     ok($dtyp, "found mydumptype");
336     is(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE)->{'optional'}, 0,
337         "'optional' has no effect when not on the last occurrence");
338 }
339
340 $testconf = Amconfig->new();
341 $testconf->add_dumptype('mydumptype', [
342     'exclude file' => '"foo" "bar"',
343     'exclude file optional append' => '"true" "star"',
344     'exclude list append' => '"true" "star"',
345 ]);
346 $testconf->write();
347
348 $cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
349 SKIP: {
350     skip "error loading config", unless $cfg_ok;
351
352     my $dtyp = lookup_dumptype("mydumptype");
353     ok($dtyp, "found mydumptype");
354     is(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE)->{'optional'}, 0,
355         "'optional' has no effect when not on the last occurrence of 'file'");
356 }
357
358 # TODO:
359 # overwrites
360 # inheritance
361 # more init