# Copyright (C) 2001-2023 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 . 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/; sub test_basics () { my @tests = (# [[Conditions], is_true?, is_false?, string, subst-string, human] [[], 1, 0, 'TRUE', '', 'TRUE'], [['TRUE'], 1, 0, 'TRUE', '', 'TRUE'], [['FALSE'], 0, 1, 'FALSE', '#', 'FALSE'], [['A_TRUE'], 0, 0, 'A_TRUE', '@A_TRUE@', 'A'], [['A_TRUE', 'B_FALSE'], 0, 0, 'A_TRUE B_FALSE', '@A_TRUE@@B_FALSE@', 'A and !B'], [['B_TRUE', 'FALSE'], 0, 1, 'FALSE', '#', 'FALSE'], [['B_TRUE', 'B_FALSE'], 0, 1, 'FALSE', '#', 'FALSE']); for (@tests) { my $a = new Automake::Condition @{$_->[0]}; return 1 if threads->new(sub { return 1 if $_->[1] != $a->true; return 1 if $_->[1] != ($a == TRUE); return 1 if $_->[2] != $a->false; return 1 if $_->[2] != ($a == FALSE); return 1 if $_->[3] ne $a->string; return 1 if $_->[4] ne $a->subst_string; return 1 if $_->[5] ne $a->human; })->join; } return 0; } sub test_true_when () { my $failed = 0; my @tests = (# [When, # [Implied-Conditions], # [Not-Implied-Conditions]] [['TRUE'], [['TRUE']], [['A_TRUE'], ['A_TRUE', 'B_FALSE'], ['FALSE']]], [['A_TRUE'], [['TRUE'], ['A_TRUE']], [['A_TRUE', 'B_FALSE'], ['FALSE']]], [['A_TRUE', 'B_FALSE'], [['TRUE'], ['A_TRUE'], ['B_FALSE'], ['A_TRUE', 'B_FALSE']], [['FALSE'], ['C_FALSE'], ['C_FALSE', 'A_TRUE']]]); for my $t (@tests) { my $a = new Automake::Condition @{$t->[0]}; return 1 if threads->new(sub { for my $u (@{$t->[1]}) { my $b = new Automake::Condition @$u; return threads->new(sub { if (! $b->true_when ($a)) { print "`" . $b->string . "' not implied by `" . $a->string . "'?\n"; $failed = 1; } })->join; } for my $u (@{$t->[2]}) { my $b = new Automake::Condition @$u; return threads->new(sub { if ($b->true_when ($a)) { print "`" . $b->string . "' implied by `" . $a->string . "'?\n"; $failed = 1; } return threads->new(sub { return 1 if $b->true_when ($a); })->join; })->join; } })->join; } return $failed; } sub test_reduce_and () { my @tests = (# If no conditions are given, TRUE should be returned [[], ["TRUE"]], # An empty condition is TRUE [[""], ["TRUE"]], # A single condition should be passed through unchanged [["FOO"], ["FOO"]], [["FALSE"], ["FALSE"]], [["TRUE"], ["TRUE"]], # TRUE and false should be discarded and overwhelm # the result, respectively [["FOO", "TRUE"], ["FOO"]], [["FOO", "FALSE"], ["FALSE"]], # Repetitions should be removed [["FOO", "FOO"], ["FOO"]], [["TRUE", "FOO", "FOO"], ["FOO"]], [["FOO", "TRUE", "FOO"], ["FOO"]], [["FOO", "FOO", "TRUE"], ["FOO"]], # Two different conditions should be preserved, # but TRUEs should be removed [["FOO", "BAR"], ["BAR,FOO"]], [["TRUE", "FOO", "BAR"], ["BAR,FOO"]], [["FOO", "TRUE", "BAR"], ["BAR,FOO"]], [["FOO", "BAR", "TRUE"], ["BAR,FOO"]], # A condition implied by another condition should be removed. [["FOO BAR", "BAR"], ["FOO BAR"]], [["BAR", "FOO BAR"], ["FOO BAR"]], [["TRUE", "FOO BAR", "BAR"], ["FOO BAR"]], [["FOO BAR", "TRUE", "BAR"], ["FOO BAR"]], [["FOO BAR", "BAR", "TRUE"], ["FOO BAR"]], [["BAR FOO", "BAR"], ["BAR FOO"]], [["BAR", "BAR FOO"], ["BAR FOO"]], [["TRUE", "BAR FOO", "BAR"], ["BAR FOO"]], [["BAR FOO", "TRUE", "BAR"], ["BAR FOO"]], [["BAR FOO", "BAR", "TRUE"], ["BAR FOO"]], # Check that reduction happens even when there are # two conditions to remove. [["FOO", "FOO BAR", "BAR"], ["FOO BAR"]], [["FOO", "FOO BAR", "BAZ", "FOO BAZ"], ["FOO BAR", "FOO BAZ"]], [["FOO", "FOO BAR", "BAZ", "FOO BAZ", "FOO BAZ BAR"], ["FOO BAZ BAR"]], # Duplicated conditionals should be removed. [["FOO", "BAR", "BAR"], ["BAR,FOO"]], # Equivalent conditions in different forms should be # reduced: which one is left is unfortunately order # dependent. [["BAR FOO", "FOO BAR"], ["FOO BAR"]], [["FOO BAR", "BAR FOO"], ["BAR FOO"]]); my $failed = 0; foreach (@tests) { my ($inref, $outref) = @$_; my @inconds = map { new Automake::Condition $_ } @$inref; return 1 if threads->new(sub { my @outconds = map { (new Automake::Condition $_)->string } @$outref; return threads->new(sub { my @res = map { $_->string } (Automake::Condition::reduce_and (@inconds)); return threads->new(sub { my $result = join (",", sort @res); my $exresult = join (",", @outconds); if ($result ne $exresult) { print '"' . join(",", @$inref) . '" => "' . $result . '" expected "' . $exresult . '"' . "\n"; $failed = 1; } return $failed; })->join; })->join; })->join; } return $failed; } sub test_reduce_or () { my @tests = (# If no conditions are given, FALSE should be returned [[], ["FALSE"]], # An empty condition is TRUE [[""], ["TRUE"]], # A single condition should be passed through unchanged [["FOO"], ["FOO"]], [["FALSE"], ["FALSE"]], [["TRUE"], ["TRUE"]], # FALSE and TRUE should be discarded and overwhelm # the result, respectively [["FOO", "TRUE"], ["TRUE"]], [["FOO", "FALSE"], ["FOO"]], # Repetitions should be removed [["FOO", "FOO"], ["FOO"]], [["FALSE", "FOO", "FOO"], ["FOO"]], [["FOO", "FALSE", "FOO"], ["FOO"]], [["FOO", "FOO", "FALSE"], ["FOO"]], # Two different conditions should be preserved, # but FALSEs should be removed [["FOO", "BAR"], ["BAR,FOO"]], [["FALSE", "FOO", "BAR"], ["BAR,FOO"]], [["FOO", "FALSE", "BAR"], ["BAR,FOO"]], [["FOO", "BAR", "FALSE"], ["BAR,FOO"]], # A condition implying another condition should be removed. [["FOO BAR", "BAR"], ["BAR"]], [["BAR", "FOO BAR"], ["BAR"]], [["FALSE", "FOO BAR", "BAR"], ["BAR"]], [["FOO BAR", "FALSE", "BAR"], ["BAR"]], [["FOO BAR", "BAR", "FALSE"], ["BAR"]], [["BAR FOO", "BAR"], ["BAR"]], [["BAR", "BAR FOO"], ["BAR"]], [["FALSE", "BAR FOO", "BAR"], ["BAR"]], [["BAR FOO", "FALSE", "BAR"], ["BAR"]], [["BAR FOO", "BAR", "FALSE"], ["BAR"]], # Check that reduction happens even when there are # two conditions to remove. [["FOO", "FOO BAR", "BAR"], ["BAR,FOO"]], [["FOO", "FOO BAR", "BAZ", "FOO BAZ"], ["BAZ,FOO"]], [["FOO", "FOO BAR", "BAZ", "FOO BAZ", "FOO BAZ BAR"], ["BAZ,FOO"]], # Duplicated conditionals should be removed. [["FOO", "BAR", "BAR"], ["BAR,FOO"]], # Equivalent conditions in different forms should be # reduced: which one is left is unfortunately order # dependent. [["BAR FOO", "FOO BAR"], ["FOO BAR"]], [["FOO BAR", "BAR FOO"], ["BAR FOO"]]); my $failed = 0; foreach (@tests) { my ($inref, $outref) = @$_; my @inconds = map { new Automake::Condition $_ } @$inref; return 1 if threads->new(sub { my @outconds = map { (new Automake::Condition $_)->string } @$outref; return threads->new(sub { my @res = map { $_->string } (Automake::Condition::reduce_or (@inconds)); return threads->new(sub { my $result = join (",", sort @res); my $exresult = join (",", @outconds); if ($result ne $exresult) { print '"' . join(",", @$inref) . '" => "' . $result . '" expected "' . $exresult . '"' . "\n"; $failed = 1; } return $failed; })->join; })->join; })->join; } return $failed; } sub test_merge () { my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE"; return threads->new(sub { my $other = new Automake::Condition "COND3_FALSE"; return threads->new(sub { my $both = $cond->merge ($other); return threads->new(sub { my $both2 = $cond->merge_conds ("COND3_FALSE"); return threads->new(sub { $cond = $both->strip ($other); my @conds = $cond->conds; return 1 if $both->string ne "COND1_TRUE COND2_FALSE COND3_FALSE"; return 1 if $cond->string ne "COND1_TRUE COND2_FALSE"; return 1 if $both != $both2; })->join; })->join; })->join; })->join; return 0; } exit (test_basics || test_true_when || test_reduce_and || test_reduce_or || test_merge);