2025-09-05 09:42:21 +02:00

238 lines
7.5 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use warnings;
################################################################################
# A sub-class of Fcm::CLI::Invoker for testing
{
package TestInvoker;
use base qw{Fcm::CLI::Invoker};
our $LATEST_INSTANCE;
############################################################################
# Returns a test attrib
sub get_test_attrib {
my ($self) = @_;
return $self->{test_attrib};
}
############################################################################
# Invokes the sub-system
sub invoke {
my ($self) = @_;
$LATEST_INSTANCE = $self;
}
}
use Fcm::CLI::Config;
use Fcm::CLI::Subcommand;
use Test::More (tests => 25);
main();
sub main {
use_ok('Fcm::CLI');
test_invalid_subcommand();
test_invoker_not_implemented();
test_normal_invoke();
test_help_invoke();
test_get_invoker_normal();
test_load_invoker_class();
}
################################################################################
# Tests to ensure that an invalid subcommand results in an exception
sub test_invalid_subcommand {
Fcm::CLI::Config->instance({core_subcommands => [], vc_subcommands => []});
eval {
local(@ARGV) = ('foo');
Fcm::CLI::invoke();
};
like($@, qr{foo: unknown command}, 'invalid subcommand');
}
################################################################################
# Tests to ensure that an unimplemented invoker results in an exception
sub test_invoker_not_implemented {
Fcm::CLI::Config->instance({
core_subcommands => [
Fcm::CLI::Subcommand->new({names => ['foo']}),
Fcm::CLI::Subcommand->new({
names => ['bar'], invoker_class => 'barley',
}),
],
vc_subcommands => [],
});
eval {
local(@ARGV) = ('foo');
Fcm::CLI::invoke();
};
like($@, qr{foo: \s command \s not \s implemented}xms, 'not implemented');
eval {
local(@ARGV) = ('bar');
Fcm::CLI::invoke();
};
like($@, qr{barley: \s class \s loading \s failed}xms, 'not implemented');
}
################################################################################
# Tests normal usage of invoke
sub test_normal_invoke {
my $prefix = "normal invoke";
Fcm::CLI::Config->instance({
core_subcommands => [
Fcm::CLI::Subcommand->new({
names => ['foo'],
invoker_class => 'TestInvoker',
invoker_config => {test_attrib => 'test_attrib value'},
}),
],
vc_subcommands => [],
});
ok(!$TestInvoker::LATEST_INSTANCE, "$prefix: invoker not called");
local(@ARGV) = ('foo', 'bar', 'baz');
Fcm::CLI::invoke();
my $invoker = $TestInvoker::LATEST_INSTANCE;
if (!$invoker) {
fail($prefix);
}
else {
is($invoker->get_command(), 'foo', "$prefix: invoker command");
is_deeply({$invoker->get_options()}, {}, "$prefix: invoker options");
is_deeply([$invoker->get_arguments()], ['bar', 'baz'],
"$prefix: invoker arguments");
is($invoker->get_test_attrib(), 'test_attrib value',
"$prefix: invoker test attrib");
}
$TestInvoker::LATEST_INSTANCE = undef;
}
################################################################################
# Tests help usage of invoke
sub test_help_invoke {
my $prefix = "help invoke";
Fcm::CLI::Config->instance({
core_subcommands => [
Fcm::CLI::Subcommand->new({
names => ['foo'],
invoker_class => 'TestInvoker',
invoker_config => {test_attrib => 'test_attrib value normal'},
options => [
Fcm::CLI::Option->new({name => 'foo', is_help => 1}),
],
}),
Fcm::CLI::Subcommand->new({
names => [q{}],
invoker_class => 'TestInvoker',
}),
],
vc_subcommands => [],
});
ok(!$TestInvoker::LATEST_INSTANCE, "$prefix: invoker not called");
local(@ARGV) = ('foo', '--foo');
Fcm::CLI::invoke();
my $invoker = $TestInvoker::LATEST_INSTANCE;
if (!$invoker) {
fail($prefix);
}
else {
is_deeply([$invoker->get_arguments()], ['foo'],
"$prefix: invoker argument");
}
$TestInvoker::LATEST_INSTANCE = undef;
}
################################################################################
# Tests getting an invoker
sub test_get_invoker_normal {
my $prefix = 'get invoker normal';
my @options = (
Fcm::CLI::Option->new({name => 'foo'}),
Fcm::CLI::Option->new({name => 'bar'}),
Fcm::CLI::Option->new({name => 'baz'}),
Fcm::CLI::Option->new({
name => q{pork},
delimiter => q{,},
has_arg => Fcm::CLI::Option->ARRAY_ARG,
}),
);
my $subcommand = Fcm::CLI::Subcommand->new({options => \@options});
my %TEST = (
test1 => {
argv => ['--foo', '--bar', 'egg', 'ham', 'sausage'],
command => 'command',
options => {foo => 1, bar => 1},
arguments => ['egg', 'ham', 'sausage'],
},
test2 => {
argv => ['--baz', '--foo', '--bar'],
command => 'test',
options => {foo => 1, bar => 1, baz => 1},
arguments => [],
},
test3 => {
argv => ['egg', 'ham', 'sausage'],
command => 'meal',
options => {},
arguments => ['egg', 'ham', 'sausage'],
},
test4 => {
argv => ['--pork', 'ham', '--pork', 'sausage'],
command => 'pig',
options => {pork => ['ham', 'sausage']},
arguments => [],
},
test5 => {
argv => ['--pork', 'ham,sausage', '--pork', 'bacon', 'liver'],
command => 'pig',
options => {pork => ['ham', 'sausage', 'bacon']},
arguments => ['liver'],
},
);
for my $key (keys(%TEST)) {
local(@ARGV) = @{$TEST{$key}{argv}};
my ($opts_ref, $args_ref) = Fcm::CLI::_parse_argv_using($subcommand);
is_deeply($opts_ref, $TEST{$key}{options},
"$prefix $key: get options");
is_deeply($args_ref, $TEST{$key}{arguments},
"$prefix $key: get arguments");
}
my %BAD_TEST = (
test1 => {
argv => ['--egg', '--bar', 'foo', 'ham', 'sausage'],
},
test2 => {
argv => ['--foo=egg'],
},
);
for my $key (keys(%BAD_TEST)) {
local(@ARGV) = @{$BAD_TEST{$key}{argv}};
eval {
Fcm::CLI::_parse_argv_using($subcommand);
};
isa_ok($@, 'Fcm::CLI::Exception', "$prefix $key");
}
}
################################################################################
# Tests loading an invoker with a different class
sub test_load_invoker_class {
my $prefix = 'get invoker class';
eval {
my $subcommand = Fcm::CLI::Subcommand->new({invoker_class => 'foo'});
Fcm::CLI::_load_invoker_class_of($subcommand);
};
isa_ok($@, 'Fcm::Exception', "$prefix");
my $invoker_class = 'Fcm::CLI::Invoker::ConfigSystem';
my $subcommand
= Fcm::CLI::Subcommand->new({invoker_class => $invoker_class});
my $class = Fcm::CLI::_load_invoker_class_of($subcommand);
is($class, $invoker_class, "$prefix: $invoker_class");
}
__END__