| # -*- 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/>. |
| |
| use Automake::Condition qw/TRUE FALSE/; |
| use Test::Simple tests => 6; |
| |
| 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 $_->[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; |
| } |
| 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]}; |
| for my $u (@{$t->[1]}) |
| { |
| my $b = new Automake::Condition @$u; |
| if (! $b->true_when ($a)) |
| { |
| print "`" . $b->string . |
| "' not implied by `" . $a->string . "'?\n"; |
| $failed = 1; |
| } |
| } |
| for my $u (@{$t->[2]}) |
| { |
| my $b = new Automake::Condition @$u; |
| if ($b->true_when ($a)) |
| { |
| print "`" . $b->string . |
| "' implied by `" . $a->string . "'?\n"; |
| $failed = 1; |
| } |
| |
| return 1 if $b->true_when ($a); |
| } |
| } |
| 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; |
| my @outconds = map { (new Automake::Condition $_)->string } @$outref; |
| my @res = |
| map { $_->string } (Automake::Condition::reduce_and (@inconds)); |
| my $result = join (",", sort @res); |
| my $exresult = join (",", @outconds); |
| |
| if ($result ne $exresult) |
| { |
| print '"' . join(",", @$inref) . '" => "' . |
| $result . '" expected "' . |
| $exresult . '"' . "\n"; |
| $failed = 1; |
| } |
| } |
| 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; |
| my @outconds = map { (new Automake::Condition $_)->string } @$outref; |
| my @res = |
| map { $_->string } (Automake::Condition::reduce_or (@inconds)); |
| my $result = join (",", sort @res); |
| my $exresult = join (",", @outconds); |
| |
| if ($result ne $exresult) |
| { |
| print '"' . join(",", @$inref) . '" => "' . |
| $result . '" expected "' . |
| $exresult . '"' . "\n"; |
| $failed = 1; |
| } |
| } |
| return $failed; |
| } |
| |
| sub test_merge () |
| { |
| my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE"; |
| my $other = new Automake::Condition "COND3_FALSE"; |
| my $both = $cond->merge ($other); |
| my $both2 = $cond->merge_conds ("COND3_FALSE"); |
| $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; |
| return 0; |
| } |
| |
| sub test_bad_declarations () |
| { |
| my $failed = 0; |
| |
| # Catch error: |
| # A condition object passed to 'new' |
| my $cond1 = new Automake::Condition ('TRUE'); |
| eval { new Automake::Condition ($cond1) }; |
| |
| $failed = 1 unless $@; |
| $@ = ''; |
| |
| # Catch common programming error: |
| # A Condition passed as a string to 'new'. |
| my $cond2 = new Automake::Condition ("COND1_TRUE"); |
| eval { new Automake::Condition ("$cond2") }; |
| |
| $failed = 1 unless $@; |
| return $failed; |
| } |
| |
| ok (test_basics == 0, 'Test basic conditions'); |
| ok (test_true_when == 0, 'Test implied conditions when declaring a new one'); |
| ok (test_reduce_and == 0, 'Test "and" reduction'); |
| ok (test_reduce_or == 0, 'Test "or" reduction'); |
| ok (test_merge == 0, 'Test the merge method'); |
| ok (test_bad_declarations == 0, 'Test bad condition declarations'); |