File Coverage

blib/lib/Test/Toolbox.pm
Criterion Covered Total %
statement 156 242 64.4
branch 49 126 38.8
condition 15 42 35.7
subroutine 28 33 84.8
pod 16 27 59.2
total 264 470 56.1


line stmt bran cond sub pod time code
1             package Test::Toolbox;
2 1     1   516 use strict;
  1         1  
  1         25  
3             # use String::Util ':all';
4 1     1   3 use Carp 'croak';
  1         1  
  1         47  
5 1     1   479 use Test::Builder::Module;
  1         9122  
  1         4  
6 1     1   29 use Cwd 'abs_path';
  1         2  
  1         73  
7              
8             # debug tools
9             # use Debug::ShowStuff ':all';
10             # use Debug::ShowStuff::ShowVar;
11              
12             # version
13             our $VERSION = '0.4';
14              
15              
16             #------------------------------------------------------------------------------
17             # opening pod
18             #
19              
20             =head1 NAME
21              
22             Test::Toolbox - tools for testing
23              
24             =head1 SYNOPSIS
25              
26             # load module
27             use Test::Toolbox;
28            
29             # plan tests
30             rtplan 43;
31            
32             # or, plan tests, but die on the first failure
33             rtplan 43, autodie=>1;
34            
35             # basic test
36             rtok 'my test name', $success;
37              
38             # test for failure if you prefer
39             rtok 'test name', $success, should=>0;
40              
41             # two values should equal each other
42             rtcomp 'test name', $val, $other_val;
43            
44             # two values should not equal each other
45             rtcomp 'test name', $val, $other_val, should=>0;
46            
47             # run some code which should succeed
48             # note that the second param is undef
49             rteval 'test name', undef, sub { mysub() };
50            
51             # run some code which should cause a specific error code
52             rteval 'test name', 'file-open-failed', sub { mysub() };
53            
54             # check that $@ has a specific error code
55             rtid 'test name', $@, 'missing-keys';
56            
57             # much more
58              
59             =head1 OVERVIEW
60              
61             Test::Toolbox provides (as you might guess) tools for automated testing.
62             Test::Toolbox is much like some other testing modules, such as Test::More
63             and Test::Simple. Test::Toolbox provides a different flavor of tests which
64             may or may not actually be to your preference.
65              
66             The tools in Test::Toolbox have a standard format. Commands start with (the
67             command (of course), followed by the test name. Then there is usually the
68             value being tested, or values being compared, then other options. So, for
69             example, this command checks compares two values:
70              
71             rtcomp 'test name', $val, $other_val;
72              
73             In some cases it's preferable to flip the logic of the test, so that, for
74             example, two values should B be the same. In that case, you can add
75             the C option:
76              
77             rtcomp 'test name', $val, $other_val, should=>0;
78              
79             All test commands require a test name as the first param.
80              
81             =head1 Meta commands
82              
83             =cut
84              
85             #
86             # opening pod
87             #------------------------------------------------------------------------------
88              
89              
90              
91             #------------------------------------------------------------------------------
92             # extend Test::Builder::Module
93             #
94 1     1   5 use base 'Test::Builder::Module';
  1         1  
  1         89  
95             #
96             # extend Test::Builder::Module
97             #------------------------------------------------------------------------------
98              
99              
100             #------------------------------------------------------------------------------
101             # export
102             # KLUDGE: I don't like automatically exporting everything from a module. By
103             # default, nothing shoujld be exported. Exports should be explicit with
104             # something like :all. However, Test::Module throws an error if Test::Toolbox
105             # tries to use %EXPORT_OK. For now, I'm just going with the flow and exporting
106             # everything, but I'll see if I can correct the situation in later releases.
107             #
108 1     1   4 use base 'Exporter';
  1         1  
  1         1999  
109             our (@EXPORT);
110              
111             # @EXPORT
112             @EXPORT = qw[
113             go_script_dir
114             rtplan
115             rtdiag
116             rtcounts
117             rtok
118             rtcomp
119             rtarr
120             rtelcount
121             rthash
122             rtisa
123             rtbool
124             rtdef
125             rtrx
126             rtfile
127             rtid
128             rteval
129             ];
130             #
131             # export
132             #------------------------------------------------------------------------------
133              
134              
135              
136             #------------------------------------------------------------------------------
137             # globals
138             #
139             our ($planned_test_count);
140             our $auto_die = 0;
141             our $verbose = 0;
142             our %counts = (success=>0, fail=>0, sofar=>0, planned=>0);
143             our $script_abs_path = abs_path($0);
144             #
145             # globals
146             #------------------------------------------------------------------------------
147              
148              
149              
150             ###############################################################################
151             # public methods
152             #
153              
154              
155             #------------------------------------------------------------------------------
156             # go_script_dir
157             #
158              
159             =head2 go_script_dir()
160              
161             C changes to the directory that the script is running in. This
162             can be handy of your test script needs to read files that are part of your
163             tests. C takes no params:
164              
165             go_script_dir();
166              
167             =cut
168              
169             sub go_script_dir {
170 1     1 1 125 my ($script_dir);
171            
172             # TESTING
173             # println subname(); ##i
174            
175             # load basename module
176 1         6 require File::Basename;
177            
178             # get script's directory
179 1         55 $script_dir = File::Basename::dirname($script_abs_path);
180            
181             # untaint directory path
182             # KLUDGE: Normally unconditional untainting is a Very Bad Idea.
183             # In this case I don't know a good way to untaint a path using a pattern.
184             # The following code checks if the path actually exists as a directory,
185             # then untaints the path
186 1 50       21 if (-d $script_dir) {
187 1 50       5 unless ($script_dir =~ m|^(.+)$|s)
188 0         0 { die 'somehow cannot untaint directory path' }
189 1         3 $script_dir = $1;
190             }
191            
192             # go to directory
193 1 50       15 chdir($script_dir) or die 'go-script-dir-chdir-fail: unable to chdir to script directory';
194             }
195             #
196             # go_script_dir
197             #------------------------------------------------------------------------------
198              
199              
200              
201              
202             #------------------------------------------------------------------------------
203             # rtplan
204             #
205              
206             =head2 rtplan()
207              
208             rtplan() indicates how many tests you plan on running. Like with other test
209             modules, failing to run exactly that many tests is itself considered on error.
210             So, this command plans on running exactly 43 tests.
211              
212             rtplan 43;
213              
214             You might prefer that your script dies on the first failure. In that case add
215             the C option:
216              
217             rtplan 43, autodie=>1;
218              
219             =cut
220              
221             sub rtplan {
222 1     1 1 11 my ($count, %opts) = @_;
223 1         2 my ($tb);
224            
225             # TESTING
226             # println subname(); ##i
227            
228             # set planned count
229 1         2 $planned_test_count = $count;
230 1         2 $counts{'planned'} = $count;
231            
232             # autodie
233 1 50       3 if (exists $opts{'autodie'})
234 1         3 { $auto_die = $opts{'autodie'} }
235            
236             # verbose
237             # if (exists $opts{'verbose'})
238             # { $verbose = $opts{'verbose'} }
239            
240             # plan tests
241 1         13 $tb = Test::Toolbox->builder;
242 1         16 return $tb->plan(tests=>$count);
243             }
244             #
245             # rtplan
246             #------------------------------------------------------------------------------
247              
248              
249             #------------------------------------------------------------------------------
250             # rtdiag
251             #
252             sub rtdiag {
253 2     2 0 2185 my (@msgs) = @_;
254 2         15 my $tb = Test::Toolbox->builder;
255 2         28 return $tb->diag(@msgs);
256             }
257             #
258             # rtdiag
259             #------------------------------------------------------------------------------
260              
261              
262             #------------------------------------------------------------------------------
263             # rtcounts
264             #
265              
266             =head2 rtcounts()
267              
268             rtcounts() returns a hashref of the test counts so far. The hashref has the
269             following elements:
270              
271             =over
272              
273             =item * success: number of successful tests so far.
274              
275             =item * fail: number of failed tests so far.
276              
277             =item * sofar: total number of tests so far.
278              
279             =item * planned: total number of planned tests.
280              
281             =back
282              
283             =cut
284              
285             sub rtcounts {
286 1     1 1 15 return {%counts};
287             }
288             #
289             # rtcounts
290             #------------------------------------------------------------------------------
291              
292              
293              
294             #------------------------------------------------------------------------------
295             # pod for test commands
296             #
297              
298             =head1 Test commands
299              
300             =cut
301              
302             #
303             # pod for test commands
304             #------------------------------------------------------------------------------
305              
306              
307              
308             #------------------------------------------------------------------------------
309             # rtok
310             #
311              
312             =head2 rtok()
313              
314             rtok() is the basic command of Test::Toolbox. It requires two params, the name
315             of the test, and a scalar indicating success (true) or failure (false). So,
316             this simple command indicates a successful test:
317              
318             rtok 'my test', 1;
319              
320             You might prefer to flip the logic, so that false indicates success. For that,
321             use the C option:
322              
323             rtok 'my test', $val, should=>0;
324              
325             All other test command call rtok().
326              
327             =cut
328              
329             sub rtok {
330 23     23 1 103 my ($test_name, $ok, %opts) = @_;
331 23         16 my ($indent);
332            
333             # TESTING
334             # println subname(); ##i
335            
336             # default options
337 23         39 %opts = (should=>1, %opts);
338            
339             # $test_name is required
340 23 50       36 $test_name or confess ('$test_name is required');
341            
342             # TESTING
343             # unless ($test_name =~ m|^\(rt\)|si)
344             # { croak 'during development, test name must start with (rt)' }
345            
346             # verbosify
347             # if ($verbose) {
348             # println 'test: ', $test_name;
349             # $indent = indent();
350             # }
351            
352             # reverse test if necessary
353 23         34 $ok = should_flop($ok, %opts);
354            
355             # autodie if mecessary
356 23 50       31 if ($auto_die) {
357 0 0       0 if (! $ok) {
358 0         0 croak("fail: $test_name");
359             }
360             }
361            
362             # regular ok
363 23         28 ok_private($test_name, $ok);
364            
365             # set counts
366 23 50       3941 if ($ok)
367 23         25 { $counts{'success'}++ }
368             else
369 0         0 { $counts{'fail'}++ }
370            
371             # increment sofar
372 23         55 $counts{'sofar'}++;
373             }
374             #
375             # rtok
376             #------------------------------------------------------------------------------
377              
378              
379             #------------------------------------------------------------------------------
380             # rtcomp
381             #
382              
383             =head2 rtcomp()
384              
385             rtcomp() compares the string value of two values. It sets success if they are
386             the same, failure if thet are different. Its simplest use would be like this:
387              
388             rtcomp 'my test', $first, $second;
389              
390             As with other commands, you can flip the logic of the command so that success
391             is if they are not the same:
392              
393             rtcomp 'my test', $first, $second, should=>0;
394              
395             rtcomp() interprets undef as matching undef, so the following test would would
396             be successful.
397              
398             rtcomp 'my test', undef, undef;
399              
400             rtcomp() takes several options.
401              
402             =over
403              
404             =item * collapse
405              
406             If this option is true, then the strings are collapsed before they are
407             compared. So, for example, the following test would succeed:
408              
409             rtcomp 'my test', ' Fred ', 'Fred', collapse=>1;
410              
411             =item * nospace
412              
413             nospace removes all spaces before comparing strings. So this test would
414             succeed:
415              
416             rtcomp 'my test', 'Fr ed', 'Fred', nospace=>1;
417              
418             =item * case_insensitive
419              
420             The case_insensitive option indicates to compare the values case insensitively.
421             So, the following test would be successful.
422              
423             =back
424              
425             =cut
426              
427             sub rtcomp {
428 12     12 1 36 my ($name, $got, $should, %opts) = @_;
429 12         8 my ($ok);
430            
431             # TESTING
432             # println subname(); ##i
433            
434             # should have gotten at least three params
435 12 50       25 unless ( @_ >= 3 )
436 0         0 { croak 'rtcomp requires at least 3 params' }
437            
438             # default options
439 12         17 %opts = (should=>1, %opts);
440            
441             # collapse as necessary
442 12 50       26 if ($opts{'collapse'}) {
    50          
443 0         0 $got = collapse($got);
444 0         0 $should = collapse($should);
445             }
446            
447             # nospace as necessary
448             elsif ($opts{'nospace'}) {
449 0         0 $got = nospace($got);
450 0         0 $should = nospace($should);
451             }
452            
453             # remove trailing whitespace
454             # elsif ($opts{'trim_end'} || $opts{'trim_ends'}) {
455             # $got =~ s|\s+$||s;
456             # $should =~ s|\s+$||s;
457             #}
458            
459             # case insensitive
460 12 50       15 if ($opts{'case_insensitive'}) {
461 0 0       0 if (defined $should)
462 0         0 { $should = lc($should) }
463 0 0       0 if (defined $got)
464 0         0 { $got = lc($got) }
465             }
466            
467             # compare
468 12         17 $ok = eqq($got, $should);
469            
470             # development environment
471 12 0 33     20 if ( (! should_flop($ok, %opts)) && $auto_die) {
472 0         0 print
473             "--- rtcomp fail -------------------------------------------\n",
474             $name, "\n";
475            
476 0 0       0 if (! $opts{'should'}) {
477 0 0       0 print "should-flop: ", ($opts{'should'} ? 1 : 0), "\n";
478             }
479            
480             print
481 0         0 "got: ", rtrim(define($got)), "\n",
482             "should: ", rtrim(define($should)), "\n",
483             "----------------------------------------------------------\n";
484             }
485            
486             # rtok
487 12         18 return rtok($name, $ok, %opts);
488             }
489             #
490             # rtcomp
491             #------------------------------------------------------------------------------
492              
493              
494              
495             #------------------------------------------------------------------------------
496             # rtelcount
497             #
498              
499             =head2 rtelcount
500              
501             Checks if an array has the correct number of elements. The first param is an
502             integer 0 or greater. The second param is an array reference. So, the following
503             test would pass:
504              
505             rtelcount 'my test', 3, \@arr;
506              
507             =cut
508              
509             sub rtelcount {
510 1     1 1 2 my ($name, $arr, $count, %opts) = @_;
511 1         4 return rtcomp $name, scalar(@$arr), $count, %opts;
512             }
513             #
514             # rtelcount
515             #------------------------------------------------------------------------------
516              
517              
518             #------------------------------------------------------------------------------
519             # rtarr
520             #
521              
522             =head2 rtarr
523              
524             rtarr compares two arrays. In its simplest use, the test passes if they are
525             identical:
526              
527             @first = qw{Larry Curly Moe};
528             @second = qw{Larry Curly Moe};
529             rtarr 'my test', \@first, \@second;
530              
531             Like with rtcomp, two undefs are considered the same, so the following test
532             would pass.
533              
534             @first = ('Larry', 'Moe', 'Curly', undef);
535             @second = ('Larry', 'Moe', 'Curly', undef);
536             rtarr 'my test', \@first, \@second;
537              
538             rtarr takes several options.
539              
540             =over
541              
542             =item * order_insensitive
543              
544             If the order_insensitive option is true, then the arrays are considered the
545             same even if the elements are not in the same order. So the following test
546             would pass:
547              
548             @first = ('Curly', 'Larry', 'Moe');
549             @second = ('Larry', 'Moe', 'Curly');
550             rtarr 'my test', \@first, \@second, order_insensitive=>1;
551              
552             =item * case_insensitive
553              
554             If the case_insensitive option is true, then the elements are compared case
555             insensitively. So the following test would pass:
556              
557             @first = ('CURLY', 'LARRY', undef, 'MOE');
558             @second = ('Curly', 'Larry', undef, 'Moe');
559             rtarr 'my test', \@first, \@second, case_insensitive=>1;
560              
561             =back
562              
563             =cut
564              
565             sub rtarr {
566 3     3 1 5 my ($name, $got, $should, %opts) = @_;
567 3         3 my ($ok);
568            
569             # TESTING
570             # println subname(); ##i
571            
572             # default options
573 3         7 %opts = (should=>1, %opts);
574            
575             # load Array::Comp
576             # require Array::Comp;
577            
578             # default options
579 3         7 %opts = (auto_die => 1, %opts);
580            
581             # get result
582 3         8 $ok = arrs_same($got, $should, %opts);
583            
584             # test
585 3 0 33     7 if ( (! should_flop($ok, %opts)) && $auto_die ) {
586             # format for printing
587 0 0       0 $got = [map({defined($_) ? $_ : '[undef]'} @$got)];
  0         0  
588 0 0       0 $should = [map({defined($_) ? $_ : '[undef]'} @$should)];
  0         0  
589            
590             # top of section
591 0         0 print "\n=== rtarr fail =============================================\n";
592            
593             # show should
594 0 0       0 if (! $opts{'should'})
595 0         0 { print 'should: ', $opts{'should'}, "\n" }
596            
597             # show $got
598 0         0 print "--- \$got ---------------------------------------------------\n";
599 0         0 print join("\n", @$got);
600 0         0 print "\n";
601            
602             # TESTING
603             # commenting out next section for testing
604            
605             # show $should
606 0         0 print "--- \$should ------------------------------------------------\n";
607 0         0 print join("\n", @$should);
608 0         0 print "\n";
609            
610             # bottom of section
611 0         0 print "===========================================================\n\n\n";
612             }
613            
614             # rtok
615 3         7 return rtok($name, $ok, %opts);
616             }
617             #
618             # rtarr
619             #------------------------------------------------------------------------------
620              
621              
622              
623             #------------------------------------------------------------------------------
624             # rthash
625             #
626              
627             =head2 rthash
628              
629             rthash checks is two hashes contain the same keys and values. The following
630             test would pass. Keep in mind that hashes don't have the concept of order, so
631             it doesn't matter that the hashes are created with differently ordered keys.
632              
633             %first = ( Curly=>'big hair', Moe=>'flat hair', Schemp=>undef);
634             %second = ( Moe=>'flat hair', Schemp=>undef, Curly=>'big hair');
635             rthash 'my test', \%first, \%second;
636              
637             rthash doesn't currently have a case_insensitive option. That will probably
638             be added in future releases.
639              
640             =cut
641              
642             sub rthash {
643 1     1 1 3 my ($name, $have_sent, $should_sent, %opts) = @_;
644 1         1 my (%have, %should, @wrong, $ok);
645            
646             # TESTING
647             # println subname(); ##i
648            
649             # special case: if either is undef, return false
650 1 50 33     9 unless (defined($have_sent) && defined($should_sent)) {
651 0 0       0 if ($opts{'auto_die'}) {
652 0         0 print 'got: ', $have_sent, "\n";
653 0         0 print 'should: ', $should_sent, "\n";
654 0         0 croak 'at least one hash not defined';
655             }
656            
657 0         0 return 0;
658             }
659            
660             # get hashes we can play with
661 1         3 %have = %$have_sent;
662 1         3 %should = %$should_sent;
663            
664             # loop through values in %should
665 1         4 foreach my $key (keys %should) {
666             # if key doesn't exist
667 3 50       5 if (exists $have{$key}) {
668 3 50       10 if (neqq($have{$key}, $should{$key})) {
669             push @wrong,
670             'have: ' . showval($have{$key}) . "\n" .
671 0         0 'should: ' . showval($should{$key});
672             }
673            
674 3         5 delete $have{$key};
675             }
676            
677             else {
678 0         0 push @wrong, "Do not have key: $key";
679             }
680             }
681            
682             # if anything left in %keys_have
683 1         2 foreach my $key (keys %have)
684 0         0 { push @wrong, "Have unexpected key: $key" }
685            
686             # decide if anything wrong
687 1 50       2 $ok = @wrong ? 0 : 1;
688            
689             # autodie if necessary
690 1 0 33     2 if ( (! should_flop($ok, %opts)) && $auto_die ) {
691 0         0 croak 'hashes are not identical';
692             }
693            
694             # call rtok
695 1         2 rtok($name, $ok, %opts);
696             }
697             #
698             # rthash
699             #------------------------------------------------------------------------------
700              
701              
702              
703             #------------------------------------------------------------------------------
704             # rtisa
705             #
706              
707             =head2 rtisa
708              
709             rtisa tests if a given value is of the given class. For example, the following
710             test would pass.
711              
712             $val = [];
713             rtisa 'my test', $val, 'ARRAY';
714              
715             The second value can be either the name of the class or an example of the
716             class, so the following test would also pass.
717              
718             $val = [];
719             rtisa 'my test', $val, [];
720              
721             If the class is undef or an empty string, then rtisa returns true if the given
722             object is not a reference.
723              
724             $val = 'whatever';
725             rtisa 'my test', $val, '';
726              
727             =cut
728              
729             sub rtisa {
730 3     3 1 7 my ($name, $have, $should, %opts) = @_;
731 3         3 my ($ok, $not);
732            
733             # TESTING
734             # println subname(); ##i
735            
736             # if $should is an object, get the class of the object
737 3 50       7 if (ref $should)
738 0         0 { $should = ref($should) }
739            
740             # if defined $should, set $isa from UNIVERSAL::isa
741 3 100 100     11 if ( defined($should) && length($should) ) {
742 1         3 $ok = UNIVERSAL::isa($have, $should);
743             }
744            
745             # else $have should not have a ref
746             else {
747 2 50       4 $ok = ref($have) ? 0 : 1;
748             }
749            
750             # return rtok
751 3         5 return rtok($name, $ok, %opts);
752             }
753             #
754             # rtisa
755             #------------------------------------------------------------------------------
756              
757              
758             #------------------------------------------------------------------------------
759             # rtbool
760             #
761              
762             =head2 rtbool
763              
764             rtbool checks if two values have the same boolean value, that is, if they are
765             both true or both false. Booleans are checked in the perlish sense, so the
766             values don't have to be the same, they just have to have the same perlish
767             boolean values. Here are some examples.
768              
769             rtbool 'my test', 'whatever', 'dude'; # passes
770             rtbool 'my test', 'whatever', 1; # passes
771             rtbool 'my test', 'whatever', undef; # fails
772             rtbool 'my test', 0, undef; # passes
773              
774             =cut
775              
776             sub rtbool {
777 4     4 1 6 my ($name, $is, $should, %opts) = @_;
778            
779             # TESTING
780             # println subname(); ##i
781             # showvar $is;
782             # showvar $should;
783            
784             # default options
785 4         9 %opts = (auto_die=>1, %opts);
786            
787             # normalize
788 4 100       8 $is = $is ? 'true' : 'false';
789 4 100       7 $should = $should ? 'true' : 'false';
790            
791             # TESTING
792             # showvar $is;
793             # showvar $should;
794            
795             # compare
796 4         9 return rtcomp($name, $is, $should, %opts);
797             }
798             #
799             # rtbool
800             #------------------------------------------------------------------------------
801              
802              
803             #------------------------------------------------------------------------------
804             # rtdef
805             #
806              
807             =head2 rtdef
808              
809             rtdef tests if the given value is defined. The second param is the value being
810             tested, the third param is if the value should be defined or not. So, the
811             following tests would pass.
812              
813             rtdef 'my test', 'hello', 1;
814             rtdef 'my test', undef, 0;
815              
816             The third param must be defined.
817              
818             =cut
819              
820             sub rtdef {
821 2     2 1 5 my ($name, $is, $should, %opts) = @_;
822            
823             # TESTING
824             # println subname(); ##i
825             # showvar $is;
826             # showvar $should;
827            
828             # $should must be defined
829 2 50       4 if (! defined $should) {
830 0         0 croak 'rtdef-should-not-defined: "should" should be defined in rtdef';
831             }
832            
833             # compare
834 2         5 return rtbool($name, defined($is), $should, %opts);
835             }
836             #
837             # rtdef
838             #------------------------------------------------------------------------------
839              
840              
841              
842             #------------------------------------------------------------------------------
843             # rtrx
844             #
845              
846             =head2 rtrx
847              
848             rtrx tests if the given value matches the given regular expression. The
849             following test would pass.
850              
851             rtrx 'my test', 'Fred', 'red';
852              
853             If you want to get fancy with your regular expressions, use qr// to create the
854             regexes as you pass them in. The following test is an example.
855              
856             rtrx 'my test', 'Fred', qr/RED$/i;
857              
858             =cut
859              
860             sub rtrx {
861 1     1 1 2 my ($name, $got, $rx, %opts) = @_;
862 1         2 my ($ok);
863            
864             # TESTING
865             # println subname(); ##i
866            
867             # default options
868 1         3 %opts = (should=>1, %opts);
869            
870             # get result
871 1 50       3 if (defined $got) {
872 1         9 $ok = $got =~ m|$rx|s;
873             }
874             else {
875 0         0 $ok = 0;
876             }
877            
878             # test
879 1 0 33     3 if ( (! should_flop($ok, %opts)) && $auto_die ) {
880            
881             # top of section
882 0         0 print "\n=== rtrx fail ============================================\n";
883            
884             # show should
885 0 0       0 if (! $opts{'should'})
886 0         0 { print 'should: ', $opts{'should'}, "\n" }
887            
888             # show $rx
889 0         0 print "--- \$rx ----------------------------------------------------\n";
890 0         0 print $rx;
891 0         0 print "\n";
892            
893             # show $got
894 0         0 print "--- \$should ------------------------------------------------\n";
895 0         0 print $got;
896 0         0 print "\n";
897            
898             # bottom of section
899 0         0 print "===========================================================\n\n\n";
900             }
901            
902             # rtok
903 1         5 return rtok($name, $ok, %opts);
904             }
905             #
906             # rtrx
907             #------------------------------------------------------------------------------
908              
909              
910              
911             #------------------------------------------------------------------------------
912             # rtfile
913             #
914              
915             =head2 rtfile
916              
917             rtfile tests if the given file path exists. In its simplest use, rtfile takes
918             just the name of the file and the path:
919              
920             rtfile 'my test', '/tmp/log.txt';
921              
922             You can use the C option to test if the file B exist:
923              
924             rtfile 'my test', '/tmp/log.txt', should=>0;
925              
926             =cut
927              
928             sub rtfile {
929 1     1 1 9 my ($name, $path, %opts) = @_;
930 1         1 my ($ok);
931            
932             # TESTING
933             # println subname(); ##i
934            
935             # default options
936 1         3 %opts = (should=>1, %opts);
937            
938             # get existence of path
939 1         14 $ok = -e($path);
940            
941             # throw error if not as should
942 1 0 33     3 if ( (! should_flop($ok, %opts)) && $auto_die ) {
943             croak
944             'file ' . $path . ' should ' .
945 0 0       0 ($opts{'should'} ? '' : 'not ') . 'exist';
946             }
947            
948             # return rtok
949 1         5 return rtok($name, $ok, %opts);
950             }
951             #
952             # rtfile
953             #------------------------------------------------------------------------------
954              
955              
956             #------------------------------------------------------------------------------
957             # message id tests
958             #
959              
960             =head1 Message ID tests
961              
962             The following tests checking for errors that begin with an error code, followed
963             by a colon, followed by plain language. For example:
964              
965             croak 'error-opening-log-file: error opening log file';
966              
967             Note that the error ID must be followed by a colon.
968              
969             =cut
970              
971             #
972             # message id tests
973             #------------------------------------------------------------------------------
974              
975              
976             #------------------------------------------------------------------------------
977             # rtid
978             #
979              
980             =head2 rtid()
981              
982             rtid() checks if the given string starts with the given id. For example, to
983             test is $! starts with the id 'error-opening-log-file' you would use this command:
984              
985             rtid 'my test', $!, 'error-opening-log-file';
986              
987             =cut
988              
989             sub rtid {
990 6     6 1 10 my ($name, $is, $should, %opts) = @_;
991            
992             # TESTING
993             # println subname(); ##i
994             # showvar $is;
995             # showvar $should;
996            
997             # get id of $is
998 6 100       9 if (defined $is)
999 5         12 { $is =~ s|\:.*||s }
1000             else
1001 1         1 { $is = '' }
1002            
1003             # get id of $should or set it to empty string
1004 6 100       8 if (defined $should)
1005 4         4 { $should =~ s|\:.*||s }
1006             else
1007 2         3 { $should = '' }
1008            
1009             # TESTING
1010             # showvar $is;
1011             # showvar $should;
1012            
1013             # compare
1014 6         9 return rtcomp($name, $is, $should, %opts);
1015             }
1016             #
1017             # rtid
1018             #------------------------------------------------------------------------------
1019              
1020              
1021             #------------------------------------------------------------------------------
1022             # rteval
1023             #
1024              
1025             =head2 rteval()
1026              
1027             rteval() allows you to test some code then check for an error id, all in one
1028             easy command. rteval runs the given subroutine in an eval{} block, then tests
1029             Here's an (admittedly contrived) example:
1030              
1031             rteval
1032             'my test',
1033             sub { die 'error-opening-log-file: whatever' },
1034             'error-opening-log-file';
1035              
1036             If your subroutine is really long, you might prefer to put the id as the first
1037             param, then the sub. rteval() provides some forgivness in that regard: if the
1038             second param is a sub, then the first param is assumed to be the id. So the
1039             following example works the same as the above example:
1040              
1041             rteval
1042             'my test',
1043             'error-opening-log-file',
1044             sub { die 'error-opening-log-file: whatever' };
1045              
1046             If the sub is supposed to work, you can put undef for the expected code:
1047              
1048             rteval
1049             'my test',
1050             sub { my $val = 1 },
1051             undef;
1052              
1053             =cut
1054              
1055             sub rteval {
1056 3     3 1 5 my ($name, $id_should, $code, %opts) = @_;
1057 3         2 my ($result);
1058            
1059             # TESTING
1060             # println subname(); ##i
1061             # println ref($id_should);
1062            
1063             # build in a little forgiveness
1064 3 50       13 if (UNIVERSAL::isa $id_should, 'CODE')
1065 3         5 { ($id_should, $code) = ($code, $id_should) }
1066            
1067             # eval code
1068 3         4 eval { &$code() };
  3         4  
1069            
1070             # test results of eval
1071 3         21 return rtid($name, $@, $id_should, %opts);
1072             }
1073             #
1074             # rteval
1075             #------------------------------------------------------------------------------
1076              
1077              
1078             #
1079             # public methods
1080             ###############################################################################
1081              
1082              
1083              
1084              
1085             ###############################################################################
1086             # private methods
1087             #
1088              
1089              
1090             #------------------------------------------------------------------------------
1091             # showval
1092             #
1093             sub showval {
1094 0     0 0 0 my ($val) = @_;
1095            
1096             # if not defined, return [undef]
1097 0 0       0 if (! defined $val) {
1098 0         0 return '[undef]';
1099             }
1100            
1101             # else just return value
1102 0         0 return $val;
1103             }
1104             #
1105             # showval
1106             #------------------------------------------------------------------------------
1107              
1108              
1109             #------------------------------------------------------------------------------
1110             # eqq, neqq
1111             #
1112             sub eqq {
1113 15     15 0 10 my ($str1, $str2) = @_;
1114            
1115             # if both defined
1116 15 50 33     49 if ( defined($str1) && defined($str2) )
1117 15         28 { return $str1 eq $str2 }
1118            
1119             # if neither are defined
1120 0 0 0     0 if ( (! defined($str1)) && (! defined($str2)) )
1121 0         0 { return 1 }
1122            
1123             # only one is defined, so return false
1124 0         0 return 0;
1125             }
1126              
1127             sub neqq {
1128 3 50   3 0 3 return eqq(@_) ? 0 : 1;
1129             }
1130             #
1131             # eqq, neqq
1132             #------------------------------------------------------------------------------
1133              
1134              
1135             #------------------------------------------------------------------------------
1136             # ok_private
1137             # private method
1138             #
1139             sub ok_private {
1140 23     23 0 19 my($name, $bool) = @_;
1141            
1142             # my $tb = Test::More->builder;
1143 23         49 my $tb = Test::Builder::Module->builder;
1144            
1145 23         128 return $tb->ok($bool, $name);
1146             }
1147             #
1148             # ok_private
1149             #------------------------------------------------------------------------------
1150              
1151              
1152             #------------------------------------------------------------------------------
1153             # should_flop
1154             #
1155             sub should_flop {
1156 41     41 0 42 my ($ok, %opts) = @_;
1157            
1158             # TESTING
1159             # println subname; ##i
1160            
1161             # default %opts
1162 41         68 %opts = (should=>1, %opts);
1163            
1164             # reverse $ok if necessary
1165 41 100       61 if (! $opts{'should'})
1166 1         3 { $ok = ! $ok }
1167            
1168             # set ok to strict boolean
1169 41 50       85 $ok = $ok ? 1 : 0;
1170             }
1171             #
1172             # should_flop
1173             #------------------------------------------------------------------------------
1174              
1175              
1176             #------------------------------------------------------------------------------
1177             # arrs_same
1178             #
1179             sub arrs_same {
1180 3     3 0 4 my ($alpha_sent, $beta_sent, %opts) = @_;
1181 3         3 my (@alpha, @beta);
1182            
1183             # both must be array references
1184 3 50 33     18 unless (
1185             UNIVERSAL::isa($alpha_sent, 'ARRAY') &&
1186             UNIVERSAL::isa($beta_sent, 'ARRAY')
1187             )
1188 0         0 { croak 'both params must be array references' }
1189            
1190             # if they have different lengths, they're different
1191 3 50       6 if (@$alpha_sent != @$beta_sent)
1192 0         0 { return 0 }
1193            
1194             # get arrays to use for comparison
1195 3         4 @alpha = @$alpha_sent;
1196 3         4 @beta = @$beta_sent;
1197            
1198             # if case insensitive
1199 3 100       7 if ($opts{'case_insensitive'}) {
1200 1 50       2 grep {if (defined $_) {$_ = lc($_)}} @alpha;
  3         6  
  3         8  
1201 1 50       2 grep {if (defined $_) {$_ = lc($_)}} @beta;
  3         10  
  3         7  
1202             }
1203            
1204             # if order insensitive
1205 3 100       7 if ($opts{'order_insensitive'}) {
1206 1         4 @alpha = comp_sorter(@alpha);
1207 1         2 @beta = comp_sorter(@beta);
1208             }
1209            
1210             # loop through array elements
1211 3         8 for (my $i=0; $i<=$#alpha; $i++) {
1212             # if one is undef but other isn't
1213 9 50 33     52 if (
    50 33        
      33        
1214             ( ( defined $alpha[$i]) && (! defined $beta[$i]) ) ||
1215             ( (! defined $alpha[$i]) && ( defined $beta[$i]) )
1216             ) {
1217 0         0 return 0;
1218             }
1219            
1220             # if $alpha[$i] is undef then both must be, so they're the same
1221             elsif (! defined $alpha[$i]) {
1222             }
1223            
1224             # both are defined
1225             else {
1226 9 50       21 unless ($alpha[$i] eq $beta[$i])
1227 0         0 { return 0 }
1228             }
1229             }
1230            
1231             # if we get this far, they're the same
1232 3         5 return 1;
1233             }
1234             #
1235             # arrs_same
1236             #------------------------------------------------------------------------------
1237              
1238              
1239             #------------------------------------------------------------------------------
1240             # comp_sorter
1241             #
1242             sub comp_sorter {
1243             return sort {
1244             # if both undefined, return 0
1245 2 50 33 2 0 8 if ( (! defined $a) && (! defined $b) )
  5 50       18  
    50          
1246 0         0 { return 0 }
1247            
1248             # if just $a isn't defined, return -1
1249             elsif ( ! defined $a )
1250 0         0 { return -1 }
1251            
1252             # if just $b isn't defined, return 1
1253             elsif ( ! defined $b )
1254 0         0 { return 1 }
1255            
1256             # else return string comparison
1257 5         10 $a cmp $b;
1258             } @_;
1259             }
1260             #
1261             # comp_sorter
1262             #------------------------------------------------------------------------------
1263              
1264              
1265              
1266             #------------------------------------------------------------------------------
1267             # ltrim, rtrim
1268             #
1269             sub ltrim {
1270 0     0 0   my ($rv) = @_;
1271            
1272 0 0         if (defined $rv)
1273 0           { $rv =~ s|\s+$||s }
1274            
1275 0           return $rv;
1276             }
1277              
1278             sub rtrim {
1279 0     0 0   my ($rv) = @_;
1280            
1281 0 0         if (defined $rv)
1282 0           { $rv =~ s|^\s+||s }
1283            
1284 0           return $rv;
1285             }
1286             #
1287             # ltrim, rtrim
1288             #------------------------------------------------------------------------------
1289              
1290              
1291              
1292             #------------------------------------------------------------------------------
1293             # define
1294             #
1295             sub define {
1296 0     0 0   my ($val) = @_;
1297            
1298             # if defined, return it
1299 0 0         if (defined $val)
1300 0           { return $val }
1301            
1302             # else return empty string
1303 0           return '';
1304             }
1305             #
1306             # define
1307             #------------------------------------------------------------------------------
1308              
1309              
1310             #------------------------------------------------------------------------------
1311             # collapse
1312             #
1313             sub collapse {
1314 0     0 1   my ($val) = @_;
1315            
1316 0 0         if (defined $val) {
1317 0           $val =~ s|^\s+||s;
1318 0           $val =~ s|\s+$||s;
1319 0           $val =~ s|\s+| |sg;
1320             }
1321            
1322 0           return $val;
1323             }
1324             #
1325             # collapse
1326             #------------------------------------------------------------------------------
1327              
1328              
1329             #
1330             # private methods
1331             ###############################################################################
1332              
1333              
1334             # return true
1335             1;
1336             __END__