File Coverage

blib/lib/String/Tests.pm
Criterion Covered Total %
statement 24 25 96.0
branch 17 18 94.4
condition 1 3 33.3
subroutine 4 4 100.0
pod 1 1 100.0
total 47 51 92.1


line stmt bran cond sub pod time code
1             package String::Tests;
2              
3 2     2   38683 use strict;
  2         5  
  2         99  
4 2     2   13 use warnings;
  2         5  
  2         79  
5 2     2   14 use Carp 'croak';
  2         9  
  2         904  
6              
7             =head1 NAME
8              
9             String::Tests - run a series of tests on a string
10              
11             =head1 VERSION
12              
13             Version 0.05
14              
15             =cut
16              
17             our $VERSION = '0.05';
18              
19              
20             =head1 SYNOPSIS
21              
22             use String::Tests;
23             my $boolean = String::Tests->pass( $string, \@tests );
24              
25             =head1 DESCRIPTION
26              
27             It is very common (for example when doing user input validation) to have to run
28             a series of tests on a single string of data. This module attempts to ease the
29             burden of doing so, by amalgamating all tests into a single boolean method call.
30              
31             =head2 EXPORT
32              
33             None by default
34              
35             =head1 METHODS
36              
37             =head2 pass
38              
39             =cut
40              
41             sub pass {
42 24 50 33 24 1 5487 shift if $_[0] eq __PACKAGE__ or ref $_[0];
43 24         47 my ($string, $tests) = @_;
44 24         207 my $type = ref $tests;
45 24 100       72 if ($type eq 'ARRAY') {
    100          
    100          
46 17         32 for my $test (@$tests) { # boolean return values only when in list context
47 47         104 my $test_type = ref $test;
48 47 100       93 if ($test_type eq 'Regexp') {
    100          
49 36 100       252 return if $string !~ $test; # simple boolean test
50             } elsif ($test_type eq 'CODE') {
51 10 100       21 return if not $test->($string); # callback
52             } else {
53 1         15 croak "ERROR: type of tests must be 'Regexp' or 'CODE'.\n";
54             }
55             }
56 3         27 return 1; # boolean all tests passed
57             } elsif ($type eq 'Regexp') {
58 3 100       30 return ( $string =~ /$tests/g ) if wantarray; # assumes capture syntax
59 2         18 return $string =~ $tests; # simple boolean test
60             } elsif ($type eq 'CODE') {
61 3         11 return $tests->($string); # return whatever the code ref returned
62             }
63 1         24 croak "ERROR: type of tests must be 'ARRAY', 'Regexp' or 'CODE'.\n";
64 0           return;
65             }
66              
67             =head1 EXAMPLES
68              
69             The most useful case is of course to run a series of code and/or regexp tests on a
70             string. The example below shows a simple way to validate user password creation.
71              
72             my $boolean = String::Tests->pass( 'wimpy_password', [
73             qr/^[\w[:punct:]]{8,16}\z/, # character white list
74             qr/[A-Z]/, # force 1 upper case
75             qr/[a-z]/, # force 1 lower case
76             qr/\d/, # force 1 digit
77             qr/[[:punct:]]/, # force 1 punctuation symbol
78             sub {$self->SUPER::password_tests(@_)}}, # whatever else...
79             ]);
80              
81             When needed you can also run a single code ref or regexp. Whatever function you
82             implement will receive the string to be tested (in the example below,
83             'email@address.com') as $_[0].
84              
85             my $boolean = String::Tests->pass( 'email@address.com',
86             sub { use Email::Valid; return Email::Valid->rfc822(shift) }
87             );
88             my $boolean = String::Tests->pass( 'some_string', qr/some_regexp/ );
89              
90             While it's unlikely to be useful in most cases, you can also capture return values
91             from a regexp test into an array.
92              
93             my @blocks_abcd = String::Tests->pass( '10.0.0.1',
94             qr/^ (\d{1,3}) \. (\d{1,3}) \. (\d{1,3}) \. (\d{1,3}) \z/x
95             );
96              
97             When running a single code ref, pass() simply returns whatever your function does.
98              
99             my @domain_parts = String::Tests->pass( 'x.y.z.sub.domain.tld.stld',
100             sub {return split_domain_name(shift)}
101             );
102              
103             The pseduo-code below provides a simple example of form validation useful for
104             providing feedback to the user about errors. Use of constants can help optimize
105             complex sets of tests when operating in a persistant environment (such as
106             mod_perl).
107              
108             package MyPackage;
109              
110             use String::Tests;
111              
112             use constant PARAM_TESTS => {
113             username => [
114             q| must be 2-32 alpha-numeric, "." or "_" characters |,
115             [
116             qr/^[\w\.\-]{2,32}\z/,
117             qr/[a-z0-9]/i,
118             ],
119             ],
120             password => [
121             q| must have 8-16 dual case letters, numbers, and punctations |,
122             [
123             qr/^[\w[:punct:]]{8,16}\z/,
124             qr/[A-Z]/,
125             qr/[a-z]/,
126             qr/\d/,
127             qr/[[:punct:]]/,
128             ],
129             ],
130             email => [
131             q| must be a valid email address |,
132             sub { use Email::Valid; return Email::Valid->rfc822(shift) },
133             ],
134             };
135              
136             sub test_params { # ->test_params(qw( username password email ))
137             my ( $self, @param_fields ) = @_;
138             for my $field (@param_fields) {
139             my ( $error_message, $tests ) = @{ __PACKAGE__->PARAM_TESTS->{$field} };
140             # set error messages (if any) so you can alert the user
141             $self->errors->{$field} = $error_message
142             unless String::Tests->pass( $http_request->param($field), $tests );
143             }
144             }
145              
146             =head1 AUTHOR
147              
148             Shaun Fryer, C<< >>
149              
150             =head1 BUGS
151              
152             Please report any bugs or feature requests to C, or through
153             the web interface at L. I will be notified, and then you'll
154             automatically be notified of progress on your bug as I make changes.
155              
156              
157              
158              
159             =head1 SUPPORT
160              
161             You can find documentation for this module with the perldoc command.
162              
163             perldoc String::Tests
164              
165              
166             You can also look for information at:
167              
168             =over 4
169              
170             =item * RT: CPAN's request tracker
171              
172             L
173              
174             =item * AnnoCPAN: Annotated CPAN documentation
175              
176             L
177              
178             =item * CPAN Ratings
179              
180             L
181              
182             =item * Search CPAN
183              
184             L
185              
186             =back
187              
188              
189             =head1 ACKNOWLEDGEMENTS
190              
191             Everybody. :)
192             L
193              
194             =head1 COPYRIGHT & LICENSE
195              
196             Copyright 2008 Shaun Fryer, all rights reserved.
197              
198             This program is free software; you can redistribute it and/or modify it
199             under the same terms as Perl itself.
200              
201              
202             =cut
203              
204             1; # End of String::Tests