File Coverage

blib/lib/Test/WriteVariants/Context.pm
Criterion Covered Total %
statement 56 123 45.5
branch 4 22 18.1
condition 0 6 0.0
subroutine 18 40 45.0
pod 13 13 100.0
total 91 204 44.6


line stmt bran cond sub pod time code
1             package Test::WriteVariants::Context;
2              
3 4     4   26 use strict;
  4         10  
  4         107  
4 4     4   22 use warnings;
  4         9  
  4         1790  
5              
6             =head1 NAME
7              
8             Test::WriteVariants::Context - representation of test context
9              
10             =head1 DESCRIPTION
11              
12             Contexts are used to abstract e.g. ambience or relations between
13             opportunities and and their application.
14              
15             =head1 METHODS
16              
17             =head2 new
18              
19             A Context is an ordered list of various kinds of named values (such as
20             environment variables, our vars) possibly including other Context objects.
21              
22             Values can be looked up by name. The first match will be returned.
23              
24             =cut
25              
26             my $ContextClass = __PACKAGE__;
27              
28             sub new
29             {
30 13     13 1 24 my $class = shift;
31 13 100       35 $class = ref $class if ref $class;
32 13         69 return bless [@_], $class;
33             }
34              
35             =head2 new_composite
36              
37             see Test::WriteVariants::Context::BaseItem
38              
39             =cut
40              
41 0     0 1 0 sub new_composite { shift->new(@_) } # see Test::WriteVariants::Context::BaseItem
42              
43             =head2 push_var
44              
45             add a var to an existing config
46              
47             =cut
48              
49             sub push_var
50             {
51 0     0 1 0 my ($self, $var) = @_;
52 0         0 push @$self, $var;
53 0         0 return;
54             }
55              
56             sub _new_var
57             {
58 0     0   0 my ($self, $t, $n, $v, %e) = @_;
59 0         0 my $var = $t->new($n, $v, %e);
60 0         0 return $self->new($var); # wrap var item in a context list
61             }
62              
63             =head2 new_env_var
64              
65             instantiates new context using an environment variable
66              
67             =head2 new_our_var
68              
69             instantiates new context using a global variable
70              
71             =head2 new_module_use
72              
73             instantiates new context using a module
74              
75             =head2 new_meta_info
76              
77             instantiates new context used to convey information between plugins
78              
79             =cut
80              
81 0     0 1 0 sub new_env_var { shift->_new_var($ContextClass . '::EnvVar', @_) }
82 0     0 1 0 sub new_our_var { shift->_new_var($ContextClass . '::OurVar', @_) }
83 0     0 1 0 sub new_module_use { shift->_new_var($ContextClass . '::ModuleUse', @_) }
84 0     0 1 0 sub new_meta_info { shift->_new_var($ContextClass . '::MetaInfo', @_) }
85              
86             =head2 get_code
87              
88             collects code from members
89              
90             =cut
91              
92             # XXX should ensure that a given type+name is only output once (the latest one)
93             sub get_code
94             {
95 40     40 1 82 my $self = shift;
96 40         64 my @code;
97 40         135 for my $setting (reverse @$self)
98             {
99 48 100       160 push @code, (ref $setting) ? $setting->get_code : $setting;
100             }
101 40         174 return join "", @code;
102             }
103              
104             =head2 get_var
105              
106             search backwards through list of settings, stop at first match
107              
108             =cut
109              
110             sub get_var
111             {
112 0     0 1   my ($self, $name, $type) = @_;
113 0           for my $setting (reverse @$self)
114             {
115 0 0         next unless $setting;
116 0           my @value = $setting->get_var($name, $type);
117 0 0         return $value[0] if @value;
118             }
119 0           return;
120             }
121              
122             =head2 get_env_var
123              
124             search backwards through list of settings, stop at first match (implies EnvVar)
125              
126             =head2 get_our_var
127              
128             search backwards through list of settings, stop at first match (implies OurVar)
129              
130             =head2 get_module_use
131              
132             search backwards through list of settings, stop at first match (implies ModuleUse)
133              
134             =head2 get_meta_info
135              
136             search backwards through list of settings, stop at first match (implies MetaInfo)
137              
138             =cut
139              
140 0     0 1   sub get_env_var { my ($self, $name) = @_; return $self->get_var($name, $ContextClass . '::EnvVar') }
  0            
141 0     0 1   sub get_our_var { my ($self, $name) = @_; return $self->get_var($name, $ContextClass . '::OurVar') }
  0            
142 0     0 1   sub get_module_use { my ($self, $name) = @_; return $self->get_var($name, $ContextClass . '::ModuleUse') }
  0            
143 0     0 1   sub get_meta_info { my ($self, $name) = @_; return $self->get_var($name, $ContextClass . '::MetaInfo') }
  0            
