File Coverage

inc/Test2/Plugin/INC_Jail.pm
Criterion Covered Total %
statement 31 31 100.0
branch 12 16 75.0
condition n/a
subroutine 6 6 100.0
pod n/a
total 49 53 92.4


line stmt bran cond sub pod time code
1             package Test2::Plugin::INC_Jail;
2              
3 7     7   13541 use 5.008001;
  7         28  
4              
5 7     7   39 use strict;
  7         12  
  7         221  
6 7     7   33 use warnings;
  7         13  
  7         545  
7              
8 7     7   44 use Carp;
  7         14  
  7         3278  
9              
10             our $VERSION = '0.009';
11              
12             sub import {
13 7     7   79 my ( undef, $test_class, @test_inc ) = @_;
14              
15 7         21 my $caller = caller;
16              
17 7 100       32 unless ( defined $test_class ) {
18 6 50       84 my $code = $caller->can( 'CLASS' )
19             or croak 'No test class specified and caller does not define CLASS';
20 6         26 $test_class = $code->();
21             }
22              
23             @test_inc
24 7 50       26 or push @test_inc, 't/lib';
25 7         20 foreach ( @test_inc ) {
26             -d
27 7 50       176 or croak "Test module directory $_ not found";
28             }
29              
30             unshift @INC, sub {
31              
32 214     214   1380320 my $lvl = 0;
33              
34 214         1101 while ( my $pkg = caller $lvl ) {
35              
36 328 100       735 if ( $test_class eq $pkg ) {
37 19         47 foreach my $dir ( @test_inc ) {
38 19         26 my $fh;
39 19 50       5114 open $fh, '<', "$dir/$_[1]"
    100          
40             and return $] ge '5.020' ? ( \'', $fh ) : $fh;
41             }
42 9         2056 croak "Can't locate $_[1] in \@INC";
43             }
44              
45             # The reason we have to iterate if the package is our
46             # original caller is that the module under test might be
47             # loading the requested module on behalf of said caller by
48             # doing a stringy eval in the caller's name space.
49 309 100       109596 $caller eq $pkg
50             or return;
51              
52             } continue {
53 122         274 $lvl++;
54             }
55 8         4696 return;
56 7         49 };
57              
58 7         280 return;
59             }
60              
61             1;
62              
63             __END__
64              
65             =head1 NAME
66              
67             Test2::Plugin::INC_Jail - Create an @INC jail for the module under test
68              
69             =head1 SYNOPSIS
70              
71             use Test2::V0 -target => 'My::Module::Under::Test';
72            
73             # The following defaults the module under test to CLASS, and the
74             # directory containing the modules it loads to t/lib
75             use Test2::Plugin::INC_Jail;
76            
77             # The following will be found anywhere in @INC except t/lib
78             use Test2::Tools::Explain; # Comes from anywhere in @INC
79            
80             # Test::Module will be found, if at all, ONLY in t/lib
81             CLASS->do_something_that_loads( 'Test::Module' );
82              
83             =head1 DESCRIPTION
84              
85             This module is B<private> to the C<Test2-Tools-LoadModule> distribution.
86             It can be changed or revoked at any time. It is written as a
87             C<Test2::Plugin> simply as a feasability study.
88              
89             This module creates an @INC jail for the module under test.
90              
91             When you C<use()> this module you can specify arguments.
92              
93             The first is the name of the module under test. If undefined, this
94             defaults to the value of C<CLASS> found in the script that loaded this
95             module. If C<CLASS> is not found an exception is thrown.
96              
97             The second and subsequent arguments are the names of directories
98             containing modules to be loaded by the module under test. If
99             unspecified, this defaults to F<t/lib/>. If any of the directories do
100             not exist, an exception is thrown.
101              
102             Modules loaded by the module under test can come only from the specified
103             directory. Modules loaded by anyone else can never come from the
104             specified directory.
105              
106             B<Note> that this plug-in does not implement a way to get out of jail.
107             If you need this, open a block, localize C<@INC>, and close the block
108             when you are done:
109              
110             {
111             local @INC = @INC;
112             use Test2::Plugin::INC_Jail;
113            
114             # Any tests requiring the jail.
115            
116             }
117            
118             # @INC is now back the way it was before.
119              
120             =head1 SEE ALSO
121              
122             L<Test2::V0|Test2::V0>.
123              
124             =head1 SUPPORT
125              
126             Support is by the author. Please file bug reports at
127             L<https://rt.cpan.org/Public/Dist/Display.html?Name=Test2-Tools-LoadModule>,
128             L<https://github.com/trwyant/perl-Test2-Tools-LoadModule/issues>, or in
129             electronic mail to the author.
130              
131             =head1 AUTHOR
132              
133             Thomas R. Wyant, III F<wyant at cpan dot org>
134              
135             =head1 COPYRIGHT AND LICENSE
136              
137             Copyright (C) 2020-2026 by Thomas R. Wyant, III
138              
139             This program is free software; you can redistribute it and/or modify it
140             under the same terms as Perl 5.10.0. For more details, see the full text
141             of the licenses in the files F<LICENSE-Artistic> and F<LICENSE-GPL>.
142              
143             This program is distributed in the hope that it will be useful, but
144             without any warranty; without even the implied warranty of
145             merchantability or fitness for a particular purpose.
146              
147             =cut
148              
149             # ex: set textwidth=72 :