summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgregor herrmann <gregoa@debian.org>2024-03-09 16:10:37 +0100
committergregor herrmann <gregoa@debian.org>2024-03-09 16:10:37 +0100
commita326df3aeab6d5a890a2d2f67dbf2b5656006a30 (patch)
treec2631a04a0e6308057ff281d25131a12b236b943
parent7054aa026e8f0ed56509649d54291a4e9f6bd803 (diff)
parent24c8ec46da161d5dfa460e0e2ee48b1171203a57 (diff)
Update upstream source from tag 'upstream/2.4.0'
Update to upstream version '2.4.0' with Debian dir 3fc815fb076911ac7c075e53f6d5dd1d44a8579e
-rw-r--r--Changes14
-rw-r--r--MANIFEST1
-rw-r--r--META.json2
-rw-r--r--META.yml2
-rw-r--r--More.pm75
-rw-r--r--t/assert_arrayref_all.t65
-rw-r--r--t/assert_context_nonvoid.t61
-rw-r--r--t/assert_context_scalar.t69
-rw-r--r--t/test-coverage.t2
9 files changed, 273 insertions, 18 deletions
diff --git a/Changes b/Changes
index 996620b..d40c5be 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,20 @@
Revision history for Perl extension Carp::Assert::More.
+2.4.0 Mon Mar 4 21:54:07 CST 2024
+ [ENHANCEMENTS]
+ New function assert_arrayref_all() calls an assertion function for every element in the array.
+
+ my $aref_of_counts = get_counts();
+ assert_arrayref_all( $aref, \&assert_positive_integer, 'Counts are positive' );
+
+ assert_context_scalar() now provides a default message of
+ "function_name must be called in scalar context".
+
+ assert_context_nonvoid() now provide a default message of
+ "function_name must not be called in void context".
+
+
2.3.0 Tue May 30 21:52:20 CDT 2023
[ENHANCEMENTS]
Added assert_arrayref_of() to verify that all of the elements
diff --git a/MANIFEST b/MANIFEST
index 90f35e5..2060ad5 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -9,6 +9,7 @@ t/00-load.t
t/assert_all_keys_in.t
t/assert_aoh.t
t/assert_arrayref.t
+t/assert_arrayref_all.t
t/assert_arrayref_nonempty.t
t/assert_arrayref_of.t
t/assert_cmp.t
diff --git a/META.json b/META.json
index f70527e..78297eb 100644
--- a/META.json
+++ b/META.json
@@ -50,6 +50,6 @@
"https://opensource.org/licenses/artistic-license-2.0.php"
]
},
- "version" : "v2.3.0",
+ "version" : "v2.4.0",
"x_serialization_backend" : "JSON::PP version 2.27400"
}
diff --git a/META.yml b/META.yml
index 0ada80a..5134a6d 100644
--- a/META.yml
+++ b/META.yml
@@ -27,5 +27,5 @@ resources:
bugtracker: https://github.com/petdance/carp-assert-more/issues
homepage: https://github.com/petdance/carp-assert-more
license: https://opensource.org/licenses/artistic-license-2.0.php
-version: v2.3.0
+version: v2.4.0
x_serialization_backend: 'CPAN::Meta::YAML version 0.012'
diff --git a/More.pm b/More.pm
index f7d2098..f25b13f 100644
--- a/More.pm
+++ b/More.pm
@@ -15,12 +15,12 @@ Carp::Assert::More - Convenience assertions for common situations
=head1 VERSION
-Version 2.3.0
+Version 2.4.0
=cut
BEGIN {
- $VERSION = '2.3.0';
+ $VERSION = '2.4.0';
@ISA = qw(Exporter);
@EXPORT = qw(
assert_all_keys_in
@@ -28,6 +28,7 @@ BEGIN {
assert_arrayref
assert_arrayref_nonempty
assert_arrayref_of
+ assert_arrayref_all
assert_cmp
assert_coderef
assert_context_nonvoid
@@ -911,6 +912,57 @@ sub assert_arrayref_of($$;$) {
}
+=head2 assert_arrayref_all( $aref, $sub [, $name] )
+
+Asserts that I<$aref> is reference to an array that has at least one
+element in it. Each element of the array is passed to subroutine I<$sub>
+which is assumed to be an assertion.
+
+For example:
+
+ my $aref_of_counts = get_counts();
+ assert_arrayref_all( $aref, \&assert_positive_integer, 'Counts are positive' );
+
+Whatever is passed as I<$name>, a string saying "Element #N" will be
+appended, where N is the zero-based index of the array.
+
+=cut
+
+sub assert_arrayref_all($$;$) {
+ my $aref = shift;
+ my $sub = shift;
+ my $name = shift;
+
+ my @why;
+
+ assert_coderef( $sub, 'assert_arrayref_all requires a code reference' );
+
+ if ( ref($aref) eq 'ARRAY' || (Scalar::Util::blessed( $aref ) && $aref->isa( 'ARRAY' )) ) {
+ if ( @{$aref} ) {
+ my $inner_msg = defined($name) ? "$name: " : 'assert_arrayref_all: ';
+ my $n = 0;
+ for my $i ( @{$aref} ) {
+ $sub->( $i, "${inner_msg}Element #$n" );
+ ++$n;
+ }
+ }
+ else {
+ push @why, 'Array contains no elements';
+ }
+ }
+ else {
+ push @why, 'First argument to assert_arrayref_all was not an array';
+ }
+
+ if ( @why ) {
+ require Carp;
+ &Carp::confess( _failure_msg($name), @why );
+ }
+
+ return;
+}
+
+
=head2 assert_aoh( $ref [, $name ] )
Verifies that C<$array> is an arrayref, and that every element is a hashref.
@@ -1261,14 +1313,17 @@ but this will fail:
something();
+If the C<$name> argument is not passed, a default message of "<funcname>
+must not be called in void context" is provided.
+
=cut
sub assert_context_nonvoid(;$) {
- my $name = shift;
+ my @caller = caller(1);
- my $wantarray = (caller(1))[5];
+ return if defined($caller[5]);
- return if defined($wantarray);
+ my $name = shift // "$caller[3] must not be called in void context";
require Carp;
&Carp::confess( _failure_msg($name) );
@@ -1300,15 +1355,19 @@ but these will fail:
something();
my @things = something();
+If the C<$name> argument is not passed, a default message of "<funcname>
+must be called in scalar context" is provided.
+
=cut
sub assert_context_scalar(;$) {
- my $name = shift;
-
- my $wantarray = (caller(1))[5];
+ my @caller = caller(1);
+ my $wantarray = $caller[5];
return if defined($wantarray) && !$wantarray;
+ my $name = shift // "$caller[3] must be called in scalar context";
+
require Carp;
&Carp::confess( _failure_msg($name) );
}
diff --git a/t/assert_arrayref_all.t b/t/assert_arrayref_all.t
new file mode 100644
index 0000000..98af698
--- /dev/null
+++ b/t/assert_arrayref_all.t
@@ -0,0 +1,65 @@
+#!perl -Tw
+
+use warnings;
+use strict;
+
+use Test::More tests => 10;
+
+use Carp::Assert::More;
+
+use Test::Exception;
+
+my $FAILED = qr/Assertion failed/;
+
+my $api = \&assert_positive_integer;
+
+MAIN: {
+ # {} is not an arrayref.
+ throws_ok( sub { assert_arrayref_all( {}, $api ) }, $FAILED );
+
+ # A ref to a hash with stuff in it is not an arrayref.
+ my $ref = { foo => 'foo', bar => 'bar' };
+ throws_ok( sub { assert_arrayref_all( $ref, $api ) }, $FAILED );
+
+ # 3 is not an arrayref.
+ throws_ok( sub { assert_arrayref_all( 3, $api ) }, $FAILED );
+
+ # [] is a nonempty arrayref.
+ lives_ok( sub { assert_arrayref_all( [ 3 ], $api ) } );
+
+ # [] is an empty arrayref.
+ throws_ok( sub { assert_arrayref_all( [], $api ) }, $FAILED );
+
+ my @empty_ary = ();
+ throws_ok( sub { assert_arrayref_all( \@empty_ary, $api ) }, qr/Array contains no elements/ );
+
+ # A coderef is not an arrayref.
+ my $coderef = sub {};
+ throws_ok( sub { assert_arrayref_all( $coderef, $api ) }, $FAILED );
+
+ # An arrayref is not a coderef.
+ throws_ok( sub { assert_arrayref_all( \@empty_ary, [] ) }, qr/assert_arrayref_all requires a code reference/ );
+}
+
+
+MASS_ASSERTIONS: {
+ my @things = ( 1, 2, 4.3 );
+
+ throws_ok(
+ sub { assert_arrayref_all( \@things, $api ) },
+ qr/assert_arrayref_all: Element #2/,
+ 'Automatic name comes back OK'
+ );
+
+ throws_ok(
+ sub { assert_arrayref_all( \@things, $api, 'All gotta be posint' ) },
+ qr/All gotta be posint: Element #2/,
+ 'Automatic name comes back OK'
+ );
+
+ @things = 1..400;
+ assert_arrayref_all( \@things, $api, 'Must all be positive integer' );
+}
+
+
+exit 0;
diff --git a/t/assert_context_nonvoid.t b/t/assert_context_nonvoid.t
index f9ab5ac..34eadcc 100644
--- a/t/assert_context_nonvoid.t
+++ b/t/assert_context_nonvoid.t
@@ -4,12 +4,12 @@ use warnings;
use strict;
use 5.010;
-use Test::More tests => 3;
+use Test::More tests => 7;
use Carp::Assert::More;
sub important_function {
- assert_context_nonvoid( 'important_function must not be called in void context' );
+ assert_context_nonvoid( 'void is bad' );
return 2112;
}
@@ -36,7 +36,62 @@ is( $@, '' );
eval {
important_function();
};
-like( $@, qr/\QAssertion (important_function must not be called in void context) failed!/ );
+like( $@, qr/\QAssertion (void is bad) failed!/ );
+# Now we test the assertions with the default message that the function provides.
+sub crucial_function {
+ assert_context_nonvoid();
+
+ return 2112;
+}
+
+
+# Keep the value returned.
+eval {
+ my $x = crucial_function();
+};
+is( $@, '' );
+
+
+# Keep the value in an array.
+eval {
+ my @x = crucial_function();
+};
+is( $@, '' );
+
+
+# Ignore the value returned.
+eval {
+ crucial_function();
+};
+like( $@, qr/\QAssertion (main::crucial_function must not be called in void context) failed!/ );
+
+
+# Test the default function name through multiple levels in different packages.
+
+package Bingo::Bongo;
+
+use Carp::Assert::More;
+
+sub vital_function {
+ assert_context_nonvoid();
+}
+
+
+package Wango;
+
+sub uninteresting_function {
+ Bingo::Bongo::vital_function();
+}
+
+
+package main;
+
+# Ignore the value returned.
+eval {
+ Wango::uninteresting_function();
+};
+like( $@, qr/\QAssertion (Bingo::Bongo::vital_function must not be called in void context) failed!/ );
+
exit 0;
diff --git a/t/assert_context_scalar.t b/t/assert_context_scalar.t
index a0d4d1f..efb74ae 100644
--- a/t/assert_context_scalar.t
+++ b/t/assert_context_scalar.t
@@ -4,12 +4,15 @@ use warnings;
use strict;
use 5.010;
-use Test::More tests => 3;
+use Test::More tests => 7;
use Carp::Assert::More;
+
+# First we test the assertions with an explicit message passed.
+
sub important_function {
- assert_context_scalar( 'important_function must be called in scalar context' );
+ assert_context_scalar( 'non-scalar context is bad' );
return 2112;
}
@@ -29,14 +32,72 @@ is( $@, '' );
eval {
important_function();
};
-like( $@, qr/\QAssertion (important_function must be called in scalar context) failed!/ );
+like( $@, qr/\QAssertion (non-scalar context is bad) failed!/ );
# Call in list context.
eval {
my @x = important_function();
};
-like( $@, qr/\QAssertion (important_function must be called in scalar context) failed!/ );
+like( $@, qr/\QAssertion (non-scalar context is bad) failed!/ );
+
+
+# Now we test the assertions with the default message that the function provides.
+sub crucial_function {
+ assert_context_scalar();
+
+ return 2112;
+}
+
+
+local $@;
+$@ = '';
+
+# Keep the value returned.
+eval {
+ my $x = crucial_function();
+};
+is( $@, '' );
+
+
+# Ignore the value returned.
+eval {
+ crucial_function();
+};
+like( $@, qr/\QAssertion (main::crucial_function must be called in scalar context) failed!/ );
+# Call in list context.
+eval {
+ my @x = crucial_function();
+};
+like( $@, qr/\QAssertion (main::crucial_function must be called in scalar context) failed!/ );
+
+
+# Test the default function name through multiple levels in different packages.
+
+package Bingo::Bongo;
+
+use Carp::Assert::More;
+
+sub vital_function {
+ assert_context_scalar();
+}
+
+
+package Wango;
+
+sub uninteresting_function {
+ Bingo::Bongo::vital_function();
+}
+
+
+package main;
+
+# Ignore the value returned.
+eval {
+ Wango::uninteresting_function();
+};
+like( $@, qr/\QAssertion (Bingo::Bongo::vital_function must be called in scalar context) failed!/ );
+
exit 0;
diff --git a/t/test-coverage.t b/t/test-coverage.t
index 71494c1..a64e614 100644
--- a/t/test-coverage.t
+++ b/t/test-coverage.t
@@ -1,6 +1,6 @@
#!perl -Tw
-use Test::More tests => 41;
+use Test::More tests => 42;
use Carp::Assert::More;