blob: 976d7a82e83f8b5d08c3e530f28735db803c551d [file] [log] [blame]
# -*- mode:perl -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
BEGIN {
use Config;
if (eval { require 5.007_002; } # for CLONE support
&& $Config{useithreads}
&& !$ENV{WANT_NO_THREADS})
{
require threads;
import threads;
}
else
{
exit 77;
}
}
use Automake::Condition qw/TRUE FALSE/;
use Automake::DisjConditions;
use Test::Simple tests => 5;
sub test_basics ()
{
my $true = new Automake::DisjConditions TRUE;
my $false = new Automake::DisjConditions FALSE;
my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
return threads->new (sub {
my $other = new Automake::Condition "COND3_FALSE";
my $another = new Automake::Condition "COND3_TRUE", "COND4_FALSE";
return threads->new (sub {
my $set1 = new Automake::DisjConditions $cond, $other;
return threads->new (sub {
my $set2 = new Automake::DisjConditions $other, $cond;
my $set3 = new Automake::DisjConditions FALSE, $another;
return 1 unless $set1 == $set2;
return 1 if $set1->false;
return 1 if $set1->true;
return 1 unless (new Automake::DisjConditions)->false;
return 1 if (new Automake::DisjConditions)->true;
return 1 unless $true->human eq 'TRUE';
return 1 unless $false->human eq 'FALSE';
return 1 unless $set1->human eq "(COND1 and !COND2) or (!COND3)";
return 1 unless $set2->human eq "(COND1 and !COND2) or (!COND3)";
my $one_cond_human = $set1->one_cond->human;
return 1 unless $one_cond_human eq "!COND3"
|| $one_cond_human eq "COND1 and !COND2";
return 1 unless $set1->string eq "COND1_TRUE COND2_FALSE | COND3_FALSE";
my $merged1 = $set1->merge ($set2);
my $merged2 = $set1->merge ($cond);
my $mult1 = $set1->multiply ($set3);
return threads->new (sub {
my $mult2 = $set1->multiply ($another);
return threads->new (sub {
return 1 unless $merged1->simplify->string eq "COND1_TRUE COND2_FALSE | COND3_FALSE";
return 1 unless $merged2->simplify->string eq "COND1_TRUE COND2_FALSE | COND3_FALSE";
return 1 unless $mult1->string eq "COND1_TRUE COND2_FALSE COND3_TRUE COND4_FALSE";
return 1 unless $mult1 == $mult2;
return 0;
})->join;
})->join;
})->join;
})->join;
})->join;
}
sub build_set (@)
{
my @conds = @_;
my @set = ();
for my $cond (@conds)
{
push @set, new Automake::Condition @$cond;
}
return new Automake::DisjConditions @set;
}
sub test_invert ()
{
my @tests = ([[["FALSE"]],
[["TRUE"]]],
[[["TRUE"]],
[["FALSE"]]],
[[["COND1_TRUE", "COND2_TRUE"],
["COND3_FALSE", "COND2_TRUE"]],
[["COND2_FALSE"],
["COND1_FALSE", "COND3_TRUE"]]],
[[["COND1_TRUE", "COND2_TRUE"],
["TRUE"]],
[["FALSE"]]],
[[["COND1_TRUE", "COND2_TRUE"],
["FALSE"]],
[["COND1_FALSE"],
["COND2_FALSE"]]],
[[["COND1_TRUE"],
["COND2_FALSE"]],
[["COND1_FALSE", "COND2_TRUE"]]]
);
for my $t (@tests)
{
my $set = build_set @{$t->[0]};
return 1
if threads->new(sub {
my $res = build_set @{$t->[1]};
my $inv = $set->invert;
if ($inv != $res)
{
print " (I) " . $set->string . "\n\t"
. $inv->string . ' != ' . $res->string . "\n";
return 1;
}
return 0
})-> join;
}
return 0;
}
sub test_simplify ()
{
my @tests = ([[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"]],
[["FOO_TRUE", "BAR_FALSE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["FOO_TRUE", "BAR_TRUE"]],
[["FOO_TRUE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["FOO_TRUE", "BAR_TRUE"],
["FOO_FALSE"]],
[["TRUE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["BAR_TRUE", "BAZ_TRUE"],
["BAR_FALSE", "BAZ_TRUE"]],
[["BAZ_TRUE"], ["FOO_TRUE", "BAR_FALSE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["BAR_TRUE", "BAZ_TRUE"],
["BAR_FALSE", "BAZ_TRUE"],
["FOO_FALSE"]],
[["FOO_FALSE"], ["BAZ_TRUE"], ["BAR_FALSE"]]],
[[["B_TRUE"],
["A_FALSE", "B_TRUE"]],
[["B_TRUE"]]],
[[["B_TRUE"],
["A_FALSE", "B_FALSE", "C_TRUE"],
["A_FALSE", "B_FALSE", "C_FALSE"]],
[["A_FALSE"], ["B_TRUE"]]],
[[["B_TRUE"],
["A_FALSE", "B_FALSE", "C_TRUE"],
["A_FALSE", "B_FALSE", "C_FALSE"],
["A_TRUE", "B_FALSE"]],
[["TRUE"]]],
[[["A_TRUE", "B_TRUE"],
["A_TRUE", "B_FALSE"],
["A_TRUE", "C_FALSE", "D_FALSE"]],
[["A_TRUE"]]],
[[["A_FALSE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
["A_FALSE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
["A_FALSE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
["A_FALSE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
["A_TRUE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
["A_TRUE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"]],
[ ["B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
["B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
["B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
["B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"]]],
[[["A_FALSE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
["A_FALSE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
["A_FALSE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
["A_FALSE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_FALSE", "D_FALSE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE", "E_TRUE"],
["A_TRUE", "B_FALSE", "C_TRUE", "D_TRUE", "E_TRUE"],
["A_TRUE", "B_FALSE", "C_FALSE", "D_TRUE", "E_FALSE"],
["A_FALSE", "B_FALSE", "C_FALSE", "D_FALSE", "E_FALSE"],
["A_FALSE", "B_FALSE", "C_TRUE", "D_FALSE", "E_TRUE"],
["A_FALSE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"],
["A_FALSE", "B_TRUE", "C_FALSE", "D_TRUE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_FALSE", "D_TRUE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"],
["A_TRUE", "B_FALSE", "C_TRUE", "D_FALSE", "E_TRUE"],
["A_TRUE", "B_FALSE", "C_FALSE", "D_FALSE", "E_FALSE"]],
[["C_FALSE", "E_FALSE"],
["C_TRUE", "E_TRUE"]]],
[[["A_FALSE"],
["A_TRUE", "B_FALSE"],
["A_TRUE", "B_TRUE", "C_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE", "F_FALSE"],
["A_TRUE", "B_TRUE", "C_TRUE", "D_TRUE", "E_TRUE"]],
[["TRUE"]]],
# Simplify should work with up to 31 variables.
[[["V01_TRUE", "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
"V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
"V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
"V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
"V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
"V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
"V31_TRUE"],
["V01_TRUE", "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
"V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
"V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
"V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
"V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
"V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
"V31_FALSE"],
["V01_FALSE","V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
"V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
"V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
"V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
"V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
"V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
"V31_TRUE"],
["V01_FALSE","V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
"V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
"V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
"V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
"V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
"V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE",
"V31_FALSE"]],
[[ "V02_TRUE", "V03_TRUE", "V04_TRUE", "V05_TRUE",
"V06_TRUE", "V07_TRUE", "V08_TRUE", "V09_TRUE", "V10_TRUE",
"V11_TRUE", "V12_TRUE", "V13_TRUE", "V14_TRUE", "V15_TRUE",
"V16_TRUE", "V17_TRUE", "V18_TRUE", "V19_TRUE", "V20_TRUE",
"V21_TRUE", "V22_TRUE", "V23_TRUE", "V24_TRUE", "V25_TRUE",
"V26_TRUE", "V27_TRUE", "V28_TRUE", "V29_TRUE", "V30_TRUE"
]]]);
for my $t (@tests)
{
my $set = build_set @{$t->[0]};
return 1
if threads->new(sub {
my $res = build_set @{$t->[1]};
return threads->new(sub {
# Make sure simplify() yields the expected result.
my $sim = $set->simplify;
return threads->new(sub {
if ($sim != $res)
{
print " (S1) " . $set->string . "\n\t"
. $sim->string . ' != ' . $res->string . "\n";
return 1;
}
# Make sure simplify() is idempotent.
my $sim2 = $sim->simplify;
return threads->new(sub {
if ($sim2 != $sim)
{
print " (S2) " . $sim->string . "\n\t"
. $sim2->string . ' != ' . $sim->string . "\n";
return 1;
}
# Also exercise invert() while we are at it.
my $inv1 = $set->invert->simplify;
return threads->new(sub {
my $inv2 = $sim->invert->simplify;
return threads->new(sub {
if ($inv1 != $inv2)
{
print " (S3) " . $set->string . ", " . $sim->string . "\n\t"
. $inv1->string . ' -= ' . $inv2->string . "\n";
return 1;
}
})->join;
})->join;
})->join;
})->join;
})->join;
})->join;
}
return 0;
}
sub test_sub_conditions ()
{
my @tests = ([[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["FOO_FALSE"]],
["FOO_TRUE"],
[["BAR_FALSE", "BAZ_FALSE"],
["BAR_FALSE", "BAZ_TRUE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["FOO_FALSE"]],
["FOO_TRUE", "BAR_FALSE"],
[["BAZ_FALSE"],
["BAZ_TRUE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAR_FALSE", "BAZ_TRUE"],
["FOO_FALSE"]],
["FOO_TRUE", "BAR_TRUE"],
[["FALSE"]]],
[[["FOO_TRUE", "BAR_FALSE", "BAZ_FALSE"],
["FOO_TRUE", "BAZ_TRUE"],
["FOO_FALSE"]],
["FOO_TRUE", "BAR_TRUE"],
[["BAZ_TRUE"]]],
[[["FOO_TRUE", "BAR_FALSE"],
["FOO_TRUE", "BAR_TRUE"]],
["FOO_TRUE", "BAR_TRUE"],
[["TRUE"]]],
[[["TRUE"]],
["TRUE"],
[["TRUE"]]],
[[["FALSE"]],
["TRUE"],
[["FALSE"]]],
[[["FALSE"]],
["FALSE"],
[["FALSE"]]]);
for my $t (@tests)
{
my $t1 = build_set @{$t->[0]};
return 1
if threads->new(sub {
my $t2 = new Automake::Condition @{$t->[1]};
return threads->new(sub {
my $t3 = build_set @{$t->[2]};
return threads->new(sub {
# Make sure sub_conditions() yields the expected result.
my $s = $t1->sub_conditions ($t2);
threads->new(sub {
if ($s != $t3)
{
print " (SC) " . $t1->string . "\n\t"
. $s->string . ' != ' . $t3->string . "\n";
return 1;
}
})->join;
})->join;
})->join;
})->join;
}
}
sub test_ambig ()
{
my @tests = ([[["TRUE"]],
["TRUE"],
"multiply defined"],
[[["C1_TRUE"]],
["C1_TRUE"],
"multiply defined"],
[[["TRUE"]],
["C1_FALSE"],
"which includes"],
[[["C1_TRUE"]],
["C1_TRUE", "C2_TRUE"],
"which includes"],
[[["C1_TRUE", "C2_TRUE"]],
["C2_TRUE"],
"which is included in"],
[[["C1_TRUE"]],
["C2_TRUE"],
''],
[[["C1_TRUE"],
["C2_FALSE"]],
["C1_FALSE", "C2_TRUE"],
'']);
my $failed = 0;
for my $t (@tests)
{
my $t1 = build_set @{$t->[0]};
$failed = 1
if threads->new(sub {
my $t2 = new Automake::Condition @{$t->[1]};
my $t3 = $t->[2];
return threads->new(sub {
my ($ans, $cond) = $t1->ambiguous_p ("FOO", $t2);
return threads->new(sub {
if ($t3 && $ans !~ /FOO.*$t3/)
{
print " (A1) " . $t1->string . " vs. " . $t2->string . "\n\t"
. "Error message '$ans' does not match '$t3'\n";
return 1;
}
if (!$t3 && $ans ne '')
{
print " (A2) " . $t1->string . " vs. " . $t2->string . "\n\t"
. "Unexpected error message: $ans\n";
return 1;
}
})->join;
})->join;
})->join;
}
return $failed;
}
ok (test_basics == 0, 'Basic tests');
ok (test_invert == 0, 'Test inverts');
ok (test_simplify == 0, 'Test condition simplifications');
ok (test_sub_conditions == 0, 'Test sub conditions');
ok (test_ambig == 0, 'Test ambiguous conditions');