+ is_deeply(getconf($CNF_RECOVERY_LIMIT),
+ [ 'foo', 'bar' ],
+ "global recovery-limit parameter");
+
+ $dtyp = lookup_dumptype("rl1");
+ is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
+ [ undef ],
+ "same-host => undef in list");
+
+ $dtyp = lookup_dumptype("rl2");
+ is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
+ [ "somehost" ],
+ "hostname => match pattern");
+
+ $dtyp = lookup_dumptype("rl3");
+ is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
+ [ undef, "somehost" ],
+ "hostname and same-host parsed correctly");
+
+ $dtyp = lookup_dumptype("rl4");
+ is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT),
+ [ undef, "foohost" ], # note that the order is an implementation detail
+ ".. even if same-host comes last");
+}
+
+##
+# Try an autolabel with a template and 'any'
+
+$testconf = Installcheck::Config->new();
+$testconf->add_param('autolabel', '"FOO%%%BAR" any');
+$testconf->write();
+
+$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
+is($cfg_result, $CFGERR_OK,
+ "first exinclude parsing config loaded")
+ or diag_config_errors();
+SKIP: {
+ skip "error loading config", 1 unless $cfg_result == $CFGERR_OK;
+ is_deeply(getconf($CNF_AUTOLABEL),
+ { template => "FOO%%%BAR", other_config => 1,
+ non_amanda => 1, volume_error => 1, empty => 1 },
+ "'autolabel \"FOO%%%BAR\" any' represented correctly");
+}
+
+##
+# Check out where quoting is and is not required.
+
+$testconf = Installcheck::Config->new();
+
+# make sure an unquoted tapetype is OK
+$testconf->add_param('tapetype', 'TEST-TAPE'); # unquoted (Installcheck::Config uses quoted)
+
+# strings can optionally be quoted
+$testconf->add_param('dumporder', '"STSTST"');
+
+# enumerations (e.g., taperalgo) must not be quoted; implicitly tested above
+
+# definitions
+$testconf->add_dumptype('"parent"', [ # note quotes
+ 'bumpsize' => '10240',
+]);
+$testconf->add_dumptype('child', [
+ '' => '"parent"', # note quotes
+]);
+$testconf->add_dumptype('child2', [
+ '' => 'parent',
+]);
+$testconf->write();
+
+$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
+is($cfg_result, $CFGERR_OK,
+ "parsed config to test strings vs. identifiers")
+ or diag_config_errors();
+SKIP: {
+ skip "error loading config", 3 unless $cfg_result == $CFGERR_OK;
+
+ my $dtyp = lookup_dumptype("parent");
+ ok($dtyp, "found parent");
+ $dtyp = lookup_dumptype("child");
+ ok($dtyp, "found child");
+ is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), 10240,
+ "child dumptype correctly inherited bumpsize");
+}
+
+##
+# Explore a quirk of read_int_or_str parsing.
+
+$testconf = Installcheck::Config->new();
+$testconf->add_dumptype('mydump-type1', [
+ 'client_port' => '12345',
+]);
+$testconf->add_dumptype('mydump-type2', [
+ 'client_port' => '"newamanda"',
+]);
+$testconf->add_dumptype('mydump-type3', [
+ 'client_port' => '"67890"',
+]);
+$testconf->write();
+
+$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
+is($cfg_result, $CFGERR_OK,
+ "read_int_or_str parsing config loaded")
+ or diag_config_errors();
+SKIP: {
+ skip "error loading config", 6 unless $cfg_result == $CFGERR_OK;
+
+ my $dtyp = lookup_dumptype("mydump-type1");
+ ok($dtyp, "found mydump-type1");
+ is(dumptype_getconf($dtyp, $DUMPTYPE_CLIENT_PORT), "12345",
+ "client_port set to 12345");
+
+ $dtyp = lookup_dumptype("mydump-type2");
+ ok($dtyp, "found mydump-type1");
+ is(dumptype_getconf($dtyp, $DUMPTYPE_CLIENT_PORT), "newamanda",
+ "client_port set to \"newamanda\"");
+
+ $dtyp = lookup_dumptype("mydump-type3");
+ ok($dtyp, "found mydump-type1");
+ is(dumptype_getconf($dtyp, $DUMPTYPE_CLIENT_PORT), "67890",
+ "client_port set to \"67890\"");
+}
+
+##
+# Check property inheritance
+
+$testconf = Installcheck::Config->new();
+$testconf->add_application('app1', [
+ 'property' => '"prop1" "val1"'
+]);
+$testconf->add_application('app2', [
+ 'property' => 'append "prop2" "val2"'
+]);
+$testconf->add_application('app3', [
+ 'property' => '"prop3" "val3"'
+]);
+$testconf->add_application('app1a', [
+ 'property' => '"prop4" "val4"',
+ 'property' => '"prop1" "val1a"',
+ 'app1' => undef
+]);
+$testconf->add_application('app2a', [
+ 'property' => '"prop5" "val5"',
+ 'property' => '"prop2" "val2a"',
+ 'app2' => undef
+]);
+$testconf->add_application('app3a', [
+ 'property' => '"prop6" "val6"',
+ 'app3' => undef,
+ 'property' => '"prop7" "val7"'
+]);
+$testconf->add_application('app1b', [
+ 'property' => '"prop4" "val4"',
+ 'property' => '"prop1" "val1a"',
+ 'app1' => undef,
+ 'property' => '"prop1" "val1b"',
+]);
+$testconf->add_application('app2b', [
+ 'property' => '"prop5" "val5"',
+ 'property' => '"prop2" "val2a"',
+ 'app2' => undef,
+ 'property' => 'append "prop2" "val2b"',
+]);
+$testconf->write();
+
+$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
+is($cfg_result, $CFGERR_OK,
+ "application properties inheritance")
+ or diag_config_errors();
+SKIP: {
+ skip "error loading config", 15 unless $cfg_result == $CFGERR_OK;
+
+ my $app = lookup_application("app1a");
+ ok($app, "found app1a");
+ is(application_name($app), "app1a",
+ "app1a knows its name");
+ my $prop = application_getconf($app, $APPLICATION_PROPERTY);
+ is_deeply($prop, { "prop4" => { priority => 0,
+ append => 0,
+ values => [ "val4" ]},
+ "prop1" => { priority => 0,
+ append => 0,
+ values => [ "val1" ] }},
+ "PROPERTY parameter of app1a parsed correctly");
+
+ $app = lookup_application("app2a");
+ ok($app, "found app2a");
+ is(application_name($app), "app2a",
+ "app2a knows its name");
+ $prop = application_getconf($app, $APPLICATION_PROPERTY);
+ is_deeply($prop, { "prop5" => { priority => 0,
+ append => 0,
+ values => [ "val5" ]},
+ "prop2" => { priority => 0,
+ append => 0,
+ values => [ "val2a", "val2" ] }},
+ "PROPERTY parameter of app2a parsed correctly");
+
+ $app = lookup_application("app3a");
+ ok($app, "found app3a");
+ is(application_name($app), "app3a",
+ "app3a knows its name");
+ $prop = application_getconf($app, $APPLICATION_PROPERTY);
+ is_deeply($prop, { "prop3" => { priority => 0,
+ append => 0,
+ values => [ "val3" ]},
+ "prop6" => { priority => 0,
+ append => 0,
+ values => [ "val6" ] },
+ "prop7" => { priority => 0,
+ append => 0,
+ values => [ "val7" ] }},
+ "PROPERTY parameter of app3a parsed correctly");
+
+ $app = lookup_application("app1b");
+ ok($app, "found app1b");
+ is(application_name($app), "app1b",
+ "app1b knows its name");
+ $prop = application_getconf($app, $APPLICATION_PROPERTY);
+ is_deeply($prop, { "prop4" => { priority => 0,
+ append => 0,
+ values => [ "val4" ]},
+ "prop1" => { priority => 0,
+ append => 0,
+ values => [ "val1b" ] }},
+ "PROPERTY parameter of app1b parsed correctly");
+
+ $app = lookup_application("app2b");
+ ok($app, "found app2b");
+ is(application_name($app), "app2b",
+ "app2b knows its name");
+ $prop = application_getconf($app, $APPLICATION_PROPERTY);
+ is_deeply($prop, { "prop5" => { priority => 0,
+ append => 0,
+ values => [ "val5" ]},
+ "prop2" => { priority => 0,
+ append => 1,
+ values => [ "val2a", "val2", "val2b" ] }},
+ "PROPERTY parameter of app2b parsed correctly");
+}
+
+
+##
+# Check getconf_byname and getconf_byname_strs
+
+$testconf = Installcheck::Config->new();
+$testconf->add_param('tapedev', '"thats a funny name"');
+$testconf->add_application('app1', [
+ 'comment' => '"one"',
+]);
+$testconf->add_script('scr1', [
+ 'comment' => '"one"',
+]);
+# check old names, too
+$testconf->add_text(<<EOF);
+define application-tool "app2" {
+ comment "two"
+}
+EOF
+$testconf->add_text(<<EOF);
+define script-tool "scr2" {
+ comment "two"
+}
+EOF
+$testconf->write();
+
+$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
+is($cfg_result, $CFGERR_OK,
+ "getconf_byname")
+ or diag_config_errors();
+SKIP: {
+ skip "error loading config", 7 unless $cfg_result == $CFGERR_OK;
+
+ is(getconf_byname("Tapedev"), "thats a funny name",
+ "getconf_byname for global param");
+ is_deeply([ getconf_byname_strs("Tapedev", 1) ],
+ [ "\"thats a funny name\"" ],
+ "getconf_byname_strs for global param with quotes");
+ is_deeply([ getconf_byname_strs("Tapedev", 0) ],
+ [ "thats a funny name" ],
+ "getconf_byname_strs for global param without quotes");
+
+ # test * and *-tool (the old name)
+ is(getconf_byname("application-tool:app1:comment"), "one",
+ "getconf_byname for appplication-tool param");
+ is(getconf_byname("application:app2:comment"), "two",
+ "getconf_byname for application param");
+ is(getconf_byname("script-tool:scr1:comment"), "one",
+ "getconf_byname for appplication-tool param");
+ is(getconf_byname("script:scr2:comment"), "two",
+ "getconf_byname for script param");
+}
+
+my @boolean_vals = (
+ {'val' => '1', 'expected' => 1},
+ {'val' => '0', 'expected' => 0},
+ {'val' => 't', 'expected' => 1},
+ {'val' => 'true', 'expected' => 1},
+ {'val' => 'f', 'expected' => 0},
+ {'val' => 'false', 'expected' => 0},
+ {'val' => 'y', 'expected' => 1},
+ {'val' => 'yes', 'expected' => 1},
+ {'val' => 'n', 'expected' => 0},
+ {'val' => 'no', 'expected' => 0},
+ {'val' => 'on', 'expected' => 1},
+ {'val' => 'off', 'expected' => 0},
+ {'val' => 'oFf', 'expected' => 0},
+ {'val' => 'foo', 'expected' => undef},
+ );
+
+for my $bv (@boolean_vals) {
+ is(string_to_boolean($bv->{'val'}), $bv->{'expected'},
+ "string_to_boolean('$bv->{'val'}') is right");
+}
+
+my @prop_names = (
+ {'val' => '', 'expected' => ''},
+ {'val' => 'prop-name', 'expected' => 'prop-name'},
+ {'val' => 'PRoP-NaME', 'expected' => 'prop-name'},
+ {'val' => 'prop_name', 'expected' => 'prop-name'},
+ {'val' => 'FaNCy_ProP', 'expected' => 'fancy-prop'},
+ {'val' => '_under_', 'expected' => '-under-'},
+ {'val' => '-dash-', 'expected' => '-dash-'},
+ {'val' => '-', 'expected' => '-'},
+ {'val' => '_', 'expected' => '-'},
+ );
+
+for my $pn (@prop_names) {
+ is(amandaify_property_name($pn->{'val'}), $pn->{'expected'},
+ "amandaify_property_name('$pn->{'val'}') is right");
+}
+
+$testconf = Installcheck::Config->new();
+$testconf->add_param('property', '"PrOP_nAme" "VALUE"');
+$testconf->write();
+config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF");
+my $properties = getconf($CNF_PROPERTY);
+
+@prop_names = (
+ {'val' => 'prop-name'},
+ {'val' => 'PRoP-NaME'},
+ {'val' => 'prop_name'},
+ {'val' => 'PROP_NAME'},
+ {'val' => 'PRoP-NaME'},
+ {'val' => 'prop_name'},
+ );
+
+for my $pn (@prop_names) {
+ is_deeply($properties->{$pn->{'val'}}->{values}, [ "VALUE" ]);