File Coverage

blib/lib/Chart/EPS_graph/Test.pm
Criterion Covered Total %
statement 18 163 11.0
branch 0 64 0.0
condition 0 3 0.0
subroutine 6 22 27.2
pod 0 16 0.0
total 24 268 8.9


line stmt bran cond sub pod time code
1             # $Source: /home/aplonis/Chart-EPS_graph/Chart/EPS_graph/Test.pm $
2             # $Date: 2006-08-15 $
3              
4             package Chart::EPS_graph::Test;
5              
6 1     1   4201 use strict;
  1         4  
  1         43  
7 1     1   6 use warnings;
  1         2  
  1         40  
8 1     1   6 use Carp qw(carp croak);
  1         2  
  1         101  
9 1     1   6 use Chart::EPS_graph;
  1         3  
  1         27  
10 1     1   6 use Config;
  1         2  
  1         39  
11 1     1   6 use English qw(-no_match_vars);
  1         1  
  1         8  
12             require File::Find; # Win32 only needs this.
13              
14             our ($VERSION) = '$Revision: 0.01 $' =~ m{ \$Revision: \s+ (\S+) }xm;
15              
16             my $EMPTY = q{};
17              
18             # For author's use when testing on different OS environs.
19             # while (my ($key,$val) = each %ENV) { print "$key = $val \n"}
20              
21             # Select an user's own home space to write test files into.
22             # Must untaint that path as apporiate for whicever OS as this
23             # program is called in CPAN module test on build.
24             sub home_dir {
25 0     0 0   my $home_dir = $ENV{HOME}; # Must untaint.
26 0 0         if ( $Config::Config{'osname'} =~ m/(MS)?Win32/im ) {
27              
28             # Do for Win32 users. Tested only on WinXP
29 0           $ENV{PATH} = 'C:\Perl\bin';
30 0           $home_dir = $ENV{USERPROFILE};
31 0           $home_dir =~ s/\\/\//gm;
32             # Untaint it.
33 0 0         if ($home_dir =~ m/(C:\/Documents and Settings)\/(.*)/m) {
34 0           $home_dir = "$1/$2/Desktop";
35             } else {
36 0           $home_dir = 'C:/';
37             }
38             } else {
39              
40             # Assume everybody else is UNIX. Tested only on NetBSD
41 0           $ENV{PATH} = '/bin:/usr/bin:/usr/pkg/bin';
42 0 0         if ($home_dir =~ m/(\/home)\/(.*)/m) {
43 0           $home_dir = "$1/$2"
44             } else {
45 0           $home_dir = '/tmp'
46             }
47             }
48 0           return $home_dir;
49             }
50              
51             # Test if scalar is tainted.
52             sub is_tainted {
53 0     0 0   my $arg = shift;
54 0           my $nada = substr $arg, 0, 0;
55 0           local $EVAL_ERROR = 0; # Perl::Critic errs about localization.
56 0           eval { eval "# $nada"}; # Perl::Critic errs about the quotes.
  0            
57 0           return length $EVAL_ERROR != 0;
58             }
59              
60             sub new {
61 0 0   0 0   ref( my $class = shift ) and croak 'Oops! Method new() is class, not instance.';
62 0           my $self = {};
63 0           $self->{dir} = shift;
64 0           $self->{results} = $EMPTY;
65 0           bless $self, $class;
66 0           return $self;
67             }
68              
69             # Wipe out any earlier EPS and PNG test files in same dir.
70             sub clean_up_dir {
71 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method clean_up_dir() is instance, not class.';
72 0           unlink "$self->{dir}/foo.eps.png";
73 0           unlink "$self->{dir}/foo.eps";
74 0           return 'Pthhht! to Perl::Critic';
75             }
76              
77             # Generate one unique curve of mock data.
78             sub curve_gen {
79 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method curve_gen() is instance, not class.';
80 0           my ($i, $j, $r) = @_;
81 0           $self->{data}[$i] = [];
82 0           for (0 .. 12){
83 0           ${$self->{data}}[$i][$_] = $_ * $r + $j * $r;
  0            
84 0 0         $r *= -1 if $i != 0;
85             }
86 0           return 'Pthhht! to Perl::Critic';
87             }
88              
89             # Generate a set of curves of mock data.
90             sub mk_mock_data {
91 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method mk_mock_data() is instance, not class.';
92              
93             # There should be no other *.esp or *.png files in the module directory
94             # at start of test as to create and check them is what shall be tested.
95 0           unlink "$self->{dir}/foo.eps";
96 0           unlink "$self->{dir}/foo.eps.png";
97              
98             # Mock channel names and a data aref as if from a read-in *.csv file.
99 0           $self->{names} = ['Time (S)', 'LH A Y1', 'Not Shown', 'LH B Y1', 'RH Y2'];
100 0           $self->{data} = [];
101              
102             # A linear time-base and four unique zig-zags.
103 0           $self->curve_gen(0, 0, 1);
104 0           $self->curve_gen(1, 7, 3);
105 0           $self->curve_gen(2, 15, -7);
106 0           $self->curve_gen(3, -31, 15);
107 0           $self->curve_gen(4, 256, 31);
108 0           return 'Pthhht! to Perl::Critic';
109             }
110              
111             # Create an EPS file
112             sub mk_eps_file {
113 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method mk_eps_file() is instance, not class.';
114              
115             # Write a PostScript file of the graph.
116 0           my $eps = Chart::EPS_graph->new(480, 480);
117              
118             # Give choices about EPS graph
119 0           $eps->set(
120             label_top => 'Colorblind Test of Chart::EPS_graph.pm Module',
121             label_y1 => 'Y1 Axis',
122             label_y1_2 => $EMPTY,
123             label_y2 => 'Y2 Axis',
124             label_x => 'Time (S)',
125             label_x_2 => $EMPTY,
126             names => $self->{names},
127             data => $self->{data},
128             y1 => [1,3],
129             y2 => [4],
130             font_name => 'Helvetica-Oblique',
131             font_size => 11,
132             bg_color => 'DarkOliveGreen',
133             fg_color => 'HotPink',
134             web_colors => ['Snow', 'Lime', 'Indigo', 'Gold', 'Red', 'Aqua'],
135             verbosity => 0,
136             );
137              
138 0           $self->x_axis_switch($eps); # X axis sometimes channel data, other times fake.
139              
140             # Create an EPS graph of the CSV data.
141 0           $eps->write_eps( "$self->{dir}/foo.eps" );
142              
143 0           return $eps;
144             }
145              
146             # With or without 0th chan as X-axis. Time-based 50% probability.
147             sub x_axis_switch {
148 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method x_axis_switch() is instance, not class.';
149 0           my $eps = shift;
150 0 0         if (time % 2) {
151 0           shift @{$self->{data}}; # Shift only data, not names.
  0            
152 0           $eps->set(
153             label_x => 'Data Points * 10',
154             x_is_zeroth => 0,
155             x_scale => 1,
156             );
157 0           $self->{results} .= "Info: Simulated data being used X axis data\n"
158             } else {
159 0           $self->{results} .= "Info: Channel data being used X axis data\n"
160             }
161 0           return 'Pthhht! to Perl::Critic';
162             }
163              
164             sub ck_age_size {
165 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method ck_age_size() is instance, not class. \n';
166 0           my ($name, $min_bytes) = @_;
167 0 0         if ( my @stats = stat "$self->{dir}/$name" ) {
168 0           my $age = time - $stats[9];
169 0 0         if ($age < 10) {
170 0           $self->{results} .= "Okay: File '$name' looks fresh: $age seconds old. \n"
171             } else {
172 0           $self->{results} .= "Oops! File '$name' looks old: $age seconds old. \n"
173             }
174 0           my $size = $stats[7];
175 0 0         if ($size > $min_bytes) {
176 0           $self->{results} .= "Okay: File '$name' looks big enough, $size bytes. \n"
177             } else {
178 0           $self->{results} .= "Oops! File '$name' looks too small, $size bytes. \n"
179             }
180             } else {
181 0           $self->{results} .= "Oops! File '$name' has no status. \n"
182             }
183 0           return 'Pthhht! to Perl::Critic';
184             }
185              
186             # Test the EPS file.
187             sub test_eps_file {
188 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method test_eps_file() is instance, not class. \n';
189 0 0         if (open my $fh, '<', "$self->{dir}/foo.eps") {
190 0 0 0       if (
191             (<$fh> =~ m/^%!PS-Adobe-2.0 EPSF-2.0$/m)
192             &&
193             (<$fh> =~ m/^%%Title: \(.*\/foo.eps\)$/m)) {
194 0           $self->{results} .= "Okay: File 'foo.eps' has expected first two lines. \n";
195             } else {
196 0           $self->{results} .= "Oops! File 'foo.eps' lacks expected first two lines. \n";
197             }
198 0           close $fh;
199 0           $self->ck_age_size('foo.eps', 20 * 1024);
200             } else {
201 0           $self->{results} .= "Oops! File 'foo.eps' could not be read. \n";
202             }
203 0           return 'Pthhht! to Perl::Critic';
204             }
205              
206             # On Win32 different versions may be located variously.
207             # Not knowing which version user has, we must seek it.
208             sub win32_seek {
209 0     0 0   our ($reg_ex, $start_path) = @_;
210 0           our $cmd_exe = $EMPTY;
211 0 0   0 0   sub seek_exe { if (m/$reg_ex/m) {
212 0           $cmd_exe = qq|"$File::Find::name"|};
213 0           return 'Pthhht! to Perl::Critic';
214             }
215 0           File::Find::find(\&seek_exe, $start_path);
216 0           $cmd_exe = qq|$cmd_exe|;
217 0           $cmd_exe =~ s/\\/\//gm;
218 0           return $cmd_exe;
219             }
220              
221             # From an already created EPS file, create a PNG file and test it.
222             sub mk_png_file {
223 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method mk_png_file() is instance, not class.';
224 0           my $eps = shift;
225 0           my $result = "Okay: Ghostscript called to create 'foo.eps.png'. \n";
226 0 0         if ( $Config::Config{'osname'} =~ m/Win/im ) {
227 0 0         if (my $gs_path = win32_seek('gswin32\.exe$','C:/Program Files/gs/')) {
228 0           $eps->display('GS');
229             } else {
230 0           $result = "Oops! Ghostscript is needed but not installed. \n"
231             }
232             }
233             else {
234 0           $result = "Note: Ghostscript assumed installed on non Win32 platforms. \n";
235 0           $eps->display('GS');
236             }
237 0           $self->{results} .= $result;
238 0           sleep 1;
239 0           return 'Pthhht! to Perl::Critic';
240             }
241              
242             sub test_png_file {
243 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method test_png_file() is instance, not class.';
244 0 0         unless ($self->{results} =~ m/Oops!/m) {
245 0           $self->ck_age_size('foo.eps.png', 40 * 1024);
246             }
247 0           return 'Pthhht! to Perl::Critic';
248             }
249              
250             sub pass_judgement {
251 0 0   0 0   ref( my $self = shift ) or croak 'Oops! Method pass_judgement() is instance, not class.';
252 0           $self->{results} .= "\n";
253 0 0         if ($self->{results} =~ m/Oops!/m) {
254 0           $self->{results} .= "Woe & Lament! Not all is well for Chart::EPS_graph. \n"
255             } else {
256 0           $self->{results} .= "Glad Tidings! All tests okay for Chart::EPS_graph. \n"
257             }
258 0           return "\n" . $self->{results} . "\n";
259             }
260              
261             # Fully exercise the EPS_Graph module just as a user would.
262             sub full_test {
263 0     0 0   my $tainted = 0; # Assume called by user, not CPAN build test.
264 0 0         ref( my $class = shift ) and croak 'Oops! Method full_test() is class, not instance.';
265 0           my $self = {};
266 0           bless $self, $class;
267 0           $self->{dir} = shift;
268 0           $self->{results} = $EMPTY;
269              
270             # CPAN build test calls sans args in taint mode.
271 0 0         unless ($self->{dir}) {
272 0           $tainted = 1;
273 0           $self->{dir} = home_dir();
274             }
275              
276 0           $self->{dir} =~ s/\/+$//m;
277 0 0         if ($self->{dir} =~ m/Chart\/EPS_graph/m) {
278 0           $self->clean_up_dir();
279 0           $self->{results} .= "Ahem! Writing test graphs to '$self->{dir}'. \n";
280             }
281 0           $self->clean_up_dir();
282 0           $self->mk_mock_data();
283 0           my $eps = $self->mk_eps_file();
284 0           $self->test_eps_file();
285              
286             # Can't run tainted because File::Find will hunt for Ghostscript on Win32.
287 0 0         unless ($tainted) {
288 0           $self->mk_png_file($eps);
289 0           $self->test_png_file($eps);
290 0           $eps->display();
291             }
292              
293 0 0         if ($self->{dir} =~ m/Chart\/EPS_graph/m) {
294 0           $self->{results} .= "Ahem! Deleting test graphs from '$self->{dir}'. \n";
295 0           $self->clean_up_dir();
296 0           $self->{results} .= "Note: Next time, specify '/some/dir/' for the test. \n";
297             } else {
298 0           my $foo_path = "$self->{dir}/foo.eps*";
299 0 0         $foo_path =~ s/\//\\/gm if $Config::Config{'osname'} =~ m/Win/im;
300 0           $self->{results} .= "Done: Lacking any oopses, you may look at '$foo_path'. \n";
301             }
302 0           return $self->pass_judgement(); # RE the string for "Oops!" as failure.
303             }
304              
305             1;
306              
307             __END__