Skip to content

Commit a730649

Browse files
committed
Proposal for Test2::V1
1 parent 5497eed commit a730649

File tree

11 files changed

+2082
-1
lines changed

11 files changed

+2082
-1
lines changed

lib/T2.pm

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package T2;
2+
use strict;
3+
use warnings;
4+
5+
my $INIT;
6+
my $HANDLE;
7+
sub handle { $HANDLE }
8+
9+
sub import {
10+
my $class = shift;
11+
my ($handle) = @_;
12+
13+
my ($caller, $file, $line) = caller;
14+
15+
die "The ${ \__PACKAGE__ } namespace has already been initialized (Originally initiated at $INIT->[1] line $INIT->[2]) at $file line $line.\n"
16+
if $INIT;
17+
18+
unless ($handle) {
19+
die "The '$caller' package does not provide a T2 handler at $file line $line.\n"
20+
unless $caller->can('T2');
21+
22+
$handle = $caller->T2 or die "Could not get handle via '$caller\->T2()' at $file line $line.\n";
23+
}
24+
25+
die "'$handle' is not a Test2::Handle instance at $file line $line.\n"
26+
unless $handle->isa('Test2::Handle');
27+
28+
$INIT = [$caller, $file, $line];
29+
$HANDLE = $handle;
30+
31+
for my $sym ($HANDLE->HANDLE_SUBS) {
32+
next if $sym eq 'import';
33+
next if $sym eq 'handle';
34+
35+
my $code = $HANDLE->HANDLE_NAMESPACE->can($sym);
36+
my $proto = prototype($code);
37+
38+
my $header = defined($proto) ? "sub $sym($proto) {" : "sub $sym {";
39+
40+
my $line = __LINE__ + 3;
41+
my $sub = eval <<" EOT" or die $@;
42+
#line $line ${ \__FILE__ }
43+
$header
44+
my (\$f) = \@_;
45+
shift if \$f && "\$f" eq "$class";
46+
goto &\$code;
47+
};
48+
49+
\\&$sym;
50+
EOT
51+
52+
no strict 'refs';
53+
*$sym = $sub;
54+
}
55+
}
56+
57+
sub AUTOLOAD {
58+
my ($this) = @_;
59+
60+
if ($this) {
61+
shift if "$this" eq 'T2';
62+
shift if ref($this) eq 'T2';
63+
}
64+
65+
my ($name) = (our $AUTOLOAD =~ m/^(?:.*::)?([^:]+)$/);
66+
67+
my @caller = caller;
68+
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};
69+
goto &$sub;
70+
}
71+
72+
1;
73+
74+
__END__
75+
76+
=pod
77+
78+
=encoding UTF-8
79+
80+
=head1 NAME
81+
82+
T2 - Define the L<T2> namespace that can always be used to access functionality
83+
from a Test2 bundle such as L<Test2::V1>.
84+
85+
=head1 DESCRIPTION
86+
87+
If you want a global C<T2> that can be called from anywhere, without needing to
88+
import L<Test2::V1> in every package, you can do that with the L<T2> module.
89+
90+
This defines the L<T2> namespace so you can always call methods on it like
91+
C<< T2->ok(1, "pass") >> and C<< T2->done_testing >>.
92+
93+
=head1 SYNOPSIS
94+
95+
Create a file/package somewhere to initialize it. Only initialize it once!
96+
97+
package My::Global::T2;
98+
99+
# Load Test2::V1 (or future bundle)
100+
# Add any customizations like including extra tools, overriding tools, etc.
101+
use Test2::V1 ...;
102+
103+
# Load T2, it will find the T2() handle in the current package and make it global
104+
use T2;
105+
106+
#########################################
107+
# Alternatively you can do this:
108+
my $handle = Test2::V1::Handle->new(...);
109+
require T2;
110+
T2->import($handle);
111+
112+
Now use it somewhere in your code:
113+
114+
use My::Global::T2;
115+
116+
Now T2 is available from any package
117+
118+
T2->ok(1, "pass");
119+
T2->ok(0, "fail");
120+
121+
T2->done_testing;
122+
123+
B<Note:> In this case T2 is a package name, not a function, so C<< T2() >> will
124+
not work. However you can import L<Test2::V1> into any package providing a T2()
125+
function that will be used preferentially to the L<T2> namespace.
126+
127+
B<Bonus:> You can use the C<T2::tool(...)> form to leverage the original
128+
prototype of the tool.
129+
130+
T2::is(@foo, 3, "Array has 3 elements");
131+
132+
Without the prototype (method form does not allow prototypes) you would have to
133+
prefix scalar on C<@foo>:
134+
135+
T2->is(scalar(@foo), 3, "Array matches expections");
136+
137+
=head1 SOURCE
138+
139+
The source code repository for Test2-Suite can be found at
140+
F<https://github.com/Test-More/test-more/>.
141+
142+
=head1 MAINTAINERS
143+
144+
=over 4
145+
146+
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
147+
148+
=back
149+
150+
=head1 AUTHORS
151+
152+
=over 4
153+
154+
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
155+
156+
=back
157+
158+
=head1 COPYRIGHT
159+
160+
Copyright Chad Granum E<lt>exodist@cpan.orgE<gt>.
161+
162+
This program is free software; you can redistribute it and/or
163+
modify it under the same terms as Perl itself.
164+
165+
See F<http://dev.perl.org/licenses/>
166+
167+
=cut

0 commit comments

Comments
 (0)