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