Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions lib/Test/Builder.pm
Original file line number Diff line number Diff line change
Expand Up @@ -939,14 +939,26 @@ sub unlike {

my %numeric_cmps = map { ( $_, 1 ) } ( "<", "<=", ">", ">=", "==", "!=", "<=>" );

# Bad, these are not comparison operators. Should we include more?
my %cmp_ok_bl = map { ( $_, 1 ) } ( "=", "+=", ".=", "x=", "^=", "|=", "||=", "&&=", "...");
# Allowlist of valid Perl comparison operators.
# Matches Test2::Tools::ClassicCompare::%OPS for consistency.
my %cmp_ok_al = map { ( $_, 1 ) } (
# numeric
"<", "<=", ">", ">=", "==", "!=", "<=>",
# string
"eq", "ne", "gt", "lt", "ge", "le", "cmp", "=~", "!~",
# logic
"&&", "||", "xor", "or", "and", "//",
# bitwise
"&", "|",
# match
"~~",
);

sub cmp_ok {
my( $self, $got, $type, $expect, $name ) = @_;
my $ctx = $self->ctx;

if ($cmp_ok_bl{$type}) {
if (!$cmp_ok_al{$type}) {
$ctx->throw("$type is not a valid comparison operator in cmp_ok()");
}

Expand Down
33 changes: 4 additions & 29 deletions t/Legacy/478-cmp_ok_hash.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,9 @@ my $got = 0;

cmp_ok($got, 'eq', $want, "Passes on correct comparison");

my ($res, @ok, @diag, @warn);
{
no warnings 'redefine';
local *Test::Builder::ok = sub {
my ($tb, $ok, $name) = @_;
push @ok => $ok;
return $ok;
};
local *Test::Builder::diag = sub {
my ($tb, @d) = @_;
push @diag => @d;
};
local $SIG{__WARN__} = sub {
push @warn => @_;
};
$res = cmp_ok($got, '#eq', $want, "You shall not pass!");
}

ok(!$res, "Did not pass");

is(@ok, 1, "1 result");
ok(!$ok[0], "result is false");

# We only care that it mentions a syntax error.
like(join("\n" => @diag), qr/syntax error at \(eval in cmp_ok\)/, "Syntax error");

# We are not going to inspect the warning because it is not super predictable,
# and changes with eval specifics.
ok(@warn, "We got warnings");
# Invalid operator '#eq' should be rejected by the allowlist
my $threw = !eval { cmp_ok($got, '#eq', $want, "You shall not pass!"); 1 };
ok($threw, "Invalid operator throws");
like($@, qr/#eq is not a valid comparison operator in cmp_ok\(\)/, "Error message mentions invalid operator");

done_testing;
9 changes: 5 additions & 4 deletions t/Legacy/cmp_ok.t
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,19 @@ my @Tests = (
[1, '==', 2],
["a", "eq", "b"],
["a", "eq", "a"],
[1, "+", 1],
[1, "-", 1],

[$cmp, '==', 42],
[$cmp, 'eq', "foo"],
[$ify, 'eq', "bar"],
[$ify, "==", 23],

[$part, '!=', 0, 'expected: anything else'],

[1, "=", 0, "= is not a valid comparison operator in cmp_ok()"],
# Operators rejected by allowlist
[1, "=", 0, "= is not a valid comparison operator in cmp_ok()"],
[1, "+=", 0, "+= is not a valid comparison operator in cmp_ok()"],
[1, "+", 1, "+ is not a valid comparison operator in cmp_ok()"],
[1, "-", 1, "- is not a valid comparison operator in cmp_ok()"],
[1, "*", 1, "* is not a valid comparison operator in cmp_ok()"],
);

plan tests => scalar @Tests;
Expand Down