Skip to content

Commit

Permalink
Item14152: Continue with the extensions tests.
Browse files Browse the repository at this point in the history
- Added the forgotten test suite ExtensionsTests.

- Fixed a but with unreset iteration over method list.
  • Loading branch information
vrurg committed Sep 15, 2016
1 parent 505aef1 commit c2af1d7
Show file tree
Hide file tree
Showing 5 changed files with 504 additions and 70 deletions.
368 changes: 368 additions & 0 deletions UnitTestContrib/test/unit/ExtensionsTests.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,368 @@
# See bottom of file for license and copyright information

package Foswiki::ExtensionsTests::SampleClass {
use Foswiki::Class qw(extensible);
extends qw(Foswiki::Object);

has allowFlowControl => (
is => 'rw',
default => 0,
);

pluggable testPluggableMethod => sub {
my $this = shift;

return wantarray
? ( qw(This is a sample return array), @_ )
: "This is a sample string {" . join( "}{", @_ ) . "}";
};
}

package ExtensionsTests;

use Assert;
use Foswiki::Exception ();

use Foswiki::Class;
extends qw(FoswikiFnTestCase);

$| = 1;

# List of all auto generated extension modules.
has autoGenerated => (
is => 'rw',
default => sub { [] },
);

around set_up => sub {
my $orig = shift;
my $this = shift;

my $mKey = ( grep { /ExtensionsTests/ } keys %INC )[0];
$this->app->env->{FOSWIKI_EXTLIBS} =
File::Spec->catdir( ( File::Spec->splitpath( $INC{$mKey} ) )[1],
'TestExtensions' );

# Disable all extensions generated by previous tests.
$this->app->env->{FOSWIKI_DISABLED_EXTENSIONS} = $this->autoGenerated;

$this->app->cfg->data->{DisableAllPlugins} = 1;

$orig->( $this, @_ );
};

sub _getExtName {
my $this = shift;

state $idx = 0;

return sprintf( 'Foswiki::Extension::Ext::Auto%04d', $idx++ );
}

sub _genExtModules {
my $this = shift;
my ( $count, @extCode ) = @_;

my @extNames;
for ( 1 .. $count ) {
my $extName = $this->_getExtName;
my $code = shift @extCode // '';
my $ret = eval <<EXT;
package $extName;
use Foswiki::Class qw(extension);
extends qw(Foswiki::Extension);
Foswiki::Extensions::registerExtModule('$extName');
$code
1;
EXT
unless ($ret) {
Foswiki::Exception::Fatal->throw(
text => "Extension module cannot be generated: "
. Foswiki::Exception::errorStr($@) );
}
push @extNames, $extName;
}

# Remember what extensions have been autogenerated.
push @{ $this->autoGenerated }, @extNames;

return @extNames;
}

sub _setExtDependencies {
my $this = shift;
my %deps = @_;

foreach my $extName ( keys %deps ) {
my $dep = $deps{$extName};
Foswiki::Extensions::registerDeps( $extName,
ref($dep) ? @{$dep} : $dep );
}
}

sub _disableAllCurrentExtensions {
my $this = shift;
$this->app->env->{FOSWIKI_DISABLED_EXTENSIONS} =
[@Foswiki::Extensions::extModules];
}

sub test_orderedList {
my $this = shift;

# First disable all previously loaded extensions.
$this->_disableAllCurrentExtensions;

my @ext = $this->_genExtModules(4);
$this->_setExtDependencies(
$ext[0] => $ext[2],
$ext[2] => $ext[3],
$ext[3] => $ext[1],
);
$this->reCreateFoswikiApp;

my $expected = [ @ext[ 1, 3, 2, 0 ] ];

$this->assert_deep_equals(
$expected,
$this->app->extensions->orderedList,
"Wrong order of extensions"
);
}

sub test_manual_disable {
my $this = shift;

my @ext = $this->_genExtModules(2);
$this->app->env->{FOSWIKI_DISABLED_EXTENSIONS} = $ext[1];
$this->reCreateFoswikiApp;

$this->assert_not_null(
$this->app->extensions->extensions->{ $ext[0] },
"First extension is expected to be initialized"
);
$this->assert( !$this->app->extensions->extEnabled( $ext[1] ),
"Second extensions is expected to be disabled but it is not" );
$this->assert_str_equals(
"Disabled by FOSWIKI_DISABLED_EXTENSIONS environment variable.",
$this->app->extensions->disabledExtensions->{ $ext[1] }
);
}

sub test_depend_on_manual_disable {
my $this = shift;

my @ext = $this->_genExtModules(4);
$this->app->env->{FOSWIKI_DISABLED_EXTENSIONS} = $ext[1];
$this->_setExtDependencies(
$ext[3] => $ext[2],
$ext[2] => $ext[1],
);

$this->reCreateFoswikiApp;

$this->assert_not_null(
$this->app->extensions->extensions->{ $ext[0] },
"First extension is expected to be initialized"
);
$this->assert( !$this->app->extensions->extEnabled( $ext[1] ),
"Second extensions is expected to be disabled but it is not" );
$this->assert_str_equals(
"Disabled by FOSWIKI_DISABLED_EXTENSIONS environment variable.",
$this->app->extensions->disabledExtensions->{ $ext[1] }
);
$this->assert(
!$this->app->extensions->extEnabled( $ext[2] ),
"Third extensions is expected to be disabled but it is not"
);
$this->assert( !$this->app->extensions->extEnabled( $ext[3] ),
"Fourth extensions is expected to be disabled but it is not" );

$this->assert_str_contains( "Disabled extension",
$this->app->extensions->disabledExtensions->{ $ext[2] } );

$this->assert_str_contains( "Disabled extension",
$this->app->extensions->disabledExtensions->{ $ext[3] } );
}

