Added Cyg-Win
This commit is contained in:
parent
82cbc206eb
commit
413c315806
10586 changed files with 3806249 additions and 0 deletions
|
|
@ -0,0 +1,80 @@
|
|||
package Test2::Plugin::BailOnFail;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000162';
|
||||
|
||||
use Test2::API qw/test2_add_callback_context_release/;
|
||||
|
||||
my $LOADED = 0;
|
||||
sub import {
|
||||
return if $LOADED++;
|
||||
|
||||
test2_add_callback_context_release(sub {
|
||||
my $ctx = shift;
|
||||
return if $ctx->hub->is_passing;
|
||||
$ctx->bail("(Bail On Fail)");
|
||||
});
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Plugin::BailOnFail - Automatically bail out of testing on the first test
|
||||
failure.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module will issue a bailout event after the first test failure. This will
|
||||
prevent your tests from continuing. The bailout runs when the context is
|
||||
released; that is, it will run when the test function you are using, such as
|
||||
C<ok()>, returns. This gives the tools the ability to output any extra
|
||||
diagnostics they may need.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test2::V0;
|
||||
use Test2::Plugin::BailOnFail;
|
||||
|
||||
ok(1, "pass");
|
||||
ok(0, "fail");
|
||||
ok(1, "Will not run");
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package Test2::Plugin::DieOnFail;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000162';
|
||||
|
||||
use Test2::API qw/test2_add_callback_context_release/;
|
||||
|
||||
my $LOADED = 0;
|
||||
sub import {
|
||||
return if $LOADED++;
|
||||
|
||||
test2_add_callback_context_release(sub {
|
||||
my $ctx = shift;
|
||||
return if $ctx->hub->is_passing;
|
||||
$ctx->throw("(Die On Fail)");
|
||||
});
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Plugin::DieOnFail - Automatically die on the first test failure.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module will die after the first test failure. This will prevent your tests
|
||||
from continuing. The exception is thrown when the context is released, that is
|
||||
it will run when the test function you are using, such as C<ok()>, returns.
|
||||
This gives the tools the ability to output any extra diagnostics they may need.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test2::V0;
|
||||
use Test2::Plugin::DieOnFail;
|
||||
|
||||
ok(1, "pass");
|
||||
ok(0, "fail");
|
||||
ok(1, "Will not run");
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package Test2::Plugin::ExitSummary;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000162';
|
||||
|
||||
use Test2::API qw/test2_add_callback_exit/;
|
||||
|
||||
my $ADDED_HOOK = 0;
|
||||
sub import { test2_add_callback_exit(\&summary) unless $ADDED_HOOK++ }
|
||||
|
||||
sub active { $ADDED_HOOK }
|
||||
|
||||
sub summary {
|
||||
my ($ctx, $real, $new) = @_;
|
||||
|
||||
# Avoid double-printing diagnostics if Test::Builder already loaded.
|
||||
return if $INC{'Test/Builder.pm'};
|
||||
|
||||
my $hub = $ctx->hub;
|
||||
my $plan = $hub->plan;
|
||||
my $count = $hub->count;
|
||||
my $failed = $hub->failed;
|
||||
|
||||
$ctx->diag('No tests run!') if !$count && (!$plan || $plan ne 'SKIP');
|
||||
$ctx->diag('Tests were run but no plan was declared and done_testing() was not seen.')
|
||||
if $count && !$plan;
|
||||
|
||||
$ctx->diag("Looks like your test exited with $real after test #$count.")
|
||||
if $real;
|
||||
|
||||
$ctx->diag("Did not follow plan: expected $plan, ran $count.")
|
||||
if $plan && $plan =~ m/^[0-9]+$/ && defined $count && $count != $plan;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Plugin::ExitSummary - Add extra diagnostics on failure at the end of the
|
||||
test.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This will provide some diagnostics after a failed test. These diagnostics can
|
||||
range from telling you how you deviated from your plan, warning you if there
|
||||
was no plan, etc. People used to L<Test::More> generally expect these
|
||||
diagnostics.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test2::Plugin::ExitSummary;
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
167
Agent-Windows/OGP64/usr/share/perl5/5.40/Test2/Plugin/SRand.pm
Normal file
167
Agent-Windows/OGP64/usr/share/perl5/5.40/Test2/Plugin/SRand.pm
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
package Test2::Plugin::SRand;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000162';
|
||||
|
||||
use Carp qw/carp/;
|
||||
|
||||
use Test2::API qw{
|
||||
context
|
||||
test2_add_callback_post_load
|
||||
test2_add_callback_exit
|
||||
test2_stack
|
||||
};
|
||||
|
||||
my $ADDED_HOOK = 0;
|
||||
my $SEED;
|
||||
my $FROM;
|
||||
|
||||
sub seed { $SEED }
|
||||
sub from { $FROM }
|
||||
|
||||
sub import {
|
||||
my $class = shift;
|
||||
|
||||
carp "SRand loaded multiple times, re-seeding rand"
|
||||
if defined $SEED;
|
||||
|
||||
if (@_ == 1) {
|
||||
($SEED) = @_;
|
||||
$FROM = 'import arg';
|
||||
}
|
||||
elsif (@_ == 2 and $_[0] eq 'seed') {
|
||||
$SEED = $_[1];
|
||||
$FROM = 'import arg';
|
||||
}
|
||||
elsif(exists $ENV{T2_RAND_SEED}) {
|
||||
$SEED = $ENV{T2_RAND_SEED};
|
||||
$FROM = 'environment variable';
|
||||
}
|
||||
else {
|
||||
my @ltime = localtime;
|
||||
# Yes, this would be an awful seed if you actually wanted randomness.
|
||||
# The idea here is that we want "random" behavior to be predictable
|
||||
# within a given day. This allows you to reproduce failures that may or
|
||||
# may not happen due to randomness.
|
||||
$SEED = sprintf('%04d%02d%02d', 1900 + $ltime[5], 1 + $ltime[4], $ltime[3]);
|
||||
$FROM = 'local date';
|
||||
}
|
||||
|
||||
$SEED = 0 unless $SEED;
|
||||
srand($SEED);
|
||||
|
||||
if ($ENV{HARNESS_IS_VERBOSE} || !$ENV{HARNESS_ACTIVE}) {
|
||||
# If the harness is verbose then just display the message for all to
|
||||
# see. It is nice info and they already asked for noisy output.
|
||||
|
||||
test2_add_callback_post_load(sub {
|
||||
test2_stack()->top; # Ensure we have at least 1 hub.
|
||||
my ($hub) = test2_stack()->all;
|
||||
$hub->send(
|
||||
Test2::Event::Note->new(
|
||||
trace => Test2::Util::Trace->new(frame => [__PACKAGE__, __FILE__, __LINE__, 'SRAND']),
|
||||
message => "Seeded srand with seed '$SEED' from $FROM.",
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
elsif (!$ADDED_HOOK++) {
|
||||
# The seed can be important for debugging, so if anything is wrong we
|
||||
# should output the seed message as a diagnostics message. This must be
|
||||
# done at the very end, even later than a hub hook.
|
||||
test2_add_callback_exit(
|
||||
sub {
|
||||
my ($ctx, $real, $new) = @_;
|
||||
|
||||
$ctx->diag("Seeded srand with seed '$SEED' from $FROM.")
|
||||
if $real
|
||||
|| ($new && $$new)
|
||||
|| !$ctx->hub->is_passing;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Plugin::SRand - Control the random seed for more controlled test
|
||||
environments.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module gives you control over the random seed used for your unit tests. In
|
||||
some testing environments the random seed can play a major role in results.
|
||||
|
||||
The default configuration for this module will seed srand with the local date.
|
||||
Using the date as the seed means that on any given day the random seed will
|
||||
always be the same, this means behavior will not change from run to run on a
|
||||
given day. However the seed is different on different days allowing you to be
|
||||
sure the code still works with actual randomness.
|
||||
|
||||
The seed is printed for you on failure, or when the harness is verbose. You can
|
||||
use the C<T2_RAND_SEED> environment variable to specify the seed. You can also
|
||||
provide a specific seed as a load-time argument to the plugin.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Loading the plugin is easy, and the defaults are sane:
|
||||
|
||||
use Test2::Plugin::SRand;
|
||||
|
||||
Custom seed:
|
||||
|
||||
use Test2::Plugin::SRand seed => 42;
|
||||
|
||||
=head1 NOTE ON LOAD ORDER
|
||||
|
||||
If you use this plugin you probably want to use it as the first, or near-first
|
||||
plugin. C<srand> is not called until the plugin is loaded, so other plugins
|
||||
loaded first may already be making use of random numbers before your seed
|
||||
takes effect.
|
||||
|
||||
=head1 CAVEATS
|
||||
|
||||
When srand is on (default) it can cause problems with things like L<File::Temp>
|
||||
which will end up attempting the same "random" filenames for every test process
|
||||
started on a given day (or sharing the same seed).
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
129
Agent-Windows/OGP64/usr/share/perl5/5.40/Test2/Plugin/Times.pm
Normal file
129
Agent-Windows/OGP64/usr/share/perl5/5.40/Test2/Plugin/Times.pm
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package Test2::Plugin::Times;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test2::Util::Times qw/render_bench render_duration/;
|
||||
|
||||
use Test2::API qw{
|
||||
test2_add_callback_exit
|
||||
};
|
||||
|
||||
use Time::HiRes qw/time/;
|
||||
|
||||
our $VERSION = '0.000162';
|
||||
|
||||
my $ADDED_HOOK = 0;
|
||||
my $START;
|
||||
sub import {
|
||||
return if $ADDED_HOOK++;
|
||||
|
||||
$START = time;
|
||||
test2_add_callback_exit(\&send_time_event);
|
||||
}
|
||||
|
||||
sub send_time_event {
|
||||
my ($ctx, $real, $new) = @_;
|
||||
my $stop = time;
|
||||
my @times = times();
|
||||
|
||||
my $summary = render_bench($START, $stop, @times);
|
||||
my $duration = render_duration($START, $stop);
|
||||
|
||||
my $e = $ctx->send_ev2(
|
||||
about => {package => __PACKAGE__, details => $summary},
|
||||
info => [{tag => 'TIME', details => $summary}],
|
||||
times => {
|
||||
details => $summary,
|
||||
start => $START,
|
||||
stop => $stop,
|
||||
user => $times[0],
|
||||
sys => $times[1],
|
||||
cuser => $times[2],
|
||||
csys => $times[3],
|
||||
},
|
||||
harness_job_fields => [
|
||||
{name => "time_duration", details => $duration},
|
||||
{name => "time_user", details => $times[0]},
|
||||
{name => "time_sys", details => $times[1]},
|
||||
{name => "time_cuser", details => $times[2]},
|
||||
{name => "time_csys", details => $times[3]},
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Plugin::Times - Output timing data at the end of the test.
|
||||
|
||||
=head1 CAVEAT
|
||||
|
||||
It is important to note that this timing data does not include global
|
||||
destruction. This data is only collected up until the point done_testing() is
|
||||
called. If your program takes time for END blocks, garbage collection, and
|
||||
similar, then this timing data will fall short of reality.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This plugin will output a diagnostics message at the end of testing that tells
|
||||
you how much time elapsed, and how hard the system worked on the test.
|
||||
|
||||
This will produce a string like one of these (Note these numbers are completely
|
||||
made up). I<Which string is used depends on the time elapsed.>
|
||||
|
||||
0.12345s on wallclock (0.05 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.05 CPU)
|
||||
|
||||
11.1234s on wallclock (0.05 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.05 CPU)
|
||||
|
||||
01m:54.45s on wallclock (0.05 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.05 CPU)
|
||||
|
||||
18h:22m:54.45s on wallclock (0.05 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.05 CPU)
|
||||
|
||||
04d:18h:22m:54.45s on wallclock (0.05 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.05 CPU)
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test2::Plugin::Times;
|
||||
|
||||
This is also useful at the command line for 1-time use:
|
||||
|
||||
$ perl -MTest2::Plugin::Times path/to/test.t
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
132
Agent-Windows/OGP64/usr/share/perl5/5.40/Test2/Plugin/UTF8.pm
Normal file
132
Agent-Windows/OGP64/usr/share/perl5/5.40/Test2/Plugin/UTF8.pm
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
package Test2::Plugin::UTF8;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000162';
|
||||
|
||||
use Carp qw/croak/;
|
||||
|
||||
use Test2::API qw{
|
||||
test2_add_callback_post_load
|
||||
test2_stack
|
||||
};
|
||||
|
||||
my $LOADED = 0;
|
||||
|
||||
sub import {
|
||||
my $class = shift;
|
||||
|
||||
my $import_utf8 = 1;
|
||||
while ( my $arg = shift @_ ) {
|
||||
croak "Unsupported import argument '$arg'" unless $arg eq 'encoding_only';
|
||||
$import_utf8 = 0;
|
||||
}
|
||||
|
||||
# Load and import UTF8 into the caller.
|
||||
if ( $import_utf8 ) {
|
||||
require utf8;
|
||||
utf8->import;
|
||||
}
|
||||
|
||||
return if $LOADED++; # do not add multiple hooks
|
||||
|
||||
# Set the output formatters to use utf8
|
||||
test2_add_callback_post_load(sub {
|
||||
my $stack = test2_stack;
|
||||
$stack->top; # Make sure we have at least 1 hub
|
||||
|
||||
my $warned = 0;
|
||||
for my $hub ($stack->all) {
|
||||
my $format = $hub->format || next;
|
||||
|
||||
unless ($format->can('encoding')) {
|
||||
warn "Could not apply UTF8 to unknown formatter ($format)\n" unless $warned++;
|
||||
next;
|
||||
}
|
||||
|
||||
$format->encoding('utf8');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Plugin::UTF8 - Test2 plugin to test with utf8.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
When used, this plugin will make tests work with utf8. This includes
|
||||
turning on the utf8 pragma and updating the Test2 output formatter to
|
||||
use utf8.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test2::Plugin::UTF8;
|
||||
|
||||
This is similar to:
|
||||
|
||||
use utf8;
|
||||
BEGIN {
|
||||
require Test2::Tools::Encoding;
|
||||
Test2::Tools::Encoding::set_encoding('utf8');
|
||||
}
|
||||
|
||||
You can also disable the utf8 import by using 'encoding_only' to only enable
|
||||
utf8 encoding on the output format.
|
||||
|
||||
use Test2::Plugin::UTF8 qw(encoding_only);
|
||||
|
||||
=head1 import options
|
||||
|
||||
=head2 encoding_only
|
||||
|
||||
Does not import utf8 in your test and only enables the encoding mode on the output.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
This module currently sets output handles to have the ':utf8' output
|
||||
layer. Some might prefer ':encoding(utf-8)' which is more strict about
|
||||
verifying characters. There is a debate about whether or not encoding
|
||||
to utf8 from perl internals can ever fail, so it may not matter. This
|
||||
was also chosen because the alternative causes threads to segfault,
|
||||
see L<perlbug 31923|https://rt.perl.org/Public/Bug/Display.html?id=31923>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue