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