Skip to content

Commit

Permalink
doc wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mattias-p committed Aug 1, 2024
1 parent 5cf2e7a commit 3e3e077
Showing 1 changed file with 127 additions and 12 deletions.
139 changes: 127 additions & 12 deletions lib/Zonemaster/CLI/TestCaseSet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,71 @@ use Carp qw( croak );

=head1 NAME
Zonemaster::CLI::TestCaseSet - A mutable set of test methods names.
=head1 SYNOPSIS
use Zoneamster::Engine::TestCaseSet;
# Construct a working subset of test methods {alpha01, alpha02, alpha03,
# beta01} of test methods out of the full set {alpha01, alpha02, alpha03,
# beta01, beta02} distributed across the test modules {alpha, beta}.
my $working_set = Zonemaster::CLI::TestCaseSet->new(
\qw( alpha01 alpha02 alpha03 beta01 ),
{
alpha => \qw( alpha01 alpha02 alpha03 ),
beta => \qw( beta01 beta02 ),
},
);
# Parse a modifier expression into a list of modifiers.
my @modifiers = Zonemaster::CLI::TestCaseSet->parse_modifier_expr( '-alpha+alpha02' );
# Traverse the list of modifiers, chunked into (operator, term) pairs.
while ( @modifiers ) {
my $op = shift @modifiers;
my $term = shift @modifiers;
# Modify the working subset by applying each operator and term.
if ( !$working_set->apply_modifier( $op, $term ) ) {
die __( "Error: Unrecognized term '$term'.\n" );
}
}
# Make sure the working subset ends up in the expected state.
if ( join(' ', $working_set->to_list) ne 'alpha02 beta01' ) {
die;
}
=head1 DESCRIPTION
A TestCaseSet primarily represents an immutable full set of test methods and a
mutable subset thereof. The full set of test methods is distributed across the
set of test modules.
=head2 TERM EXPANSION
Terms are expanded in one of three ways.
=over 4
=item The full set of all test methods.
The term matching the string C<'all'>.
=item The set of all test methods inside one test module.
Terms matching the name of a test module.
=item The singleton set of a single test methods
Terms matching the name of a test methods or the concatenation of a test module,
a slash and a test methodsbelonging to that test module.
=back
Term names are matched case insensitively.
=head1 SUBROUTINES
=cut
Expand All @@ -31,14 +92,26 @@ sub parse_modifier_expr {

=head1 CONSTRUCTORS
=head2 new()
In the full set of test methods, methods names must not share the same name as
other test methods or test modules.
=cut

sub new {
my ( $class, $initial_cases, %all_methods ) = @_;
my ( $class, $initial_methods, %all_methods ) = @_;

my %flattened_methods = map { $_ => 1 } map { @{ $_ } } values %all_methods;
for my $method ( @initial_methods ) {
if ( !exists $flattened_methods ) {
die "Undefined initial method '$method'";
}
}

my $obj = {
_cur_cases => { map { $_ => 1 } @$initial_cases },
_all_term_cases => _get_all_term_cases( \%all_methods ),
_cur_methods => { map { $_ => 1 } @$initial_methods },
_all_term_methods => _get_all_term_methods( \%all_methods ),
};

bless $obj, $class;
Expand All @@ -48,29 +121,62 @@ sub new {

=head1 INSTANCE METHODS
=head2 apply_modifier()
Update the working subset.
The given operator is applied to two operands and the result is assigned to the
working subset. The left hand side operand is the current value of the working
subset. The right hand side operand is calculated by L<expanding|/"TERM
EXPANSION"> the given term to a subset of test methods.
Three operators are supported.
=over 4
=item C<'+'>
Returns the union of the left and right hand side operands
=item C<'-'>
Returns the set difference of the left and right hand side operands
=item C<''>
Ignores the left hand side operand and returns the right hand side operand.
=back
Returns true if the operation is successful.
Returns false if the term could not be expanded.
Dies if the operator is not recognized.
=cut

sub apply_modifier {
my ( $self, $op, $term ) = @_;

my $cases_ref = $self->{_all_term_cases}{ lc $term };
my $methods_ref = $self->{_all_term_methods}{ lc $term };

if ( !defined $cases_ref ) {
if ( !defined $methods_ref ) {
return 0;
}

if ( $op eq '' ) {
$self->{_cur_cases} = {};
$self->{_cur_methods} = {};
}

if ( $op eq '-' ) {
for my $case ( @$cases_ref ) {
delete $self->{_cur_cases}{$case};
for my $method ( @$methods_ref ) {
delete $self->{_cur_methods}{$method};
}
}
elsif ( $op eq '+' ) {
for my $case ( @$cases_ref ) {
$self->{_cur_cases}{$case} = 1;
for my $method ( @$methods_ref ) {
$self->{_cur_methods}{$method} = 1;
}
}
else {
Expand All @@ -83,18 +189,27 @@ sub apply_modifier {
sub to_list {
my ( $self ) = @_;

return sort keys %{ $self->{_cur_cases} };
return sort keys %{ $self->{_cur_methods} };
}

sub _get_all_term_cases {
sub _get_all_term_methods {
my ( $all_methods ) = @_;

my $terms = {};
$terms->{all} = [];

for my $module ( keys %$all_methods ) {
if ( lc $module eq 'all' ) {
croak "module name must not be 'all'";
}
$terms->{ lc $module } = [];
for my $method ( @{ $all_methods->{$module} } ) {
if ( lc $method eq 'all' ) {
croak "method name must not be 'all'";
}
if ( exists $terms->{lc $method} ) {
croak "found method with same name as another method or module: '$method'";
}
$terms->{ lc $method } = [$method];
$terms->{ lc "$module/$method" } = [$method];
push @{$terms->{ lc $module }}, $method;
Expand Down

0 comments on commit 3e3e077

Please sign in to comment.