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

229 lines
7.8 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use warnings;
################################################################################
# A Fcm::Keyword::Entry sub-class for testing
{
package TestEntry;
use base qw{Fcm::Keyword::Entry};
}
################################################################################
# A mock loader implementing the Fcm::Keyword::Loader interface
{
package MockLoader0;
use Scalar::Util qw{blessed};
############################################################################
# Constructor
sub new {
my ($class) = @_;
return bless({number_of_calls_to_load_to => 0}, $class);
}
############################################################################
##Returns the package name
sub get_source {
my ($self) = @_;
return blessed($self);
}
############################################################################
# Returns number of times $self->load_to() has been called
sub get_number_of_calls_to_load_to {
my ($self) = @_;
return $self->{number_of_calls_to_load_to};
}
############################################################################
# Loads data into $entries, and returns number of entries loaded
sub load_to {
my ($self, $entries) = @_;
$self->{number_of_calls_to_load_to}++;
return $self->load_to_impl($entries);
}
############################################################################
# Returns 0
sub load_to_impl {
my ($self, $entries) = @_;
return 0;
}
}
################################################################################
# A mock loader implementing the Fcm::Keyword::Loader interface
{
package MockLoader1;
our @ISA = qw{MockLoader0};
my %VALUE_OF = (foo => 'foo1', bar => 'bar2', baz => 'baz3');
############################################################################
# Returns a reference to the mock data
sub get_data {
my ($class) = @_;
return \%VALUE_OF;
}
############################################################################
##Writes mock data to the $entries object
sub load_to_impl {
my ($self, $entries) = @_;
my $counter = 0;
for my $key (keys(%{$self->get_data()})) {
$entries->add_entry($key, $self->get_data()->{$key});
$counter++;
}
return $counter;
}
}
################################################################################
# A mock loader implementing the Fcm::Keyword::Loader interface
{
package MockLoader2;
our @ISA = qw{MockLoader1};
my %VALUE_OF = (sausages => 'pig', eggs => 'hen', chips => 'potato');
############################################################################
# Returns a reference to the mock data
sub get_data {
my ($class) = @_;
return \%VALUE_OF;
}
}
package main;
use Test::More qw{no_plan};
main();
sub main {
my $class = 'Fcm::Keyword::Entries';
use_ok($class);
test_empty_constructor($class);
test_constructor($class);
test_add_entry($class);
test_loaders($class);
}
################################################################################
# Tests empty constructor
sub test_empty_constructor {
my ($class) = @_;
my $prefix = 'empty constructor';
my $entries = $class->new();
isa_ok($entries, $class);
is($entries->get_entry_class(), 'Fcm::Keyword::Entry',
"$prefix: default entry class");
is_deeply([$entries->get_loaders()], [], "$prefix: empty list of loaders");
is_deeply([$entries->get_all_entries()], [],
"$prefix: empty list of entries");
for my $arg ('foo', undef) {
is($entries->get_entry_by_key($arg), undef,
"$prefix: entry by key: undef");
is($entries->get_entry_by_value($arg), undef,
"$prefix: entry by value: undef");
}
}
################################################################################
# Tests other constructor usages
sub test_constructor {
my ($class) = @_;
my $prefix = 'constructor';
my @loaders = (MockLoader1->new(), MockLoader2->new());
my $entries = $class->new({
entry_class => 'not-a-class',
loaders => \@loaders,
});
isa_ok($entries, $class);
is($entries->get_entry_class(), 'not-a-class', "$prefix: entry class");
is_deeply([$entries->get_loaders()], \@loaders, "$prefix: list of loaders");
eval {
$entries->add_entry('key', 'value');
};
isnt($@, undef, "$prefix: invalid entry class");
}
################################################################################
# Tests adding entries
sub test_add_entry {
my ($class) = @_;
my $prefix = 'add entry';
my %VALUE_OF = (key1 => 'value1', egg => 'white and yolk', 'xyz.abc' => '');
for my $entry_class ('Fcm::Keyword::Entry', 'TestEntry') {
my $entries = $class->new({entry_class => $entry_class});
my $number_of_entries = 0;
for my $key (keys(%VALUE_OF)) {
my $entry = $entries->add_entry($key, $VALUE_OF{$key});
isa_ok($entry, $entry_class);
is(scalar(@{$entries->get_all_entries()}), ++$number_of_entries,
"$prefix: number of entries: $number_of_entries");
}
for my $key (keys(%VALUE_OF)) {
my $entry = $entries->get_entry_by_key($key);
isa_ok($entry, $entry_class);
is($entry->get_key(), uc($key), "$prefix: get by key: $key");
is($entry->get_value(), $VALUE_OF{$key},
"$prefix: get by key: $key: value");
}
for my $key (keys(%VALUE_OF)) {
my $entry = $entries->get_entry_by_value($VALUE_OF{$key});
isa_ok($entry, $entry_class);
is($entry->get_key(), uc($key), "$prefix: get by value: $key");
is($entry->get_value(), $VALUE_OF{$key},
"$prefix: get by value: $key: value");
}
is($entries->get_entry_by_key('no-such-key'), undef,
"$prefix: get by key: no-such-key");
is($entries->get_entry_by_value('no-such-value'), undef,
"$prefix: get by value: no-such-value");
}
}
################################################################################
# Tests usage of loaders
sub test_loaders {
my ($class) = @_;
my $prefix = "loader";
my @loaders = (MockLoader0->new(), MockLoader1->new(), MockLoader2->new());
my $entries = $class->new({loaders => \@loaders});
for my $loader (@loaders) {
is($loader->get_number_of_calls_to_load_to(), 0, "$prefix: not loaded");
}
for my $key (keys(%{$loaders[1]->get_data()})) {
my $value = $loaders[1]->get_data()->{$key};
my $entry = $entries->get_entry_by_key($key);
is($entry->get_key(), uc($key), "$prefix: by key: $key: key");
is($entries->get_entry_by_value($value), $entry,
"$prefix: by value: $key: object");
}
is($loaders[0]->get_number_of_calls_to_load_to(), 1,
"$prefix: loaded once: 0");
is($loaders[1]->get_number_of_calls_to_load_to(), 1,
"$prefix: loaded once: 1");
is($loaders[2]->get_number_of_calls_to_load_to(), 0,
"$prefix: not loaded: 2");
for my $key (keys(%{$loaders[2]->get_data()})) {
my $value = $loaders[2]->get_data()->{$key};
my $entry = $entries->get_entry_by_key($key);
is($entry->get_key(), uc($key), "$prefix: by key: $key: key");
is($entries->get_entry_by_value($value), $entry,
"$prefix: by value: $key: object");
}
is($loaders[0]->get_number_of_calls_to_load_to(), 2,
"$prefix: loaded once: 0");
is($loaders[1]->get_number_of_calls_to_load_to(), 1,
"$prefix: loaded once: 1");
is($loaders[2]->get_number_of_calls_to_load_to(), 1,
"$prefix: not loaded: 2");
}
__END__