sub test_circular_deps {
my $this = shift;

$this->_disableAllCurrentExtensions;

my @ext = $this->_genExtModules(4);
$this->_setExtDependencies(
$ext[0] => $ext[2],
$ext[3] => $ext[1],
$ext[1] => $ext[3],
);
$this->reCreateFoswikiApp;

my $expected = [ @ext[ 2, 0 ] ];

$this->assert_deep_equals(
$expected,
$this->app->extensions->orderedList,
"Wrong order of extensions"
);

$this->assert_str_contains( "Circular dependecy found for ",
$this->app->extensions->disabledExtensions->{ $ext[1] } );

$this->assert_str_contains( "Circular dependecy found for ",
$this->app->extensions->disabledExtensions->{ $ext[3] } );
}

sub test_pluggable_methods {
my $this = shift;

$this->_disableAllCurrentExtensions;
my @ext = $this->_genExtModules(
3,
<<'EXT1',
plugBefore 'Foswiki::ExtensionsTests::SampleClass::testPluggableMethod' => sub {
my $this = shift;
my ($params) = @_;
$this->_traceMsg("");
# We expect at least to parameters to be passed in.
$params->{args}[1] = "ext1ArgFromBefore";
};
EXT1
<<'EXT2',
plugAround 'Foswiki::ExtensionsTests::SampleClass::testPluggableMethod' => sub {
my $this = shift;
my ($params) = @_;
$this->_traceMsg("");
# Only if flow control is allowed by the calling test code.
if ($params->{object}->allowFlowControl) {
my $rc = 'ext2ReturnFromAround';
if ( $params->{wantarray} ) {
$params->{rc} = [$rc];
}
elsif ( defined $params->{wantarray} ) {
$params->{rc} .= ($params->{rc} ? " " : "") . $rc;
}
delete $params->{ext3Flag1};
Foswiki::Exception::Ext::Last->throw(
rc => $params->{rc},
extension => $this,
);
}
};
EXT2
<<'EXT3',
plugBefore 'Foswiki::ExtensionsTests::SampleClass::testPluggableMethod' => sub {
my $this = shift;
my ($params) = @_;
$this->_traceMsg("");
$params->{ext3Flag1} = 1;
$params->{ext3Flag2} = 1;
};
plugAfter 'Foswiki::ExtensionsTests::SampleClass::testPluggableMethod' => sub {
my $this = shift;
my ($params) = @_;
$this->_traceMsg("");
foreach my $flag (qw(ext3Flag1 ext3Flag2)) {
if ($params->{$flag}) {
my $rc = "with_$flag";
if ($params->{wantarray}) {
push @{$params->{rc}}, $rc;
}
elsif (defined $params->{wantarray}) {
$params->{rc} .= " $rc";
}
}
}
};
EXT3
);
$this->_setExtDependencies(
$ext[2] => $ext[1],
$ext[1] => $ext[0],
);

$this->reCreateFoswikiApp;

my $testClass = 'Foswiki::ExtensionsTests::SampleClass';
my $testMethod = 'testPluggableMethod';
$this->assert(
defined $Foswiki::Extensions::pluggables{$testClass}{$testMethod},
"Method "
. $testMethod
. " of class "
. $testClass
. " is not registered as pluggable!"
);

my $testObj = $this->create('Foswiki::ExtensionsTests::SampleClass');

$this->assert( $testObj->DOES('Foswiki::Aux::_ExtensibleRole'),
"Test object of class "
. ref($testObj)
. " doesn't have extensible role!" );

my @args;
@args = qw(arg1 arg2);
my $rc = $testObj->testPluggableMethod(@args);

$this->assert_str_equals(
'This is a sample string {arg1}{ext1ArgFromBefore} with_ext3Flag1 with_ext3Flag2',
$rc
);

@args = qw(arg1 arg2);
my @rc = $testObj->testPluggableMethod(@args);

$this->assert_deep_equals(
[
qw(This is a sample return array arg1 ext1ArgFromBefore with_ext3Flag1 with_ext3Flag2)
],
\@rc
);

$testObj->allowFlowControl(1);
@args = qw(arg1 arg2);
$rc = $testObj->testPluggableMethod(@args);

$this->assert_str_equals( 'ext2ReturnFromAround with_ext3Flag2', $rc );

@args = qw(arg1 arg2);
@rc = $testObj->testPluggableMethod(@args);

$this->assert_deep_equals( [qw(ext2ReturnFromAround with_ext3Flag2)],
[@rc] );
}

1;
__END__
Foswiki - The Free and Open Source Wiki, http://foswiki.org/
Copyright (C) 2016 Foswiki Contributors. Foswiki Contributors
are listed in the AUTHORS file in the root of this distribution.
NOTE: Please extend that file, not this notice.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. For
more details read LICENSE in the root of this distribution.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
As per the GPL, removal of this notice is prohibited.
Loading

0 comments on commit c2af1d7

Please sign in to comment.