Imported Upstream version 3.3.3
[debian/amanda] / installcheck / amgetconf.pl
1 # Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 # for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19
20 use Test::More tests => 86;
21 use strict;
22 use warnings;
23
24 use lib "@amperldir@";
25 use Installcheck;
26 use Installcheck::Config;
27 use Installcheck::Run qw(run run_get run_err);
28 use Amanda::Paths;
29 use Cwd;
30
31 # this is re-created for each test
32 my $testconf;
33
34 ##
35 # First, try amgetconf out without a config
36
37 ok(!run('amgetconf'), "bare amgetconf fails");
38 like($Installcheck::Run::stdout, qr(\AUsage: )i, 
39     ".. and gives usage message on stdout");
40 like(run_err('amgetconf', 'this-probably-doesnt-exist', 'tapedev'),
41     qr(could not open conf file)i, 
42     "error message when configuration parameter doesn't exist");
43
44 ##
45 # Next, work against a basically empty config
46
47 $testconf = Installcheck::Config->new();
48 $testconf->write();
49
50 # test some defaults
51 is(run_get('amgetconf', 'TESTCONF', "reserve"), "100", 
52     "reserve defaults to 100");
53 is(run_get('amgetconf', 'TESTCONF', "tapelist"), "tapelist", 
54     "tapelist defaults to 'tapelist'");
55 is(run_get('amgetconf', 'TESTCONF', "usetimestamps"), "yes", 
56     "usetimestamps defaults to 'yes'");
57 is(run_get('amgetconf', 'TESTCONF', "send_amreport_on"), "ALL",
58     "send_amreport_on defaults to 'ALL'"); # (enum value is 0)
59 is(run_get('amgetconf', 'TESTCONF', "taperalgo"), "FIRST",
60     "taperalgo defaults to 'ALL'"); # (enum value is 0)
61 is(run_get('amgetconf', 'TESTCONF', "printer"), "",
62     "printer defaults to empty string, which is not an error");
63
64 # test command-line parsing
65 is(run_get('amgetconf', 'TESTCONF', '--execute-where', 'client', 'amandates'),
66    $Amanda::Constants::DEFAULT_AMANDATES_FILE,
67     "--execute-where client");
68 is(run_get('amgetconf', 'TESTCONF', '--execute-where=client', 'amandates'),
69    $Amanda::Constants::DEFAULT_AMANDATES_FILE,
70     "--execute-where=client");
71 is(run_get('amgetconf', 'TESTCONF', '--client', 'amandates'),
72    $Amanda::Constants::DEFAULT_AMANDATES_FILE,
73     "--client");
74
75 is(run_get('amgetconf', 'TESTCONF', '--execute-where', 'server', 'reserve'), "100",
76     "--execute-where server");
77 is(run_get('amgetconf', 'TESTCONF', '--execute-where=server', 'reserve'), "100",
78     "--execute-where=server");
79 is(run_get('amgetconf', 'TESTCONF', '--execute-where=server', '--execute-where=server', 'reserve'), "100",
80     "--execute-where=server --execute-where=server");
81 is(run_get('amgetconf', 'TESTCONF', '--execute-where=client', '--execute-where=client', 'amandates'),
82    $Amanda::Constants::DEFAULT_AMANDATES_FILE,
83     "--execute-where=client --execute-where=client");
84
85 like(run_err('amgetconf', 'TESTCONF', '--execute-where=server', '--execute-where=client'),
86     qr/conflicts with/,
87     "handles conflict --execute-where=server --execute-where=client");
88 like(run_err('amgetconf', 'TESTCONF', '--execute-where=client', '--execute-where=server'),
89     qr/conflicts with/,
90     "handles conflict --execute-where=client --execute-where=server");
91 like(run_err('amgetconf', 'TESTCONF', '--execute-where=server', '--client'),
92      qr/conflicts with/,
93     "handles conflict --execute-where=server --client");
94 like(run_err('amgetconf', 'TESTCONF', '--client', '--execute-where=server'),
95     qr/conflicts with/, 
96     "handles conflict --client --execute-where=server");
97
98 is(run_get('amgetconf', 'TESTCONF', '-o', 'reserve=50', 'reserve'), "50",
99     "-o reserve=50");
100 is(run_get('amgetconf', 'TESTCONF', '-oreserve=50', 'reserve'), "50",
101     "-oreserve=50");
102 is(run_get('amgetconf', '-o', 'reserve=50', 'TESTCONF', 'reserve'), "50",
103     "-oreserve=50 before config name");
104 is(run_get('amgetconf', 'TESTCONF', 'reserve', 'a', 'table', 'for', 'two', '-o', 'reserve=50'), "50",
105     "extra command-line arguments are ignored");
106
107 # test a nonexistent parameter
108 like(run_err('amgetconf', 'TESTCONF', "foos_per_bar"), qr/no such parameter/, 
109     "handles nonexistent parameters as an error");
110 like(run_err('amgetconf', 'TESTCONF', "build.foos_per_bar"), qr/no such parameter/, 
111     "handles nonexistent build parameters as an error");
112
113 # Test build parameters that we can determine easily.  Testing all parameters
114 # would be more of a maintenance bother than a help.
115 is(run_get('amgetconf', 'TESTCONF', "build.bindir"), $bindir,
116     "build.bindir is correct");
117 is(run_get('amgetconf', 'TESTCONF', "build.sbindir"), $sbindir,
118     "build.sbindir is correct");
119 is(run_get('amgetconf', 'TESTCONF', "build.libexecdir"), $libexecdir,
120     "build.libexecdir is correct");
121 is(run_get('amgetconf', 'TESTCONF', "build.amlibexecdir"), $amlibexecdir,
122     "build.amlibexecdir is correct");
123 is(run_get('amgetconf', 'TESTCONF', "build.mandir"), $mandir,
124     "build.mandir is correct");
125 is(run_get('amgetconf', 'TESTCONF', "build.AMANDA_DBGDIR"), $AMANDA_DBGDIR,
126     "build.AMANDA_DBGDIR is correct");
127 is(run_get('amgetconf', 'TESTCONF', "build.AMANDA_TMPDIR"), $AMANDA_TMPDIR,
128     "build.AMDNA_TMPDIR is correct");
129 is(run_get('amgetconf', 'TESTCONF', "build.CONFIG_DIR"), $CONFIG_DIR,
130     "build.CONFIG_DIR is correct");
131 is(run_get('amgetconf', 'TESTCONF', "build.__empty"), "",
132     "empty build variables handled correctly");
133
134 like(run_err('amgetconf', 'TESTCONF', "build.bogus-param"), qr(no such parameter),
135     "bogus build parameters result in an error");
136
137 is(run_get('amgetconf', 'TESTCONF', "build.config_dir"), $CONFIG_DIR, 
138     "build parameters are case-insensitive");
139
140 is(run_get('amgetconf', "build.bindir"), $bindir, "build variables are available without a config");
141
142 # empty --list should return nothing
143 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'holdingdisk')))], [ ],
144         "--list returns an empty list when there's nothing to return");
145
146 # dbopen, dbclose
147 my $dbfile = run_get('amgetconf', 'TESTCONF', "dbopen.foo");
148 chomp $dbfile;
149 like($dbfile, qr(^\Q$AMANDA_DBGDIR\E/server/foo.[0-9]*.debug$),
150     "'amgetconf dbopen.foo' returns a proper debug filename");
151 SKIP: {
152     skip "dbopen didn't work, so I'll skip the rest", 3
153         unless (-f $dbfile);
154     ok(!run('amgetconf', 'TESTCONF', "dbclose.foo"),
155         "dbclose without filename fails");
156     is(run_get('amgetconf', 'TESTCONF', "dbclose.foo:$dbfile"), $dbfile, 
157         "'amgetconf dbclose.foo:<filename>' returns the debug filename");
158
159     # sometimes shell scripts pass a full path as appname..
160     $dbfile = run_get('amgetconf', 'TESTCONF', 'dbopen./sbin/foo');
161     like($dbfile, qr(^\Q$AMANDA_DBGDIR\E/server/_sbin_foo.[0-9]*.debug$),
162         "'amgetconf dbopen./sbin/foo' doesn't get confused by the slashes");
163 }
164
165 ##
166 # Test an invalid config file
167
168 $testconf = Installcheck::Config->new();
169 $testconf->add_param("foos_per_bar", "10");
170 $testconf->write();
171
172 like(run_err('amgetconf', 'TESTCONF', "foos_per_bar"), qr/errors processing config file/, 
173     "gives error on invalid configuration");
174
175 ##
176 # Now let's fill in some interesting values
177
178 $testconf = Installcheck::Config->new();
179 $testconf->add_param("reserved-udp-port", '100,200');
180 $testconf->add_param("printer", '"/dev/lp"');
181 $testconf->add_param("reserve", '27');
182 $testconf->write();
183
184 is(run_get('amgetconf', 'TESTCONF', "reserved-udp-port"), "100,200", 
185     "correctly returns intrange parameters from the file");
186 is(run_get('amgetconf', 'TESTCONF', "printer"), "/dev/lp", 
187     "correctly returns string parameters from the file");
188 is(run_get('amgetconf', 'TESTCONF', "reserve"), "27", 
189     "correctly returns integer parameters from the file");
190 is(run_get('amgetconf', 'TESTCONF', "rEsErVe"), "27", 
191     "is case-insensitive");
192 is(run_get('amgetconf', 'TESTCONF', "reserved_udp_port"), "100,200", 
193     "treats _ and - identically");
194
195 # check runs without a config
196 my $olddir = getcwd();
197 chdir("$CONFIG_DIR/TESTCONF") or die("Could not 'cd' to TESTCONF directory");
198 is(run_get('amgetconf', "printer"), "/dev/lp", 
199     "uses current directory when no configuration name is given");
200 chdir($olddir) or die("Could not 'cd' back to my original directory");
201
202 ##
203 # device_property can appear multiple times
204
205 $testconf = Installcheck::Config->new();
206 $testconf->add_param("device_property", '"power" "on"');
207 $testconf->add_param("device_property", '"turbo" "engaged"');
208 $testconf->write();
209
210 is_deeply([sort(+split(qr/\n/, run_get('amgetconf', 'TESTCONF', 'device_property')))],
211           [sort('"power" "on"', '"turbo" "engaged"')],
212     "device_property can have multiple values");
213
214 ##
215 # Subsections
216
217 $testconf = Installcheck::Config->new();
218 $testconf->add_tapetype("cassette", [ length => "32 k" ]);
219 $testconf->add_tapetype("reel2reel", [ length => "1 M" ]);
220 $testconf->add_tapetype("scotch", [ length => "512000 bytes" ]);
221 $testconf->add_dumptype("testdump", [ comment => '"testdump-dumptype"',
222                                       auth => '"bsd"' ]);
223 $testconf->add_dumptype("testdump1", [ inherit => 'testdump' ]);
224 $testconf->add_interface("testiface", [ use => '10' ]);
225 $testconf->add_holdingdisk("hd17", [ chunksize => '128' ]);
226 $testconf->add_application('app_amgtar', [ plugin => '"amgtar"' ]);
227 $testconf->add_application('app_amstar', [ plugin => '"amstar"' ]);
228 $testconf->add_script('my_script', [ "execute-on" => 'pre-dle-amcheck', 'plugin' => '"foo"' ]);
229 $testconf->add_device('my_device', [ "tapedev" => '"foo:/bar"' ]);
230 $testconf->write();
231
232 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'tapetype')))],
233           [sort("cassette", "reel2reel", "scotch", "TEST-TAPE")],
234         "--list returns correct set of tapetypes");
235 is(run_get('amgetconf', 'TESTCONF', 'tapetype:scotch:length'), '500', 
236     "returns tapetype parameter correctly");
237
238 ok(scalar(grep { $_ eq 'testdump' } 
239         split(/\n/, 
240             run_get('amgetconf', 'TESTCONF', '--list', 'dumptype'))),
241         "--list returns a test dumptype among the default dumptypes");
242 is(run_get('amgetconf', 'TESTCONF', 'dumptype:testdump:comment'), 'testdump-dumptype', 
243     "returns dumptype parameter correctly");
244
245 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'interface')))], 
246           [sort("testiface", "default")],
247         "--list returns correct set of interfaces");
248 is(run_get('amgetconf', 'TESTCONF', 'interface:testiface:use'), '10', 
249     "returns interface parameter correctly");
250
251 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'holdingdisk')))], 
252           [sort("hd17")], 
253         "--list returns correct set of holdingdisks");
254 is(run_get('amgetconf', 'TESTCONF', 'holdingdisk:hd17:chunksize'), '128',
255     "returns holdingdisk parameter correctly");
256
257 like(run_get('amgetconf', 'TESTCONF', '--list', 'build'), qr(.*version.*),
258         "'--list build' lists build variables");
259
260 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'application')))],
261           [sort("app_amgtar", "app_amstar")],
262         "--list returns correct set of applications");
263
264 is(run_get('amgetconf', 'TESTCONF', 'application-tool:app_amgtar:plugin'), 'amgtar',
265     "returns application-tool parameter correctly");
266
267 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'script')))],
268           [sort("my_script")],
269         "--list returns correct set of scripts");
270
271 # test the old names
272 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'script-tool')))],
273           [sort("my_script")],
274         "--list returns correct set of scripts, using the name script-tool");
275
276 is_deeply([sort(+split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'application-tool')))],
277           [sort("app_amgtar", "app_amstar")],
278         "--list returns correct set of applications, using the name 'application-tool'");
279
280 is(run_get('amgetconf', 'TESTCONF', 'script-tool:my_script:execute-on'), 'PRE-DLE-AMCHECK',
281     "returns script-tool parameter correctly");
282 is(run_get('amgetconf', 'TESTCONF', 'script_tOOl:my_script:execute-on'), 'PRE-DLE-AMCHECK',
283     "insensitive to case in subsec_type");
284 is(run_get('amgetconf', 'TESTCONF', 'script-tool:my_script:execute-on'), 'PRE-DLE-AMCHECK',
285     "insensitive to -/_ in subsec_type");
286 is(run_get('amgetconf', 'TESTCONF', 'script_tOOl:my_script:eXECute-on'), 'PRE-DLE-AMCHECK',
287     "insensitive to case in subsec_key");
288 is(run_get('amgetconf', 'TESTCONF', 'script-tool:my_script:execute_on'), 'PRE-DLE-AMCHECK',
289     "insensitive to -/_ in subsec_key");
290 is(run_get('amgetconf', 'TESTCONF', 'dumptype:testdump1:auth', '-odumptype:testdump:auth=SSH'), 'SSH',
291     "inherited setting are overrided");
292 is(run_get('amgetconf', 'TESTCONF', 'dumptype:testdump1:compress', '-odumptype:testdump:compress=SERVER BEST'), 'SERVER BEST',
293     "inherited default are overrided");
294
295 is_deeply([sort(split(/\n/, run_get('amgetconf', 'TESTCONF', '--list', 'device')))],
296           [sort("my_device")],
297         "--list returns correct set of devices");
298
299 is(run_get('amgetconf', 'TESTCONF', 'device:my_device:tapedev'), 'foo:/bar',
300     "returns device parameter correctly");
301
302 # non-existent subsection types, names, and parameters
303 like(run_err('amgetconf', 'TESTCONF', 'NOSUCHTYPE:testiface:comment'), qr/no such parameter/, 
304     "handles bad subsection type");
305 like(run_err('amgetconf', 'TESTCONF', 'dumptype:NOSUCHDUMP:comment'), qr/no such parameter/, 
306     "handles bad dumptype namek");
307 like(run_err('amgetconf', 'TESTCONF', 'dumptype:testdump:NOSUCHPARAM'), qr/no such parameter/, 
308     "handles bad dumptype parameter name");
309 like(run_err('amgetconf', 'TESTCONF', 'application-tool:app_amgtar:NOSUCHPARAM'), qr/no such parameter/, 
310     "handles bad application-tool parameter name");
311 like(run_err('amgetconf', 'TESTCONF', 'script-tool:my-script:NOSUCHPARAM'), qr/no such parameter/, 
312     "handles bad script-tool parameter name");
313
314 like(run_err('amgetconf', 'TESTCONF', '--list', 'frogs'), qr/no such parameter/,
315         "--list fails given an invalid subsection name");
316
317 ##
318 # exclude lists are a bit funny, too
319
320 $testconf = Installcheck::Config->new();
321 $testconf->add_dumptype("testdump", [
322     "exclude file optional" => '"f1"', # this optional will have no effect
323     "exclude file append" => '"f2"',
324     "exclude list" => '"l1"',
325     "exclude list append" => '"l2"',
326     "include file" => '"ifo"',
327     "include list optional" => '"ilo"',
328     ]);
329 $testconf->write();
330
331 is_deeply([sort(+split(qr/\n/, run_get('amgetconf', 'TESTCONF', 'dumptype:testdump:exclude')))],
332           [sort('FILE "f1" "f2"',
333                 'LIST "l1" "l2"')],
334     "exclude files and lists displayed correctly; a non-final optional is ignored");
335
336 is_deeply([sort(+split(qr/\n/, run_get('amgetconf', 'TESTCONF', 'dumptype:testdump:include')))],
337           [sort('FILE OPTIONAL "ifo"',
338                 'LIST OPTIONAL "ilo"')],
339     "a final 'OPTIONAL' makes the whole include/exclude optional");
340
341 $testconf = Installcheck::Config->new();
342 $testconf->add_param("property", '"prop1" "value1"');
343 $testconf->add_param("property", '"prop2" "value2"');
344 $testconf->add_param("property", '"prop3" "value3"');
345 $testconf->write();
346
347 is(run_get('amgetconf', 'TESTCONF', "property:prop1"), "value1", 
348     "correctly returns property prop1 from the file");
349 is(run_get('amgetconf', 'TESTCONF', "property:prop2"), "value2", 
350     "correctly returns property prop2 from the file");
351 is(run_get('amgetconf', 'TESTCONF', "property:prop3"), "value3", 
352     "correctly returns property prop3 from the file");
353 is(run_get('amgetconf', 'TESTCONF', "property"), "\"prop1\" \"value1\"\n\"prop2\" \"value2\"\n\"prop3\" \"value3\"", 
354     "correctly returns all propertiss from the file");
355