File Coverage

blib/lib/Carp/Assert/More.pm
Criterion Covered Total %
statement 367 374 98.1
branch 180 188 95.7
condition 75 118 63.5
subroutine 44 45 97.7
pod 37 37 100.0
total 703 762 92.2


line stmt bran cond sub pod time code
1             package Carp::Assert::More;
2              
3 40     40   2235052 use warnings;
  40         390  
  40         1310  
4 40     40   175 use strict;
  40         64  
  40         672  
5              
6 40     40   143 use Exporter;
  40         58  
  40         1024  
7 40     40   164 use Scalar::Util;
  40         61  
  40         1290  
8              
9 40     40   194 use vars qw( $VERSION @ISA @EXPORT );
  40         86  
  40         5068  
10              
11             =head1 NAME
12              
13             Carp::Assert::More - Convenience assertions for common situations
14              
15             =head1 VERSION
16              
17             Version 2.1.0
18              
19             =cut
20              
21             BEGIN {
22 40     40   134 $VERSION = '2.1.0';
23 40         595 @ISA = qw(Exporter);
24 40         32459 @EXPORT = qw(
25             assert_all_keys_in
26             assert_aoh
27             assert_arrayref
28             assert_arrayref_nonempty
29             assert_coderef
30             assert_context_nonvoid
31             assert_context_scalar
32             assert_datetime
33             assert_defined
34             assert_empty
35             assert_exists
36             assert_fail
37             assert_hashref
38             assert_hashref_nonempty
39             assert_in
40             assert_integer
41             assert_is
42             assert_isa
43             assert_isa_in
44             assert_isnt
45             assert_keys_are
46             assert_lacks
47             assert_like
48             assert_listref
49             assert_negative
50             assert_negative_integer
51             assert_nonblank
52             assert_nonempty
53             assert_nonnegative
54             assert_nonnegative_integer
55             assert_nonref
56             assert_nonzero
57             assert_nonzero_integer
58             assert_numeric
59             assert_positive
60             assert_positive_integer
61             assert_undefined
62             assert_unlike
63             );
64             }
65              
66             my $INTEGER = qr/^-?\d+$/;
67              
68             =head1 SYNOPSIS
69              
70             A set of convenience functions for common assertions.
71              
72             use Carp::Assert::More;
73              
74             my $obj = My::Object;
75             assert_isa( $obj, 'My::Object', 'Got back a correct object' );
76              
77             =head1 DESCRIPTION
78              
79             Carp::Assert::More is a convenient set of assertions to make the habit
80             of writing assertions even easier.
81              
82             Everything in here is effectively syntactic sugar. There's no technical
83             difference between calling one of these functions:
84              
85             assert_datetime( $foo );
86             assert_isa( $foo, 'DateTime' );
87              
88             that are provided by Carp::Assert::More and calling these assertions
89             from Carp::Assert
90              
91             assert( defined $foo );
92             assert( ref($foo) eq 'DateTime' );
93              
94             My intent here is to make common assertions easy so that we as programmers
95             have no excuse to not use them.
96              
97             =head1 SIMPLE ASSERTIONS
98              
99             =head2 assert_is( $string, $match [,$name] )
100              
101             Asserts that I<$string> matches I<$match>.
102              
103             =cut
104              
105             sub assert_is($$;$) {
106 8     8 1 3995 my $string = shift;
107 8         9 my $match = shift;
108 8         8 my $name = shift;
109              
110 8 100       14 if ( defined($string) ) {
111 6 100 100     31 return if defined($match) && ($string eq $match);
112             }
113             else {
114 2 100       7 return if !defined($match);
115             }
116              
117 3         15 require Carp;
118 3         7 &Carp::confess( _failure_msg($name) );
119             }
120              
121              
122             =head2 assert_isnt( $string, $unmatch [,$name] )
123              
124             Asserts that I<$string> does NOT match I<$unmatch>.
125              
126             =cut
127              
128             sub assert_isnt($$;$) {
129 8     8 1 4747 my $string = shift;
130 8         11 my $unmatch = shift;
131 8         9 my $name = shift;
132              
133             # undef only matches undef
134 8 100 100     39 return if defined($string) xor defined($unmatch);
135              
136 6 100 66     29 return if defined($string) && defined($unmatch) && ($string ne $unmatch);
      100        
137              
138 5         22 require Carp;
139 5         12 &Carp::confess( _failure_msg($name) );
140             }
141              
142              
143             =head2 assert_like( $string, qr/regex/ [,$name] )
144              
145             Asserts that I<$string> matches I.
146              
147             The assertion fails either the string or the regex are undef.
148              
149             =cut
150              
151             sub assert_like($$;$) {
152 7     7 1 3406 my $string = shift;
153 7         9 my $regex = shift;
154 7         10 my $name = shift;
155              
156 7 100 66     29 if ( defined($string) && !ref($string) ) {
157 6 100       14 if ( ref($regex) ) {
158 5 100       44 return if $string =~ $regex;
159             }
160             }
161              
162 4         21 require Carp;
163 4         11 &Carp::confess( _failure_msg($name) );
164             }
165              
166              
167             =head2 assert_unlike( $string, qr/regex/ [,$name] )
168              
169             Asserts that I<$string> matches I.
170              
171             The assertion fails if the regex is undef.
172              
173             =cut
174              
175             sub assert_unlike($$;$) {
176 7     7 1 3805 my $string = shift;
177 7         7 my $regex = shift;
178 7         9 my $name = shift;
179              
180 7 100       15 return if !defined($string);
181              
182 5 100       12 if ( ref($regex) eq 'Regexp' ) {
183 3 100       16 return if $string !~ $regex;
184             }
185              
186 4         17 require Carp;
187 4         7 &Carp::confess( _failure_msg($name) );
188             }
189              
190              
191             =head2 assert_defined( $this [, $name] )
192              
193             Asserts that I<$this> is defined.
194              
195             =cut
196              
197             sub assert_defined($;$) {
198 9 100   9 1 901 return if defined( $_[0] );
199              
200 2         10 require Carp;
201 2         8 &Carp::confess( _failure_msg($_[1]) );
202             }
203              
204              
205             =head2 assert_undefined( $this [, $name] )
206              
207             Asserts that I<$this> is not defined.
208              
209             =cut
210              
211             sub assert_undefined($;$) {
212 4 100   4 1 2369 return unless defined( $_[0] );
213              
214 3         14 require Carp;
215 3         8 &Carp::confess( _failure_msg($_[1]) );
216             }
217              
218             =head2 assert_nonblank( $this [, $name] )
219              
220             Asserts that I<$this> is not a reference and is not an empty string.
221              
222             =cut
223              
224             sub assert_nonblank($;$) {
225 7     7 1 4351 my $this = shift;
226 7         12 my $name = shift;
227              
228 7         7 my $why;
229 7 100       16 if ( !defined($this) ) {
230 2         3 $why = 'Value is undef.';
231             }
232             else {
233 5 100       8 if ( ref($this) ) {
234 1         4 $why = 'Value is a reference to ' . ref($this) . '.';
235             }
236             else {
237 4 100       14 return if $this ne '';
238 2         4 $why = 'Value is blank.';
239             }
240             }
241              
242 5         46 require Carp;
243 5         12 &Carp::confess( _failure_msg($name, $why) );
244             }
245              
246              
247             =head1 NUMERIC ASSERTIONS
248              
249             =head2 assert_numeric( $n [, $name] )
250              
251             Asserts that C<$n> looks like a number, according to C.
252             C will always fail.
253              
254             =cut
255              
256             sub assert_numeric {
257 21     21 1 12117 my $n = shift;
258 21         29 my $name = shift;
259              
260 21 100       94 return if Scalar::Util::looks_like_number( $n );
261              
262 9         56 require Carp;
263 9         24 &Carp::confess( _failure_msg($name) );
264             }
265              
266              
267             =head2 assert_integer( $this [, $name ] )
268              
269             Asserts that I<$this> is an integer, which may be zero or negative.
270              
271             assert_integer( 0 ); # pass
272             assert_integer( 14 ); # pass
273             assert_integer( -14 ); # pass
274             assert_integer( '14.' ); # FAIL
275              
276             =cut
277              
278             sub assert_integer($;$) {
279 20     20 1 6444 my $this = shift;
280 20         23 my $name = shift;
281              
282 20 100       34 if ( defined($this) ) {
283 18 100       90 return if $this =~ $INTEGER;
284             }
285              
286 14         50 require Carp;
287 14         20 &Carp::confess( _failure_msg($name) );
288             }
289              
290              
291             =head2 assert_nonzero( $this [, $name ] )
292              
293             Asserts that the numeric value of I<$this> is defined and is not zero.
294              
295             assert_nonzero( 0 ); # FAIL
296             assert_nonzero( -14 ); # pass
297             assert_nonzero( '14.' ); # pass
298              
299             =cut
300              
301             sub assert_nonzero($;$) {
302 10     10 1 5294 my $this = shift;
303 10         13 my $name = shift;
304              
305 10 100       32 if ( Scalar::Util::looks_like_number($this) ) {
306 5 100       15 return if $this != 0;
307             }
308              
309 6         28 require Carp;
310 6         13 &Carp::confess( _failure_msg($name) );
311             }
312              
313              
314             =head2 assert_positive( $this [, $name ] )
315              
316             Asserts that I<$this> is defined, numeric and greater than zero.
317              
318             assert_positive( 0 ); # FAIL
319             assert_positive( -14 ); # FAIL
320             assert_positive( '14.' ); # pass
321              
322             =cut
323              
324             sub assert_positive($;$) {
325 10     10 1 4937 my $this = shift;
326 10         14 my $name = shift;
327              
328 10 100       34 if ( Scalar::Util::looks_like_number($this) ) {
329 5 100       20 return if ($this+0 > 0);
330             }
331              
332 7         33 require Carp;
333 7         23 &Carp::confess( _failure_msg($name) );
334             }
335              
336              
337             =head2 assert_nonnegative( $this [, $name ] )
338              
339             Asserts that I<$this> is defined, numeric and greater than or equal
340             to zero.
341              
342             assert_nonnegative( 0 ); # pass
343             assert_nonnegative( -14 ); # FAIL
344             assert_nonnegative( '14.' ); # pass
345             assert_nonnegative( 'dog' ); # pass
346              
347             =cut
348              
349             sub assert_nonnegative($;$) {
350 10     10 1 4861 my $this = shift;
351 10         10 my $name = shift;
352              
353 10 100       30 if ( Scalar::Util::looks_like_number( $this ) ) {
354 5 100       12 return if $this >= 0;
355             }
356              
357 6         25 require Carp;
358 6         13 &Carp::confess( _failure_msg($name) );
359             }
360              
361              
362             =head2 assert_negative( $this [, $name ] )
363              
364             Asserts that the numeric value of I<$this> is defined and less than zero.
365              
366             assert_negative( 0 ); # FAIL
367             assert_negative( -14 ); # pass
368             assert_negative( '14.' ); # FAIL
369              
370             =cut
371              
372             sub assert_negative($;$) {
373 10     10 1 5000 my $this = shift;
374 10         13 my $name = shift;
375              
376 40     40   332 no warnings;
  40         61  
  40         93348  
377 10 100 100     44 return if defined($this) && ($this+0 < 0);
378              
379 9         38 require Carp;
380 9         20 &Carp::confess( _failure_msg($name) );
381             }
382              
383              
384             =head2 assert_nonzero_integer( $this [, $name ] )
385              
386             Asserts that the numeric value of I<$this> is defined, an integer, and not zero.
387              
388             assert_nonzero_integer( 0 ); # FAIL
389             assert_nonzero_integer( -14 ); # pass
390             assert_nonzero_integer( '14.' ); # FAIL
391              
392             =cut
393              
394             sub assert_nonzero_integer($;$) {
395 10     10 1 4847 my $this = shift;
396 10         13 my $name = shift;
397              
398 10 100 100     68 if ( defined($this) && ($this =~ $INTEGER) ) {
399 3 100       9 return if $this != 0;
400             }
401              
402 8         29 require Carp;
403 8         15 &Carp::confess( _failure_msg($name) );
404             }
405              
406              
407             =head2 assert_positive_integer( $this [, $name ] )
408              
409             Asserts that the numeric value of I<$this> is defined, an integer and greater than zero.
410              
411             assert_positive_integer( 0 ); # FAIL
412             assert_positive_integer( -14 ); # FAIL
413             assert_positive_integer( '14.' ); # FAIL
414             assert_positive_integer( '14' ); # pass
415              
416             =cut
417              
418             sub assert_positive_integer($;$) {
419 11     11 1 5649 my $this = shift;
420 11         11 my $name = shift;
421              
422 11 100 100     76 if ( defined($this) && ($this =~ $INTEGER) ) {
423 4 100       12 return if $this > 0;
424             }
425              
426 9         36 require Carp;
427 9         16 &Carp::confess( _failure_msg($name) );
428             }
429              
430              
431             =head2 assert_nonnegative_integer( $this [, $name ] )
432              
433             Asserts that the numeric value of I<$this> is defined, an integer, and not less than zero.
434              
435             assert_nonnegative_integer( 0 ); # pass
436             assert_nonnegative_integer( -14 ); # FAIL
437             assert_nonnegative_integer( '14.' ); # FAIL
438              
439             =cut
440              
441             sub assert_nonnegative_integer($;$) {
442 10     10 1 4809 my $this = shift;
443 10         16 my $name = shift;
444              
445 10 100 100     85 if ( defined($this) && ($this =~ $INTEGER) ) {
446 3 100       11 return if $this >= 0;
447             }
448              
449 8         43 require Carp;
450 8         22 &Carp::confess( _failure_msg($name) );
451             }
452              
453              
454             =head2 assert_negative_integer( $this [, $name ] )
455              
456             Asserts that the numeric value of I<$this> is defined, an integer, and less than zero.
457              
458             assert_negative_integer( 0 ); # FAIL
459             assert_negative_integer( -14 ); # pass
460             assert_negative_integer( '14.' ); # FAIL
461              
462             =cut
463              
464             sub assert_negative_integer($;$) {
465 11     11 1 5396 my $this = shift;
466 11         14 my $name = shift;
467              
468 11 100 100     76 if ( defined($this) && ($this =~ $INTEGER) ) {
469 3 100       7 return if $this < 0;
470             }
471              
472 10         40 require Carp;
473 10         38 &Carp::confess( _failure_msg($name) );
474             }
475              
476              
477             =head1 REFERENCE ASSERTIONS
478              
479             =head2 assert_isa( $this, $type [, $name ] )
480              
481             Asserts that I<$this> is an object of type I<$type>.
482              
483             =cut
484              
485             sub assert_isa($$;$) {
486 6     6 1 3200 my $this = shift;
487 6         10 my $type = shift;
488 6         8 my $name = shift;
489              
490             # The assertion is true if
491             # 1) For objects, $this is of class $type or of a subclass of $type
492             # 2) For non-objects, $this is a reference to a HASH, SCALAR, ARRAY, etc.
493              
494 6 100 66     35 return if Scalar::Util::blessed( $this ) && $this->isa( $type );
495 4 100       11 return if ref($this) eq $type;
496              
497 3         14 require Carp;
498 3         8 &Carp::confess( _failure_msg($name) );
499             }
500              
501              
502             =head2 assert_isa_in( $obj, \@types [, $description] )
503              
504             Assert that the blessed C<$obj> isa one of the types in C<\@types>.
505              
506             assert_isa_in( $obj, [ 'My::Foo', 'My::Bar' ], 'Must pass either a Foo or Bar object' );
507              
508             =cut
509              
510             sub assert_isa_in($$;$) {
511 17     17 1 9233 my $obj = shift;
512 17         19 my $types = shift;
513 17         17 my $name = shift;
514              
515 17 100       61 if ( Scalar::Util::blessed($obj) ) {
516 12         33 for ( @{$types} ) {
  12         17  
517 12 100       54 return if $obj->isa($_);
518             }
519             }
520              
521 8         35 require Carp;
522 8         16 &Carp::confess( _failure_msg($name) );
523             }
524              
525              
526             =head2 assert_empty( $this [, $name ] )
527              
528             I<$this> must be a ref to either a hash or an array. Asserts that that
529             collection contains no elements. Will assert (with its own message,
530             not I<$name>) unless given a hash or array ref. It is OK if I<$this> has
531             been blessed into objecthood, but the semantics of checking an object to see
532             if it does not have keys (for a hashref) or returns 0 in scalar context (for
533             an array ref) may not be what you want.
534              
535             assert_empty( 0 ); # FAIL
536             assert_empty( 'foo' ); # FAIL
537             assert_empty( undef ); # FAIL
538             assert_empty( {} ); # pass
539             assert_empty( [] ); # pass
540             assert_empty( {foo=>1} );# FAIL
541             assert_empty( [1,2,3] ); # FAIL
542              
543             =cut
544              
545             sub assert_empty($;$) {
546 13     13 1 6239 my $ref = shift;
547 13         16 my $name = shift;
548              
549 13         12 my $underlying_type;
550 13 100       32 if ( Scalar::Util::blessed( $ref ) ) {
551 6         11 $underlying_type = Scalar::Util::reftype( $ref );
552             }
553             else {
554 7         10 $underlying_type = ref( $ref );
555             }
556              
557 13         18 my $why;
558             my $n;
559 13 100       27 if ( $underlying_type eq 'HASH' ) {
    100          
560 5 100       5 return if scalar keys %{$ref} == 0;
  5         16  
561 3         4 $n = scalar keys %{$ref};
  3         4  
562 3         6 $why = "Hash contains $n key";
563             }
564             elsif ( $underlying_type eq 'ARRAY' ) {
565 5 100       4 return if @{$ref} == 0;
  5         15  
566 3         5 $n = scalar @{$ref};
  3         4  
567 3         5 $why = "Array contains $n element";
568             }
569             else {
570 3         4 $why = 'Argument is not a hash or array.';
571             }
572              
573 9 100 100     26 $why .= 's' if $n && ($n>1);
574 9         10 $why .= '.';
575              
576 9         35 require Carp;
577 9         18 &Carp::confess( _failure_msg($name, $why) );
578             }
579              
580              
581             =head2 assert_nonempty( $this [, $name ] )
582              
583             I<$this> must be a ref to either a hash or an array. Asserts that that
584             collection contains at least 1 element. Will assert (with its own message,
585             not I<$name>) unless given a hash or array ref. It is OK if I<$this> has
586             been blessed into objecthood, but the semantics of checking an object to see
587             if it has keys (for a hashref) or returns >0 in scalar context (for an array
588             ref) may not be what you want.
589              
590             assert_nonempty( 0 ); # FAIL
591             assert_nonempty( 'foo' ); # FAIL
592             assert_nonempty( undef ); # FAIL
593             assert_nonempty( {} ); # FAIL
594             assert_nonempty( [] ); # FAIL
595             assert_nonempty( {foo=>1} );# pass
596             assert_nonempty( [1,2,3] ); # pass
597              
598             =cut
599              
600             sub assert_nonempty($;$) {
601 13     13 1 7747 my $ref = shift;
602 13         16 my $name = shift;
603              
604 13         14 my $underlying_type;
605 13 100       30 if ( Scalar::Util::blessed( $ref ) ) {
606 4         8 $underlying_type = Scalar::Util::reftype( $ref );
607             }
608             else {
609 9         13 $underlying_type = ref( $ref );
610             }
611              
612 13         15 my $why;
613             my $n;
614 13 100       32 if ( $underlying_type eq 'HASH' ) {
    100          
615 4 100       4 return if scalar keys %{$ref} > 0;
  4         15  
616 2         3 $why = "Hash contains 0 keys.";
617             }
618             elsif ( $underlying_type eq 'ARRAY' ) {
619 4 100       4 return if scalar @{$ref} > 0;
  4         12  
620 2         4 $why = "Array contains 0 elements.";
621             }
622             else {
623 5         7 $why = 'Argument is not a hash or array.';
624             }
625              
626 9         36 require Carp;
627 9         20 &Carp::confess( _failure_msg($name, $why) );
628             }
629              
630              
631             =head2 assert_nonref( $this [, $name ] )
632              
633             Asserts that I<$this> is not undef and not a reference.
634              
635             =cut
636              
637             sub assert_nonref($;$) {
638 5     5 1 1800 my $this = shift;
639 5         6 my $name = shift;
640              
641 5         10 assert_defined( $this, $name );
642 4 100       11 return unless ref( $this );
643              
644 1         4 require Carp;
645 1         3 &Carp::confess( _failure_msg($name) );
646             }
647              
648              
649             =head2 assert_hashref( $ref [,$name] )
650              
651             Asserts that I<$ref> is defined, and is a reference to a (possibly empty) hash.
652              
653             B This method returns I for objects, even those whose underlying
654             data is a hashref. This is as it should be, under the assumptions that:
655              
656             =over 4
657              
658             =item (a)
659              
660             you shouldn't rely on the underlying data structure of a particular class, and
661              
662             =item (b)
663              
664             you should use C instead.
665              
666             =back
667              
668             =cut
669              
670             sub assert_hashref($;$) {
671 7     7 1 3024 my $ref = shift;
672 7         11 my $name = shift;
673              
674 7 100 66     34 if ( ref($ref) eq 'HASH' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'HASH' )) ) {
      66        
675 3         9 return;
676             }
677              
678 4         17 require Carp;
679 4         10 &Carp::confess( _failure_msg($name) );
680             }
681              
682              
683             =head2 assert_hashref_nonempty( $ref [,$name] )
684              
685             Asserts that I<$ref> is defined and is a reference to a hash with at
686             least one key/value pair.
687              
688             =cut
689              
690             sub assert_hashref_nonempty($;$) {
691 10     10 1 5856 my $ref = shift;
692 10         14 my $name = shift;
693              
694 10 100 66     45 if ( ref($ref) eq 'HASH' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'HASH' )) ) {
      66        
695 6 100       9 return if scalar keys %{$ref} > 0;
  6         21  
696             }
697              
698 7         29 require Carp;
699 7         13 &Carp::confess( _failure_msg($name) );
700             }
701              
702              
703             =head2 assert_arrayref( $ref [, $name] )
704              
705             =head2 assert_listref( $ref [,$name] )
706              
707             Asserts that I<$ref> is defined, and is a reference to an array, which
708             may or may not be empty.
709              
710             B The same caveat about objects whose underlying structure is a
711             hash (see C) applies here; this method returns false
712             even for objects whose underlying structure is an array.
713              
714             C is an alias for C and may go away in
715             the future. Use C instead.
716              
717             =cut
718              
719             sub assert_arrayref($;$) {
720 13     13 1 7881 my $ref = shift;
721 13         21 my $name = shift;
722              
723 13 100 66     87 if ( ref($ref) eq 'ARRAY' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'ARRAY' )) ) {
      66        
724 5         14 return;
725             }
726              
727 8         41 require Carp;
728 8         24 &Carp::confess( _failure_msg($name) );
729             }
730             *assert_listref = *assert_arrayref;
731              
732              
733             =head2 assert_arrayref_nonempty( $ref [, $name] )
734              
735             Asserts that I<$ref> is reference to an array that has at least one element in it.
736              
737             =cut
738              
739             sub assert_arrayref_nonempty($;$) {
740 11     11 1 5513 my $ref = shift;
741 11         15 my $name = shift;
742              
743 11 100 66     56 if ( ref($ref) eq 'ARRAY' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'ARRAY' )) ) {
      66        
744 7 100       9 return if scalar @{$ref} > 0;
  7         45  
745             }
746              
747 7         32 require Carp;
748 7         17 &Carp::confess( _failure_msg($name) );
749             }
750              
751              
752             =head2 assert_aoh( $ref [, $name ] )
753              
754             Verifies that C<$array> is an arrayref, and that every element is a hashref.
755              
756             The array C<$array> can be an empty arraref and the assertion will pass.
757              
758             =cut
759              
760             sub assert_aoh {
761 8     8 1 3313 my $ref = shift;
762 8         9 my $name = shift;
763              
764 8         8 my $ok = 0;
765 8 100 66     41 if ( ref($ref) eq 'ARRAY' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'ARRAY' )) ) {
      66        
766 4         5 $ok = 1;
767 4         4 for my $val ( @{$ref} ) {
  4         10  
768 5 50 33     17 if ( not ( ref($val) eq 'HASH' || (Scalar::Util::blessed( $val) && $val->isa( 'HASH' )) ) ) {
      66        
769 2         3 $ok = 0;
770 2         3 last;
771             }
772             }
773             }
774              
775 8 100       16 return if $ok;
776              
777 6         25 require Carp;
778 6         13 &Carp::confess( _failure_msg($name) );
779             }
780              
781              
782             =head2 assert_coderef( $ref [,$name] )
783              
784             Asserts that I<$ref> is defined, and is a reference to a closure.
785              
786             =cut
787              
788             sub assert_coderef($;$) {
789 7     7 1 3417 my $ref = shift;
790 7         9 my $name = shift;
791              
792 7 100 66     55 if ( ref($ref) eq 'CODE' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'CODE' )) ) {
      66        
793 2         6 return;
794             }
795              
796 5         27 require Carp;
797 5         17 &Carp::confess( _failure_msg($name) );
798             }
799              
800              
801             =head1 TYPE-SPECIFIC ASSERTIONS
802              
803             =head2 assert_datetime( $date )
804              
805             Asserts that C<$date> is a DateTime object.
806              
807             =cut
808              
809             sub assert_datetime($;$) {
810 0     0 1 0 my $ref = shift;
811 0         0 my $name = shift;
812              
813 0 0 0     0 if ( ref($ref) eq 'DateTime' || (Scalar::Util::blessed( $ref ) && $ref->isa( 'DateTime' )) ) {
      0        
814 0         0 return;
815             }
816              
817 0         0 require Carp;
818 0         0 &Carp::confess( _failure_msg($name) );
819             }
820              
821              
822             =head1 SET AND HASH MEMBERSHIP
823              
824             =head2 assert_in( $string, \@inlist [,$name] );
825              
826             Asserts that I<$string> matches one of the elements of I<\@inlist>.
827             I<$string> may be undef.
828              
829             I<\@inlist> must be an array reference of non-ref strings. If any
830             element is a reference, the assertion fails.
831              
832             =cut
833              
834             sub assert_in($$;$) {
835 12     12 1 5661 my $needle = shift;
836 12         13 my $haystack = shift;
837 12         12 my $name = shift;
838              
839 12         13 my $found = 0;
840              
841             # String has to be a non-ref scalar, or undef.
842 12 50       21 if ( !ref($needle) ) {
843              
844             # Target list has to be an array...
845 12 100 33     33 if ( ref($haystack) eq 'ARRAY' || (Scalar::Util::blessed( $haystack ) && $haystack->isa( 'ARRAY' )) ) {
      66        
846              
847             # ... and all elements have to be non-refs.
848 10         11 my $elements_ok = 1;
849 10         10 foreach my $element (@{$haystack}) {
  10         12  
850 28 100       38 if ( ref($element) ) {
851 1         1 $elements_ok = 0;
852 1         2 last;
853             }
854             }
855              
856             # Now we can actually do the search.
857 10 100       18 if ( $elements_ok ) {
858 9 100       12 if ( defined($needle) ) {
859 7         7 foreach my $element (@{$haystack}) {
  7         18  
860 17 100       24 if ( $needle eq $element ) {
861 5         6 $found = 1;
862 5         7 last;
863             }
864             }
865             }
866             else {
867 2         3 foreach my $element (@{$haystack}) {
  2         2  
868 5 100       9 if ( !defined($element) ) {
869 1         1 $found = 1;
870 1         2 last;
871             }
872             }
873             }
874             }
875             }
876             }
877              
878 12 100       20 return if $found;
879              
880 6         25 require Carp;
881 6         11 &Carp::confess( _failure_msg($name) );
882             }
883              
884              
885             =head2 assert_exists( \%hash, $key [,$name] )
886              
887             =head2 assert_exists( \%hash, \@keylist [,$name] )
888              
889             Asserts that I<%hash> is indeed a hash, and that I<$key> exists in
890             I<%hash>, or that all of the keys in I<@keylist> exist in I<%hash>.
891              
892             assert_exists( \%custinfo, 'name', 'Customer has a name field' );
893              
894             assert_exists( \%custinfo, [qw( name addr phone )],
895             'Customer has name, address and phone' );
896              
897             =cut
898              
899             sub assert_exists($$;$) {
900 10     10 1 3992 my $hash = shift;
901 10         15 my $key = shift;
902 10         11 my $name = shift;
903              
904 10         10 my $ok = 0;
905              
906 10 50 0     23 if ( ref($hash) eq 'HASH' || (Scalar::Util::blessed( $hash ) && $hash->isa( 'HASH' )) ) {
      33        
907 10 100       18 if ( defined($key) ) {
908 9 100       19 if ( ref($key) eq 'ARRAY' ) {
    100          
909 5         5 $ok = (@{$key} > 0);
  5         9  
910 5         6 for ( @{$key} ) {
  5         8  
911 7 100       14 if ( !exists( $hash->{$_} ) ) {
912 2         2 $ok = 0;
913 2         3 last;
914             }
915             }
916             }
917             elsif ( !ref($key) ) {
918 3         4 $ok = exists( $hash->{$key} );
919             }
920             else {
921 1         2 $ok = 0;
922             }
923             }
924             }
925              
926 10 100       19 return if $ok;
927              
928 6         25 require Carp;
929 6         13 &Carp::confess( _failure_msg($name) );
930             }
931              
932              
933             =head2 assert_lacks( \%hash, $key [,$name] )
934              
935             =head2 assert_lacks( \%hash, \@keylist [,$name] )
936              
937             Asserts that I<%hash> is indeed a hash, and that I<$key> does NOT exist
938             in I<%hash>, or that none of the keys in I<@keylist> exist in I<%hash>.
939             The list C<@keylist> cannot be empty.
940              
941             assert_lacks( \%users, 'root', 'Root is not in the user table' );
942              
943             assert_lacks( \%users, [qw( root admin nobody )], 'No bad usernames found' );
944              
945             =cut
946              
947             sub assert_lacks($$;$) {
948 6     6 1 2534 my $hash = shift;
949 6         10 my $key = shift;
950 6         6 my $name = shift;
951              
952 6         8 my $ok = 0;
953              
954 6 50 0     18 if ( ref($hash) eq 'HASH' || (Scalar::Util::blessed( $hash ) && $hash->isa( 'HASH' )) ) {
      33        
955 6 50       11 if ( defined($key) ) {
956 6 100       16 if ( ref($key) eq 'ARRAY' ) {
    50          
957 4         5 $ok = (@{$key} > 0);
  4         8  
958 4         5 for ( @{$key} ) {
  4         8  
959 6 100       13 if ( exists( $hash->{$_} ) ) {
960 1         2 $ok = 0;
961 1         2 last;
962             }
963             }
964             }
965             elsif ( !ref($key) ) {
966 2         4 $ok = !exists( $hash->{$key} );
967             }
968             else {
969 0         0 $ok = 0;
970             }
971             }
972             }
973              
974 6 100       18 return if $ok;
975              
976 3         13 require Carp;
977 3         7 &Carp::confess( _failure_msg($name) );
978             }
979              
980              
981             =head2 assert_all_keys_in( \%hash, \@names [, $name ] )
982              
983             Asserts that each key in C<%hash> is in the list of C<@names>.
984              
985             This is used to ensure that there are no extra keys in a given hash.
986              
987             assert_all_keys_in( $obj, [qw( height width depth )], '$obj can only contain height, width and depth keys' );
988              
989             You can pass an empty list of C<@names>.
990              
991             =cut
992              
993             sub assert_all_keys_in($$;$) {
994 7     7 1 4102 my $hash = shift;
995 7         10 my $keys = shift;
996 7         9 my $name = shift;
997              
998 7         9 my $why;
999 7         10 my $ok = 0;
1000 7 100 33     32 if ( ref($hash) eq 'HASH' || (Scalar::Util::blessed( $hash ) && $hash->isa( 'HASH' )) ) {
      66        
1001 6 100       12 if ( ref($keys) eq 'ARRAY' ) {
1002 5         8 $ok = 1;
1003 5         10 my %keys = map { $_ => 1 } @{$keys};
  9         20  
  5         9  
1004 5         6 for my $key ( keys %{$hash} ) {
  5         15  
1005 8 100       31 if ( !exists $keys{$key} ) {
1006 2         4 $ok = 0;
1007 2         5 $why = qq{Key "$key" is not a valid key.};
1008 2         5 last;
1009             }
1010             }
1011             }
1012             else {
1013 1         2 $why = 'Argument for array of keys is not an arrayref.';
1014             }
1015             }
1016             else {
1017 1         3 $why = 'Argument for hash is not a hashref.';
1018             }
1019              
1020 7 100       22 return if $ok;
1021              
1022 4         111 require Carp;
1023 4         13 &Carp::confess( _failure_msg($name, $why) );
1024             }
1025              
1026              
1027             =head2 assert_keys_are( \%hash, \@keys [, $name ] )
1028              
1029             Asserts that the keys for C<%hash> are exactly C<@keys>, no more and no less.
1030              
1031             =cut
1032              
1033             sub assert_keys_are($$;$) {
1034 10     10 1 8921 my $hash = shift;
1035 10         14 my $keys = shift;
1036 10         10 my $name = shift;
1037              
1038 10         12 my $why;
1039 10         13 my $ok = 0;
1040 10 100 33     37 if ( ref($hash) eq 'HASH' || (Scalar::Util::blessed( $hash ) && $hash->isa( 'HASH' )) ) {
      66        
1041 9 100       17 if ( ref($keys) eq 'ARRAY' ) {
1042 8         9 my %keys = map { $_ => 1 } @{$keys};
  18         36  
  8         12  
1043              
1044             # First check all the keys are allowed.
1045 8         14 $ok = 1;
1046 8         12 for my $key ( keys %{$hash} ) {
  8         19  
1047 14 100       50 if ( !exists $keys{$key} ) {
1048 3         4 $ok = 0;
1049 3         7 $why = qq{Key "$key" is not a valid key.};
1050 3         4 last;
1051             }
1052             }
1053              
1054             # Now check that all the valid keys are represented.
1055 8         13 for my $key ( @{$keys} ) {
  8         10  
1056 14 100       27 if ( !exists $hash->{$key} ) {
1057 3         4 $ok = 0;
1058 3         16 $why = qq{Key "$key" is not in the hash.};
1059 3         7 last;
1060             }
1061             }
1062             }
1063             else {
1064 1         3 $why = 'Argument for array of keys is not an arrayref.';
1065             }
1066             }
1067             else {
1068 1         3 $why = 'Argument for hash is not a hashref.';
1069             }
1070              
1071 10 100       25 return if $ok;
1072              
1073 7         33 require Carp;
1074 7         15 &Carp::confess( _failure_msg($name, $why) );
1075             }
1076              
1077              
1078             =head1 CONTEXT ASSERTIONS
1079              
1080             =head2 assert_context_nonvoid( [$name] )
1081              
1082             Verifies that the function currently being executed has not been called
1083             in void context. This is to ensure the calling function is not ignoring
1084             the return value of the executing function.
1085              
1086             Given this function:
1087              
1088             sub something {
1089             ...
1090              
1091             assert_context_scalar();
1092              
1093             return $important_value;
1094             }
1095              
1096             These calls to C will pass:
1097              
1098             my $val = something();
1099             my @things = something();
1100              
1101             but this will fail:
1102              
1103             something();
1104              
1105             =cut
1106              
1107             sub assert_context_nonvoid(;$) {
1108 3     3 1 1267 my $name = shift;
1109              
1110 3         17 my $wantarray = (caller(1))[5];
1111              
1112 3 100       9 return if defined($wantarray);
1113              
1114 1         4 require Carp;
1115 1         4 &Carp::confess( _failure_msg($name) );
1116             }
1117              
1118              
1119             =head2 assert_context_scalar( [$name] )
1120              
1121             Verifies that the function currently being executed has been called in
1122             scalar context. This is to ensure the calling function is not ignoring
1123             the return value of the executing function.
1124              
1125             Given this function:
1126              
1127             sub something {
1128             ...
1129              
1130             assert_context_scalar();
1131              
1132             return $important_value;
1133             }
1134              
1135             This call to C will pass:
1136              
1137             my $val = something();
1138              
1139             but these will fail:
1140              
1141             something();
1142             my @things = something();
1143              
1144             =cut
1145              
1146             sub assert_context_scalar(;$) {
1147 3     3 1 1859 my $name = shift;
1148              
1149 3         22 my $wantarray = (caller(1))[5];
1150              
1151 3 100 100     19 return if defined($wantarray) && !$wantarray;
1152              
1153 2         13 require Carp;
1154 2         6 &Carp::confess( _failure_msg($name) );
1155             }
1156              
1157              
1158             =head1 UTILITY ASSERTIONS
1159              
1160             =head2 assert_fail( [$name] )
1161              
1162             Assertion that always fails. C is exactly the same
1163             as calling C, but it eliminates that case where you
1164             accidentally use C, which of course never fires.
1165              
1166             =cut
1167              
1168             sub assert_fail(;$) {
1169 1     1 1 63 require Carp;
1170 1         3 &Carp::confess( _failure_msg($_[0]) );
1171             }
1172              
1173              
1174             # Can't call confess() here or the stack trace will be wrong.
1175             sub _failure_msg {
1176 209     209   289 my $name = shift;
1177 209         265 my $why = shift;
1178              
1179 209         275 my $msg = 'Assertion';
1180 209 100       425 $msg .= " ($name)" if defined $name;
1181 209         353 $msg .= " failed!\n";
1182 209 100       379 $msg .= "$why\n" if defined($why);
1183              
1184 209         11366 return $msg;
1185             }
1186              
1187              
1188             =head1 COPYRIGHT & LICENSE
1189              
1190             Copyright 2005-2022 Andy Lester.
1191              
1192             This program is free software; you can redistribute it and/or modify
1193             it under the terms of the Artistic License version 2.0.
1194              
1195             =head1 ACKNOWLEDGEMENTS
1196              
1197             Thanks to
1198             Eric A. Zarko,
1199             Bob Diss,
1200             Pete Krawczyk,
1201             David Storrs,
1202             Dan Friedman,
1203             Allard Hoeve,
1204             Thomas L. Shinnick,
1205             and Leland Johnson
1206             for code and fixes.
1207              
1208             =cut
1209              
1210             1;