144              
145             {
146              
147             package Test::WriteVariants::Context::BaseItem;
148 4     4   27 use strict;
  4         14  
  4         80  
149 4     4   20 use warnings;
  4         8  
  4         1273  
150             require Data::Dumper;
151             require Carp;
152              
153             # base class for an item (a name-value-type triple)
154              
155             sub new
156             {
157 0     0     my ($class, $name, $value) = @_;
158              
159 0           my $self = bless {} => $class;
160 0           $self->name($name);
161 0           $self->value($value);
162              
163 0           return $self;
164             }
165              
166             sub name
167             {
168 0     0     my $self = shift;
169 0 0         $self->{name} = shift if @_;
170 0           return $self->{name};
171             }
172              
173             sub value
174             {
175 0     0     my $self = shift;
176 0 0         $self->{value} = shift if @_;
177 0           return $self->{value};
178             }
179              
180             sub get_code
181             {
182 0     0     return '';
183             }
184              
185             sub get_var
186             {
187 0     0     my ($self, $name, $type) = @_;
188 0 0 0       return if $type && !$self->isa($type); # empty list
189 0 0         return if $name ne $self->name; # empty list
190 0           return $self->value; # scalar
191             }
192              
193             sub quote_values_as_perl
194             {
195 0     0     my $self = shift;
196             ## no critic (BuiltinFunctions::ProhibitComplexMappings)
197             my @perl_values = map {
198 0           my $val = Data::Dumper->new([$_])->Terse(1)->Purity(1)->Useqq(1)->Sortkeys(1)->Dump;
  0            
199 0           chomp $val;
200 0           $val;
201             } @_;
202 0 0 0       Carp::confess("quote_values_as_perl called with multiple items in scalar context (@perl_values)")
203             if @perl_values > 1 && !wantarray;
204 0 0         return $perl_values[0] unless wantarray;
205 0           return @perl_values;
206             }
207              
208             # utility method to get a new composite when you only have a value object
209 0     0     sub new_composite { $ContextClass->new(@_) }
210              
211             } # ::BaseItem
212              
213             {
214              
215             package Test::WriteVariants::Context::EnvVar;
216 4     4   27 use strict;
  4         8  
  4         126  
217 4     4   21 use warnings;
  4         13  
  4         113  
218 4     4   21 use base 'Test::WriteVariants::Context::BaseItem';
  4         12  
  4         1681  
219              
220             # subclass representing a named environment variable
221              
222             sub get_code
223             {
224 0     0     my $self = shift;
225 0           my $name = $self->{name};
226 0           my @lines;
227 0 0         if (defined $self->{value})
228             {
229 0           my $perl_value = $self->quote_values_as_perl($self->{value});
230 0           push @lines, sprintf('$ENV{%s} = %s;', $name, $perl_value);
231 0           push @lines, sprintf('END { delete $ENV{%s} } # for VMS', $name);
232             }
233             else
234             {
235             # we treat undef to mean the ENV var should not exist in %ENV
236 0           push @lines, sprintf('local $ENV{%s};', $name); # preserve old value for VMS
237 0           push @lines, sprintf('delete $ENV{%s};', $name); # delete from %ENV
238             }
239 0           return join "\n", @lines, '';
240             }
241             }
242              
243             {
244              
245             package Test::WriteVariants::Context::OurVar;
246 4     4   28 use strict;
  4         16  
  4         92  
247 4     4   21 use warnings;
  4         7  
  4         108  
248 4     4   22 use base 'Test::WriteVariants::Context::BaseItem';
  4         12  
  4         1072  
249              
250             # subclass representing a named 'our' variable
251              
252             sub get_code
253             {
254 0     0     my $self = shift;
255 0           my $perl_value = $self->quote_values_as_perl($self->{value});
256 0           return sprintf 'our $%s = %s;%s', $self->{name}, $perl_value, "\n";
257             }
258             }
259              
260             {
261              
262             package Test::WriteVariants::Context::ModuleUse;
263 4     4   29 use strict;
  4         7  
  4         69  
264 4     4   19 use warnings;
  4         9  
  4         146  
265 4     4   22 use base 'Test::WriteVariants::Context::BaseItem';
  4         7  
  4         1143  
266              
267             # subclass representing 'use $name (@$value)'
268              
269             sub get_code
270             {
271 0     0     my $self = shift;
272 0           my @imports = $self->quote_values_as_perl(@{$self->{value}});
  0            
273 0           return sprintf 'use %s (%s);%s', $self->{name}, join(", ", @imports), "\n";
274             }
275             }
276              
277             {
278              
279             package Test::WriteVariants::Context::MetaInfo;
280 4     4   29 use strict;
  4         8  
  4         65  
281 4     4   21 use warnings;
  4         7  
  4         108  
282 4     4   22 use base 'Test::WriteVariants::Context::BaseItem';
  4         19  
  4         929  
283              
284             # subclass that doesn't generate any code
285             # It's just used to convey information between plugins
286             }
287              
288             1;
289              
290             __END__