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