line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Class::Moose::Runner; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# ABSTRACT: Runner for Test::Class::Moose tests |
4
|
|
|
|
|
|
|
|
5
|
32
|
|
|
32
|
|
932182
|
use strict; |
|
32
|
|
|
|
|
114
|
|
|
32
|
|
|
|
|
1100
|
|
6
|
32
|
|
|
32
|
|
218
|
use warnings; |
|
32
|
|
|
|
|
80
|
|
|
32
|
|
|
|
|
1002
|
|
7
|
32
|
|
|
32
|
|
2658
|
use namespace::autoclean; |
|
32
|
|
|
|
|
93131
|
|
|
32
|
|
|
|
|
246
|
|
8
|
|
|
|
|
|
|
|
9
|
32
|
|
|
32
|
|
2901
|
use 5.010000; |
|
32
|
|
|
|
|
129
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.99'; |
12
|
|
|
|
|
|
|
|
13
|
32
|
|
|
32
|
|
3265
|
use Moose 2.0000; |
|
32
|
|
|
|
|
2395375
|
|
|
32
|
|
|
|
|
266
|
|
14
|
32
|
|
|
32
|
|
237954
|
use Carp; |
|
32
|
|
|
|
|
96
|
|
|
32
|
|
|
|
|
2607
|
|
15
|
|
|
|
|
|
|
|
16
|
32
|
|
|
32
|
|
4317
|
use Test::Class::Moose::Config; |
|
32
|
|
|
|
|
86
|
|
|
32
|
|
|
|
|
17380
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
has 'test_configuration' => ( |
19
|
|
|
|
|
|
|
is => 'ro', |
20
|
|
|
|
|
|
|
isa => 'Test::Class::Moose::Config', |
21
|
|
|
|
|
|
|
); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has 'jobs' => ( |
24
|
|
|
|
|
|
|
is => 'ro', |
25
|
|
|
|
|
|
|
isa => 'Int', |
26
|
|
|
|
|
|
|
default => 1, |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
has 'show_parallel_progress' => ( |
30
|
|
|
|
|
|
|
is => 'ro', |
31
|
|
|
|
|
|
|
isa => 'Bool', |
32
|
|
|
|
|
|
|
default => 1, |
33
|
|
|
|
|
|
|
); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
has 'color_output' => ( |
36
|
|
|
|
|
|
|
is => 'ro', |
37
|
|
|
|
|
|
|
isa => 'Bool', |
38
|
|
|
|
|
|
|
default => 1, |
39
|
|
|
|
|
|
|
); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
has 'executor_roles' => ( |
42
|
|
|
|
|
|
|
traits => ['Array'], |
43
|
|
|
|
|
|
|
is => 'ro', |
44
|
|
|
|
|
|
|
isa => 'ArrayRef[RoleName]', |
45
|
|
|
|
|
|
|
default => sub { [] }, |
46
|
|
|
|
|
|
|
handles => { |
47
|
|
|
|
|
|
|
_has_executor_roles => 'count', |
48
|
|
|
|
|
|
|
}, |
49
|
|
|
|
|
|
|
); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
has '_executor' => ( |
52
|
|
|
|
|
|
|
is => 'ro', |
53
|
|
|
|
|
|
|
init_arg => undef, |
54
|
|
|
|
|
|
|
lazy_build => 1, |
55
|
|
|
|
|
|
|
handles => [ 'runtests', 'test_classes', 'test_report' ], |
56
|
|
|
|
|
|
|
); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
my %config_attrs = map { $_->init_arg => 1 } |
59
|
|
|
|
|
|
|
Test::Class::Moose::Config->meta->get_all_attributes; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
around BUILDARGS => sub { |
62
|
|
|
|
|
|
|
my $orig = shift; |
63
|
|
|
|
|
|
|
my $class = shift; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
my $p = $class->$orig(@_); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
my %config_p = map { $config_attrs{$_} ? ( $_ => delete $p->{$_} ) : () } |
68
|
|
|
|
|
|
|
keys %{$p}; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
$p->{test_configuration} ||= Test::Class::Moose::Config->new(%config_p); |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
return $p; |
73
|
|
|
|
|
|
|
}; |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub _build__executor { |
76
|
35
|
|
|
35
|
|
154
|
my $self = shift; |
77
|
|
|
|
|
|
|
|
78
|
35
|
|
|
|
|
91
|
my $executor; |
79
|
35
|
100
|
|
|
|
1146
|
if ( $self->jobs == 1 ) { |
80
|
24
|
|
|
|
|
10875
|
require Test::Class::Moose::Executor::Sequential; |
81
|
24
|
|
|
|
|
993
|
$executor = Test::Class::Moose::Executor::Sequential->new( |
82
|
|
|
|
|
|
|
test_configuration => $self->test_configuration ); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
else { |
85
|
11
|
|
|
|
|
9240
|
require Test::Class::Moose::Executor::Parallel; |
86
|
11
|
|
|
|
|
495
|
$executor = Test::Class::Moose::Executor::Parallel->new( |
87
|
|
|
|
|
|
|
test_configuration => $self->test_configuration, |
88
|
|
|
|
|
|
|
jobs => $self->jobs, |
89
|
|
|
|
|
|
|
color_output => $self->color_output, |
90
|
|
|
|
|
|
|
show_parallel_progress => $self->show_parallel_progress, |
91
|
|
|
|
|
|
|
); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
35
|
100
|
|
|
|
1574
|
return $executor unless $self->_has_executor_roles; |
95
|
|
|
|
|
|
|
|
96
|
1
|
|
|
|
|
7
|
require Moose::Util; |
97
|
1
|
|
|
|
|
3
|
Moose::Util::apply_all_roles( $executor, @{ $self->executor_roles } ); |
|
1
|
|
|
|
|
45
|
|
98
|
|
|
|
|
|
|
|
99
|
1
|
|
|
|
|
7104
|
return $executor; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
1; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
__END__ |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=pod |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=encoding UTF-8 |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=head1 NAME |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
Test::Class::Moose::Runner - Runner for Test::Class::Moose tests |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 VERSION |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
version 0.99 |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head1 SYNOPSIS |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
use Test::Class::Moose::Load 't/lib'; |
123
|
|
|
|
|
|
|
use Test::Class::Moose::Runner; |
124
|
|
|
|
|
|
|
Test::Class::Moose::Runner->new->runtests; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head1 DESCRIPTION |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
This class is responsible for running tests. Internally, most of the work is |
129
|
|
|
|
|
|
|
done by either a C<Test::Class::Moose::Executor::Sequential> or |
130
|
|
|
|
|
|
|
C<Test::Class::Moose::Executor::Parallel> object. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=head1 LOADING TESTS |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
We I<strongly> recommend using the L<Test::Class::Moose::Load> driver for your |
135
|
|
|
|
|
|
|
test suite. Simply point it at the directory or directories containing your |
136
|
|
|
|
|
|
|
test classes: |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
use Test::Class::Moose::Load 't/lib'; |
139
|
|
|
|
|
|
|
use Test::Class::Moose::Runner; |
140
|
|
|
|
|
|
|
Test::Class::Moose::Runner->new->runtests; |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
By running your C<Test::Class::Moose> tests with a single driver script like |
143
|
|
|
|
|
|
|
this, all classes are loaded once and this can be a significant performance |
144
|
|
|
|
|
|
|
boost. This does mean a global state will be shared, so keep this in mind. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head1 CONSTRUCTOR ATTRIBUTES |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=over 4 |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item * C<show_timing> |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Boolean. Will display verbose information on the amount of time it takes each |
153
|
|
|
|
|
|
|
test class/test method to run. Defaults to false, but see C<use_environment>. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item * C<set_process_name> |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Boolean. If this is true, then C<$0> will be updated to include the test |
158
|
|
|
|
|
|
|
instance name for each test instance as it is run, and then further updated as |
159
|
|
|
|
|
|
|
each test control method and test method are run, This can be helpful when |
160
|
|
|
|
|
|
|
debugging hanging tests. Defaults to false. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=item * C<statistics> |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Boolean. Will display number of classes, test methods and tests run. Defaults |
165
|
|
|
|
|
|
|
to false, but see C<use_environment>. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=item * C<use_environment> |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
If this is true, then the default value for show_timing and statistics will be |
170
|
|
|
|
|
|
|
true if the C<HARNESS_IS_VERBOSE> environment variable is true. This is set |
171
|
|
|
|
|
|
|
when running C<prove -v ...>, for example. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=item * C<jobs> |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
This defaults to 1. If you set this to a larger number than test instances will |
176
|
|
|
|
|
|
|
be run in parallel. See the L</PARALLEL RUNNING> section below for more |
177
|
|
|
|
|
|
|
details. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item * C<show_parallel_progress> |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
This defaults to 1. This only impacts the output when running tests in |
182
|
|
|
|
|
|
|
parallel. If this is true then when running tests in parallel the runner will |
183
|
|
|
|
|
|
|
output one dot per class being executed. This makes it clear that the test |
184
|
|
|
|
|
|
|
suite is not stuck. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
However, this output can cause issues with things like the |
187
|
|
|
|
|
|
|
L<TAP::Harness::Archive> module, so you can disable it if needed. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=item * C<color_output> |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
This defaults to 1. This only impacts the output when running tests in |
192
|
|
|
|
|
|
|
parallel. If this is true then parallel test progress output will use ANSI |
193
|
|
|
|
|
|
|
coloring to indicate each class's pass/fail status. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item * C<randomize> |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Boolean. Will run test methods in a random order. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item * C<randomize_classes> |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Boolean. Will run test classes in a random order. Note that if you specify an |
202
|
|
|
|
|
|
|
explicit list of classes in C<test_classes>, these classes will be run in the |
203
|
|
|
|
|
|
|
order you specify. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item * C<test_classes> |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Takes a class name or an array reference of class names. If it is present, only |
208
|
|
|
|
|
|
|
these test classes will be run. This is very useful if you wish to run an |
209
|
|
|
|
|
|
|
individual class as a test: |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
My::Base::Class->new( |
212
|
|
|
|
|
|
|
test_classes => $ENV{TEST_CLASS}, # ignored if undef |
213
|
|
|
|
|
|
|
)->runtests; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
You can also achieve this effect by writing a subclass and overriding the |
216
|
|
|
|
|
|
|
C<test_classes> method, but this makes it trivial to do this: |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
TEST_CLASS=TestsFor::Our::Company::Invoice prove -lv t/test_classes.t |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Alternatively: |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
My::Base::Class->new( |
223
|
|
|
|
|
|
|
test_classes => \@ARGV, # ignored if empty |
224
|
|
|
|
|
|
|
)->runtests; |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
That lets you use the arisdottle to provide arguments to your test driver |
227
|
|
|
|
|
|
|
script: |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
prove -lv t/test_classes.t :: TestsFor::Our::Company::Invoice TestsFor::Something::Else |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=item * C<include> |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Regex. If present, only test methods whose name matches C<include> will be |
234
|
|
|
|
|
|
|
included. B<However>, they must still start with C<test_>. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
For example: |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
my $test_suite = Test::Class::Moose->new({ |
239
|
|
|
|
|
|
|
include => qr/customer/, |
240
|
|
|
|
|
|
|
}); |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
The above constructor will let you match test methods named C<test_customer> |
243
|
|
|
|
|
|
|
and C<test_customer_account>, but will not suddenly match a method named |
244
|
|
|
|
|
|
|
C<default_customer>. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
By enforcing the leading C<test_> behavior, we don't surprise developers who |
247
|
|
|
|
|
|
|
are trying to figure out why C<default_customer> is being run as a test. This |
248
|
|
|
|
|
|
|
means an C<include> such as C<< /^customer.*/ >> will never run any tests. |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=item * C<exclude> |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
Regex. If present, only test methods whose names don't match C<exclude> will be |
253
|
|
|
|
|
|
|
included. B<However>, they must still start with C<test_>. See C<include>. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=item * C<include_tags> |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Array ref of strings matching method tags (a single string is also ok). If |
258
|
|
|
|
|
|
|
present, only test methods whose tags match C<include_tags> or whose tags don't |
259
|
|
|
|
|
|
|
match C<exclude_tags> will be included. B<However>, they must still start with |
260
|
|
|
|
|
|
|
C<test_>. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
For example: |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
my $test_suite = Test::Class::Moose->new({ |
265
|
|
|
|
|
|
|
include_tags => [qw/api database/], |
266
|
|
|
|
|
|
|
}); |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
The above constructor will only run tests tagged with C<api> or C<database>. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item * C<exclude_tags> |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
The same as C<include_tags>, but will exclude the tests rather than include |
273
|
|
|
|
|
|
|
them. For example, if your network is down: |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my $test_suite = Test::Class::Moose->new({ |
276
|
|
|
|
|
|
|
exclude_tags => [ 'network' ], |
277
|
|
|
|
|
|
|
}); |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# or |
280
|
|
|
|
|
|
|
my $test_suite = Test::Class::Moose->new({ |
281
|
|
|
|
|
|
|
exclude_tags => 'network', |
282
|
|
|
|
|
|
|
}); |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item * C<executor_roles> |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
An array reference containing one or more roles to be applied to the executor |
287
|
|
|
|
|
|
|
object. This allows you to apply plugins on top of the normal TCM behavior. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
See the L<Test::Class::Moose::Role::Executor> docs for details of what methods |
290
|
|
|
|
|
|
|
you can modify as part of such roles. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=back |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=head1 METHODS |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
In addition to the C<new> method, this class provides several additional |
297
|
|
|
|
|
|
|
public methods |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head2 C<< $runner->runtests >> |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
This method runs your tests. It accepts no arguments. |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head2 C<< $runner->test_configuration >> |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
This returns a L<Test::Class::Moose::Config> for the runner. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
Most of the attributes passed to the runner are actually available in a |
308
|
|
|
|
|
|
|
L<Test::Class::Moose::Config> rather than the runner itself. This may change in |
309
|
|
|
|
|
|
|
a future release, in which case this method will simply return the runner |
310
|
|
|
|
|
|
|
itself for backwards compatibility. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head2 C<< $runner->test_report >> |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
This returns a L<Test::Class::Moose::Report> for the runner. After running |
315
|
|
|
|
|
|
|
tests you can use this object to get information about the test run. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head1 PARALLEL RUNNING |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Running tests in parallel requires you to have L<Parallel::ForkManager> |
320
|
|
|
|
|
|
|
installed. This is not a prereq of this distro so you will need to install |
321
|
|
|
|
|
|
|
manually. |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
To run tests in parallel, simply pass a value greater than 1 for the C<jobs> |
324
|
|
|
|
|
|
|
parameter when creating a runner object: |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Test::Class::Moose::Runner->new( jobs => 4 )->runtests; |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
Your test classes will be run in parallel in separate child processes. Test |
329
|
|
|
|
|
|
|
classes are parallelized on a B<per instance basis>. This means that each child |
330
|
|
|
|
|
|
|
process constructs a single instance of a test class and runs all of the |
331
|
|
|
|
|
|
|
methods belonging to that class. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
If you are using parameterized test instances (see the L<Test::Class::Moose> |
334
|
|
|
|
|
|
|
docs for details) then the same class may have instances running in different |
335
|
|
|
|
|
|
|
child processes. |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
If any of the methods in a class are marked with the C<noparallel> tag, then |
338
|
|
|
|
|
|
|
that class will be not be run in a child process. All test classes which can't |
339
|
|
|
|
|
|
|
be run in parallel are run sequentially after all parallelizable classes have |
340
|
|
|
|
|
|
|
run. |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=head1 SUPPORT |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
Bugs may be submitted at L<https://github.com/houseabsolute/test-class-moose/issues>. |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>. |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=head1 SOURCE |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
The source code repository for Test-Class-Moose can be found at L<https://github.com/houseabsolute/test-class-moose>. |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=head1 AUTHORS |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=over 4 |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=item * |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
Curtis "Ovid" Poe <ovid@cpan.org> |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=item * |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
Dave Rolsky <autarch@urth.org> |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=back |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
This software is copyright (c) 2012 - 2021 by Curtis "Ovid" Poe. |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
371
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
The full text of the license can be found in the |
374
|
|
|
|
|
|
|
F<LICENSE> file included with this distribution. |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=cut |