# # Copyright (c) 2015-2021 Christian Jaeger, copying@christianjaeger.ch # # This is free software, offered under either the same terms as perl 5 # or the terms of the Artistic License version 2 or the terms of the # MIT License (Expat version). See the file COPYING.md that came # bundled with this file. # =head1 NAME FP::Equal::t -- tests for FP::Equal =head1 SYNOPSIS =head1 DESCRIPTION run by test suite =head1 NOTE This is alpha software! Read the status section in the package README or on the L. =cut package FP::Equal::t; use strict; use warnings; use warnings FATAL => 'uninitialized'; use FP::Equal ":all"; use Chj::TEST; # compare arguments both straight and swapped; if the results don't # match, return an array with both results sub tequals { @_ == 2 or die "wrong num arg"; my $x = equaln(@_); my $y = equaln(@_); if (defined $x) { if (defined $y) { if ($x eq $y) { return $x } } } else { if (defined $y) { [$x, $y] } else { undef } } } # from the synopsis use FP::List; use FP::Div qw(inc); TEST { equal [1, list(2, 3)], [1, list(1, 2)->map(\&inc)] } 1; TEST { equal [1, list(2, 3)], [1, list(1, 2)] } ''; TEST { equal [1, list(2, 3)], [1, list([], 3)] } undef; # 'systematic': TEST { equal undef, undef } 1; TEST { equal 1, undef } undef; # really give undef in TEST { equal undef, 1 } undef; # this case? TEST { equal 1, 1 } 1; TEST { equal 1, 0 } ''; TEST { equal 0, 1 } ''; TEST { equal [], 0 } undef; TEST { equal 0, [] } undef; TEST { equal [], [] } 1; TEST { my $v = []; equal $v, $v } 1; TEST { equal [], {} } undef; TEST { equal {}, {} } 1; TEST { equal {}, { a => 1 } } ''; TEST { equal { a => 2 }, { a => 1 } } ''; TEST { equal { a => 1 }, { b => 1 } } ''; TEST { equal { a => 1 }, { a => 1 } } 1; TEST { equal { a => 1, b => 2 }, { a => 1 } } ''; TEST { equal { a => 1, b => 2 }, { a => 1, b => 2 } } 1; TEST { equal { a => 1, b => 2 }, { a => 1, B => 2 } } ''; TEST { equal { a => 1, b => 2 }, { a => 1, b => 3 } } ''; TEST { equal { a => [1, 3] }, { a => [1, 2 + 1] } } 1; TEST { equal { a => [1, 3] }, { a => [1, 2] } } ''; TEST { equal "a", "b" } ''; TEST { equal "a", "a" } 1; # Perl just can't disambiguate between numbers and strings, don't try # to fight it? TEST { tequals "2", 2 } 1; TEST { tequals "2.0", 2.0 } ''; # Somewhere around version 5.20-5.21 Perl changed the formatting of # inf from "inf" to "Inf". Instead of trying to figure out which # version exactly changed it (if it's a precise version at all) try to # determine the right way automatically: sub positive_inf { my $inf = "inf" +0; $inf =~ /^\+?inf$/i or warn "positive_inf: got '$inf'"; $inf } sub negative_inf { my $inf = -&positive_inf(); $inf =~ /^-inf$/i or warn "negative_inf: got '$inf'"; $inf } TEST { tequals 1e+20000, positive_inf } 1; TEST { 1e+20000 == "inf" } 1; TEST { tequals 1 / (-1e+20000), 1 / (1e+20000) } 1; TEST { 1 / (-1e+20000) == 1 / (1e+20000) } 1; # so, no need to have both eq and == for those cases! # but that's not the case here, of course: TEST { -1e1000 == "-1e1000" } 1; TEST { -1e1000 eq "-1e1000" } ''; TEST { tequals -1e100, "-1e100" } ''; TEST { tequals -1e10000, "-1e10000" } ''; TEST { tequals -1e10000, negative_inf } 1; TEST { -1e10000 == "-inf" } 1; TEST { tequals 2, 2.0 } 1; # those are converted to the same value at # compile time. TEST { tequals "2", "2.0" } ''; # Weak typing is where the data (or context of the language) doesn't # say what it is. TEST { tequals \("foo"), \("f" . "oo") } 1; TEST { tequals \("foo"), \("bar") } ''; TEST { my $x = undef; my $y = undef; tequals \$x, \$y } 1; TEST { my $x = "foo"; my $y = undef; tequals \$x, \$y } undef; # globs TEST { tequals *foo::bar, "*foo::bar" } undef; TEST { tequals((*foo::bar) . "", "*foo::bar") } 1; TEST { tequals *foo, *FP::Equal::t::foo } 1; TEST { tequals \*foo, \*FP::Equal::t::foo } 1; TEST { tequals \(*foo::bar), \("*foo::bar") } undef; TEST { tequals \(*foo::bar), \(*foo::baz) } ''; TEST { tequals *foo, *bar } ''; # filehandles TEST { equal * STDIN {IO}, *STDIN{IO} } 1; # equal pointers TEST_EXCEPTION { equal * STDIN {IO}, *STDOUT{IO} } q{Can't locate object method "FP_Equal_equal" via package "IO::File"}; # encoding use utf8; { my ($s1, $s2); TEST { $s1 = "Smørrebrød"; $s2 = "Smørrebrød"; equal $s1, $s2 } 1; TEST { utf8::encode($s2); equal $s1, $s2 } ''; } # Lazy values, classes: use FP::Stream; use FP::Lazy; TEST { tequals "a", lazy { chr 65 + 32 } } 1; TEST { tequals stream(1, 2), stream(1, 2) } 1; TEST { tequals stream(1, 2), lazy { cons 1, stream(2) } } 1; TEST { tequals stream(1, 2), cons 1, stream(2) } 1; # only one of the arguments lazy: TEST { tequals lazy { 2 + 1 }, 1 + 2 } 1; TEST { tequals lazy { [2 + 1] }, [lazy { 1 + 2 }] } 1; TEST { tequals lazy { [2 + 1] }, [lazy { 1 + 3 }] } ''; TEST { tequals lazy { 2 + 1 }, [1 + 2] } undef; TEST { tequals lazy { [2 + 1] }, 1 + 2 } undef; # does it force identical promises? my ($a, $b, $sideeffect); TEST { $sideeffect = 0; $a = lazy { $sideeffect++; 33 * 3 }; $b = $a; tequals $a, $b } 1; TEST {$sideeffect} 0; TEST { $sideeffect = 0; $a = lazy { $sideeffect++; 33 * 3 }; $b = lazy { $sideeffect++; 33 * 3 }; tequals $a, $b } 1; TEST {$sideeffect} 2; # lazy and undef or non-references: TEST { tequals lazy {undef}, undef } 1; TEST { tequals lazy {"a"}, "a" } 1; TEST { tequals lazy {"a"}, undef } undef; TEST { tequals lazy {undef}, "a" } undef; 1