Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions lib/T2.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package T2;
use strict;
use warnings;

my $INIT;
my $HANDLE;
sub handle { $HANDLE }

sub import {
my $class = shift;
my ($handle) = @_;

my ($caller, $file, $line) = caller;

die "The ${ \__PACKAGE__ } namespace has already been initialized (Originally initiated at $INIT->[1] line $INIT->[2]) at $file line $line.\n"
if $INIT;

unless ($handle) {
die "The '$caller' package does not provide a T2 handler at $file line $line.\n"
unless $caller->can('T2');

$handle = $caller->T2 or die "Could not get handle via '$caller\->T2()' at $file line $line.\n";
}

die "'$handle' is not a Test2::Handle instance at $file line $line.\n"
unless $handle->isa('Test2::Handle');

$INIT = [$caller, $file, $line];
$HANDLE = $handle;

for my $sym ($HANDLE->HANDLE_SUBS) {
next if $sym eq 'import';
next if $sym eq 'handle';

my $code = $HANDLE->HANDLE_NAMESPACE->can($sym);
my $proto = prototype($code);

my $header = defined($proto) ? "sub $sym($proto) {" : "sub $sym {";

my $line = __LINE__ + 3;
my $sub = eval <<" EOT" or die $@;
#line $line ${ \__FILE__ }
$header
my (\$f) = \@_;
shift if \$f && "\$f" eq "$class";
goto &\$code;
};

\\&$sym;
EOT

no strict 'refs';
*$sym = $sub;
}
}

sub AUTOLOAD {
my ($this) = @_;

if ($this) {
shift if "$this" eq 'T2';
shift if ref($this) eq 'T2';
}

my ($name) = (our $AUTOLOAD =~ m/^(?:.*::)?([^:]+)$/);

my @caller = caller;
my $sub = $HANDLE->HANDLE_NAMESPACE->can($name) or die qq{"$name" is not provided by this T2 handle at $caller[1] line $caller[2].\n};
goto &$sub;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

T2 - Define the L<T2> namespace that can always be used to access functionality
from a Test2 bundle such as L<Test2::V1>.

=head1 DESCRIPTION

If you want a global C<T2> that can be called from anywhere, without needing to
import L<Test2::V1> in every package, you can do that with the L<T2> module.

This defines the L<T2> namespace so you can always call methods on it like
C<< T2->ok(1, "pass") >> and C<< T2->done_testing >>.

=head1 SYNOPSIS

Create a file/package somewhere to initialize it. Only initialize it once!

package My::Global::T2;

# Load Test2::V1 (or future bundle)
# Add any customizations like including extra tools, overriding tools, etc.
use Test2::V1 ...;

# Load T2, it will find the T2() handle in the current package and make it global
use T2;

#########################################
# Alternatively you can do this:
my $handle = Test2::V1::Handle->new(...);
require T2;
T2->import($handle);

Now use it somewhere in your code:

use My::Global::T2;

Now T2 is available from any package

T2->ok(1, "pass");
T2->ok(0, "fail");

T2->done_testing;

B<Note:> In this case T2 is a package name, not a function, so C<< T2() >> will
not work. However you can import L<Test2::V1> into any package providing a T2()
function that will be used preferentially to the L<T2> namespace.

B<Bonus:> You can use the C<T2::tool(...)> form to leverage the original
prototype of the tool.

T2::is(@foo, 3, "Array has 3 elements");

Without the prototype (method form does not allow prototypes) you would have to
prefix scalar on C<@foo>:

T2->is(scalar(@foo), 3, "Array matches expections");

=head1 SOURCE

The source code repository for Test2-Suite can be found at
F<https://github.com/Test-More/test-more/>.

=head1 MAINTAINERS

=over 4

=item Chad Granum E<lt>exodist@cpan.orgE<gt>

=back

=head1 AUTHORS

=over 4

=item Chad Granum E<lt>exodist@cpan.orgE<gt>

=back

=head1 COPYRIGHT

Copyright Chad Granum E<lt>exodist@cpan.orgE<gt>.

This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

See F<http://dev.perl.org/licenses/>

=cut
2 changes: 1 addition & 1 deletion lib/Test2/API/InterceptResult.pm
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ needing a deep understanding of the event/facet model.
Usually you get an instance of this class when you use C<intercept()> from
L<Test2::API>.

use Test2::V0;
use Test2::V1 '-iPp';
use Test2::API qw/intercept/;

my $events = intercept {
Expand Down
2 changes: 1 addition & 1 deletion lib/Test2/API/InterceptResult/Event.pm
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ you to use when testing your test tools.

=head1 SYNOPSIS

use Test2::V0;
use Test2::V1 '-iPp';
use Test2::API qw/intercept/;

my $events = intercept {
Expand Down
2 changes: 2 additions & 0 deletions lib/Test2/Bundle/Extended.pm
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Test2::Bundle::Extended - Old name for Test2::V0
This bundle has been renamed to L<Test2::V0>, in which the C<':v1'> tag has
been removed as unnecessary.

B<Note:> L<Test2::V1> is the latest bundle, you probably want to look at that.

=head1 DESCRIPTION

This is the big-daddy bundle. This bundle includes nearly every tool, and
Expand Down
Loading
Loading