File Coverage

blib/lib/Test/Without/Module.pm
Criterion Covered Total %
statement 45 46 97.8
branch 7 8 87.5
condition n/a
subroutine 11 11 100.0
pod 1 5 20.0
total 64 70 91.4


line stmt bran cond sub pod time code
1             package Test::Without::Module;
2 5     5   52857 use strict;
  5         7  
  5         159  
3 5     5   20 use Carp qw( croak );
  5         8  
  5         286  
4              
5 5     5   21 use vars qw( $VERSION );
  5         5  
  5         248  
6             $VERSION = '0.19';
7              
8 5     5   16 use vars qw(%forbidden);
  5         5  
  5         2229  
9              
10             sub get_forbidden_list {
11 48     48 1 16424 \%forbidden
12             };
13              
14             sub import {
15 7     7   2176 my ($self,@forbidden_modules) = @_;
16              
17 7         13 my $forbidden = get_forbidden_list;
18            
19 7         14 for (@forbidden_modules) {
20 4         10 my $file = module2file($_);
21 4         12 $forbidden->{$file} = delete $INC{$file};
22             };
23              
24             # Scrub %INC, so that loaded modules disappear
25 7         13 for my $module (@forbidden_modules) {
26 4         9 scrub( $module );
27             };
28              
29 7 100       15 @INC = (\&fake_module, grep { !ref || $_ != \&fake_module } @INC);
  79         230  
30             };
31              
32             sub fake_module {
33 37     37 0 252218 my ($self,$module_file,$member_only) = @_;
34             # Don't touch $@, or .al files will not load anymore????
35              
36 37 100       71 if (exists get_forbidden_list->{$module_file}) {
37 2         9 my $module_name = file2module($module_file);
38 2         376 croak "Can't locate $module_file in \@INC (you may need to install the $module_name module) (\@INC contains: @INC)";
39             };
40             };
41              
42             sub unimport {
43 2     2   11 my ($self,@list) = @_;
44 2         2 my $module;
45 2         5 my $forbidden = get_forbidden_list;
46              
47 2         3 for $module (@list) {
48 2         3 my $file = module2file($module);
49 2 50       6 if (exists $forbidden->{$file}) {
50 2         3 my $path = delete $forbidden->{$file};
51 2 100       1140 if (defined $path) {
52 1         1037 $INC{ $file } = $path;
53             }
54             } else {
55 0         0 croak "Can't allow non-forbidden module $module";
56             };
57             };
58             };
59              
60             sub file2module {
61 2     2 0 3 my ($mod) = @_;
62 2         9 $mod =~ s!/!::!g;
63 2         8 $mod =~ s!\.pm$!!;
64 2         4 $mod;
65             };
66              
67             sub module2file {
68 10     10 0 13 my ($mod) = @_;
69 10         53 $mod =~ s!::|'!/!g;
70 10         11 $mod .= ".pm";
71 10         20 $mod;
72             };
73              
74             sub scrub {
75 4     4 0 5 my ($module) = @_;
76 4         29 delete $INC{module2file($module)};
77             };
78              
79             1;
80              
81             =head1 NAME
82              
83             Test::Without::Module - Test fallback behaviour in absence of modules
84              
85             =head1 SYNOPSIS
86              
87             =for example begin
88              
89             use Test::Without::Module qw( My::Module );
90              
91             # Now, loading of My::Module fails :
92             eval { require My::Module; };
93             warn $@ if $@;
94              
95             # Now it works again
96             eval q{ no Test::Without::Module qw( My::Module ) };
97             eval { require My::Module; };
98             print "Found My::Module" unless $@;
99              
100             =for example end
101              
102             =head1 DESCRIPTION
103              
104             This module allows you to deliberately hide modules from a program
105             even though they are installed. This is mostly useful for testing modules
106             that have a fallback when a certain dependency module is not installed.
107              
108             =head2 EXPORT
109              
110             None. All magic is done via C and
111             C.
112              
113             =head2 Test::Without::Module::get_forbidden_list
114              
115             This function returns a reference to a copy of the current hash of forbidden
116             modules or an empty hash if none are currently forbidden. This is convenient
117             if you are testing and/or debugging this module.
118              
119             =cut
120              
121             =head1 ONE LINER
122              
123             A neat trick for using this module from the command line
124             was mentioned to me by NUFFIN and by Jerrad Pierce:
125              
126             perl -MTest::Without::Module=Some::Module -w -Iblib/lib t/SomeModule.t
127              
128             That way, you can easily see how your module or test file behaves
129             when a certain module is unavailable.
130              
131             =head1 BUGS
132              
133             =over 4
134              
135             =item *
136              
137             There is no lexical scoping
138              
139             =back
140              
141             =head1 CREDITS
142              
143             Much improvement must be thanked to Aristotle from PerlMonks, he pointed me
144             to a much less convoluted way to fake a module at
145             L.
146              
147             I also discussed with him an even more elegant way of overriding
148             CORE::GLOBAL::require, but the parsing of the overridden subroutine
149             didn't work out the way I wanted it - CORE::require didn't recognize
150             barewords as such anymore.
151              
152             NUFFIN and Jerrad Pierce pointed out the convenient
153             use from the command line to interactively watch the
154             behaviour of the test suite and module in absence
155             of a module.
156              
157             =head1 AUTHOR
158              
159             Copyright (c) 2003-2014 Max Maischein, Ecorion@cpan.orgE
160              
161             =head1 LICENSE
162              
163             This module is released under the same terms as Perl itself.
164              
165             =head1 REPOSITORY
166              
167             The public repository of this module is
168             L.
169              
170             =head1 SUPPORT
171              
172             The public support forum of this module is
173             L.
174              
175             =head1 BUG TRACKER
176              
177             Please report bugs in this module via the RT CPAN bug queue at
178             L
179             or via mail to L.
180              
181             =head1 SEE ALSO
182              
183             L, L, L, L
184              
185             =cut
186              
187             __END__