test: check that subsecond mtime works with make.
[automake.git] / t / pm / Condition-t.pl
blob6a2a03c52f0d0b5ff39f2003ef67080aa26f1c18
1 # Copyright (C) 2001-2024 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2, or (at your option)
6 # any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 BEGIN {
17 use Config;
18 if (eval { require 5.007_002; } # for CLONE support
19 && $Config{useithreads}
20 && !$ENV{WANT_NO_THREADS})
22 require threads;
23 import threads;
25 else
27 exit 77;
30 use Automake::Condition qw/TRUE FALSE/;
32 sub test_basics ()
34 my @tests = (# [[Conditions], is_true?, is_false?, string, subst-string, human]
35 [[], 1, 0, 'TRUE', '', 'TRUE'],
36 [['TRUE'], 1, 0, 'TRUE', '', 'TRUE'],
37 [['FALSE'], 0, 1, 'FALSE', '#', 'FALSE'],
38 [['A_TRUE'], 0, 0, 'A_TRUE', '@A_TRUE@', 'A'],
39 [['A_TRUE', 'B_FALSE'],
40 0, 0, 'A_TRUE B_FALSE', '@A_TRUE@@B_FALSE@', 'A and !B'],
41 [['B_TRUE', 'FALSE'], 0, 1, 'FALSE', '#', 'FALSE'],
42 [['B_TRUE', 'B_FALSE'], 0, 1, 'FALSE', '#', 'FALSE']);
44 for (@tests)
46 my $a = new Automake::Condition @{$_->[0]};
47 return 1
48 if threads->new(sub {
49 return 1 if $_->[1] != $a->true;
50 return 1 if $_->[1] != ($a == TRUE);
51 return 1 if $_->[2] != $a->false;
52 return 1 if $_->[2] != ($a == FALSE);
53 return 1 if $_->[3] ne $a->string;
54 return 1 if $_->[4] ne $a->subst_string;
55 return 1 if $_->[5] ne $a->human;
56 })->join;
58 return 0;
61 sub test_true_when ()
63 my $failed = 0;
65 my @tests = (# [When,
66 # [Implied-Conditions],
67 # [Not-Implied-Conditions]]
68 [['TRUE'],
69 [['TRUE']],
70 [['A_TRUE'], ['A_TRUE', 'B_FALSE'], ['FALSE']]],
71 [['A_TRUE'],
72 [['TRUE'], ['A_TRUE']],
73 [['A_TRUE', 'B_FALSE'], ['FALSE']]],
74 [['A_TRUE', 'B_FALSE'],
75 [['TRUE'], ['A_TRUE'], ['B_FALSE'], ['A_TRUE', 'B_FALSE']],
76 [['FALSE'], ['C_FALSE'], ['C_FALSE', 'A_TRUE']]]);
78 for my $t (@tests)
80 my $a = new Automake::Condition @{$t->[0]};
81 return 1
82 if threads->new(sub {
83 for my $u (@{$t->[1]})
85 my $b = new Automake::Condition @$u;
86 return threads->new(sub {
87 if (! $b->true_when ($a))
89 print "`" . $b->string .
90 "' not implied by `" . $a->string . "'?\n";
91 $failed = 1;
93 })->join;
95 for my $u (@{$t->[2]})
97 my $b = new Automake::Condition @$u;
98 return threads->new(sub {
99 if ($b->true_when ($a))
101 print "`" . $b->string .
102 "' implied by `" . $a->string . "'?\n";
103 $failed = 1;
106 return threads->new(sub {
107 return 1 if $b->true_when ($a);
108 })->join;
109 })->join;
111 })->join;
113 return $failed;
116 sub test_reduce_and ()
118 my @tests = (# If no conditions are given, TRUE should be returned
119 [[], ["TRUE"]],
120 # An empty condition is TRUE
121 [[""], ["TRUE"]],
122 # A single condition should be passed through unchanged
123 [["FOO"], ["FOO"]],
124 [["FALSE"], ["FALSE"]],
125 [["TRUE"], ["TRUE"]],
126 # TRUE and false should be discarded and overwhelm
127 # the result, respectively
128 [["FOO", "TRUE"], ["FOO"]],
129 [["FOO", "FALSE"], ["FALSE"]],
130 # Repetitions should be removed
131 [["FOO", "FOO"], ["FOO"]],
132 [["TRUE", "FOO", "FOO"], ["FOO"]],
133 [["FOO", "TRUE", "FOO"], ["FOO"]],
134 [["FOO", "FOO", "TRUE"], ["FOO"]],
135 # Two different conditions should be preserved,
136 # but TRUEs should be removed
137 [["FOO", "BAR"], ["BAR,FOO"]],
138 [["TRUE", "FOO", "BAR"], ["BAR,FOO"]],
139 [["FOO", "TRUE", "BAR"], ["BAR,FOO"]],
140 [["FOO", "BAR", "TRUE"], ["BAR,FOO"]],
141 # A condition implied by another condition should be removed.
142 [["FOO BAR", "BAR"], ["FOO BAR"]],
143 [["BAR", "FOO BAR"], ["FOO BAR"]],
144 [["TRUE", "FOO BAR", "BAR"], ["FOO BAR"]],
145 [["FOO BAR", "TRUE", "BAR"], ["FOO BAR"]],
146 [["FOO BAR", "BAR", "TRUE"], ["FOO BAR"]],
148 [["BAR FOO", "BAR"], ["BAR FOO"]],
149 [["BAR", "BAR FOO"], ["BAR FOO"]],
150 [["TRUE", "BAR FOO", "BAR"], ["BAR FOO"]],
151 [["BAR FOO", "TRUE", "BAR"], ["BAR FOO"]],
152 [["BAR FOO", "BAR", "TRUE"], ["BAR FOO"]],
154 # Check that reduction happens even when there are
155 # two conditions to remove.
156 [["FOO", "FOO BAR", "BAR"], ["FOO BAR"]],
157 [["FOO", "FOO BAR", "BAZ", "FOO BAZ"], ["FOO BAR", "FOO BAZ"]],
158 [["FOO", "FOO BAR", "BAZ", "FOO BAZ", "FOO BAZ BAR"],
159 ["FOO BAZ BAR"]],
161 # Duplicated conditionals should be removed.
162 [["FOO", "BAR", "BAR"], ["BAR,FOO"]],
164 # Equivalent conditions in different forms should be
165 # reduced: which one is left is unfortunately order
166 # dependent.
167 [["BAR FOO", "FOO BAR"], ["FOO BAR"]],
168 [["FOO BAR", "BAR FOO"], ["BAR FOO"]]);
170 my $failed = 0;
171 foreach (@tests)
173 my ($inref, $outref) = @$_;
174 my @inconds = map { new Automake::Condition $_ } @$inref;
175 return 1
176 if threads->new(sub {
177 my @outconds = map { (new Automake::Condition $_)->string } @$outref;
178 return threads->new(sub {
179 my @res =
180 map { $_->string } (Automake::Condition::reduce_and (@inconds));
181 return threads->new(sub {
182 my $result = join (",", sort @res);
183 my $exresult = join (",", @outconds);
185 if ($result ne $exresult)
187 print '"' . join(",", @$inref) . '" => "' .
188 $result . '" expected "' .
189 $exresult . '"' . "\n";
190 $failed = 1;
192 return $failed;
193 })->join;
194 })->join;
195 })->join;
197 return $failed;
200 sub test_reduce_or ()
202 my @tests = (# If no conditions are given, FALSE should be returned
203 [[], ["FALSE"]],
204 # An empty condition is TRUE
205 [[""], ["TRUE"]],
206 # A single condition should be passed through unchanged
207 [["FOO"], ["FOO"]],
208 [["FALSE"], ["FALSE"]],
209 [["TRUE"], ["TRUE"]],
210 # FALSE and TRUE should be discarded and overwhelm
211 # the result, respectively
212 [["FOO", "TRUE"], ["TRUE"]],
213 [["FOO", "FALSE"], ["FOO"]],
214 # Repetitions should be removed
215 [["FOO", "FOO"], ["FOO"]],
216 [["FALSE", "FOO", "FOO"], ["FOO"]],
217 [["FOO", "FALSE", "FOO"], ["FOO"]],
218 [["FOO", "FOO", "FALSE"], ["FOO"]],
219 # Two different conditions should be preserved,
220 # but FALSEs should be removed
221 [["FOO", "BAR"], ["BAR,FOO"]],
222 [["FALSE", "FOO", "BAR"], ["BAR,FOO"]],
223 [["FOO", "FALSE", "BAR"], ["BAR,FOO"]],
224 [["FOO", "BAR", "FALSE"], ["BAR,FOO"]],
225 # A condition implying another condition should be removed.
226 [["FOO BAR", "BAR"], ["BAR"]],
227 [["BAR", "FOO BAR"], ["BAR"]],
228 [["FALSE", "FOO BAR", "BAR"], ["BAR"]],
229 [["FOO BAR", "FALSE", "BAR"], ["BAR"]],
230 [["FOO BAR", "BAR", "FALSE"], ["BAR"]],
232 [["BAR FOO", "BAR"], ["BAR"]],
233 [["BAR", "BAR FOO"], ["BAR"]],
234 [["FALSE", "BAR FOO", "BAR"], ["BAR"]],
235 [["BAR FOO", "FALSE", "BAR"], ["BAR"]],
236 [["BAR FOO", "BAR", "FALSE"], ["BAR"]],
238 # Check that reduction happens even when there are
239 # two conditions to remove.
240 [["FOO", "FOO BAR", "BAR"], ["BAR,FOO"]],
241 [["FOO", "FOO BAR", "BAZ", "FOO BAZ"], ["BAZ,FOO"]],
242 [["FOO", "FOO BAR", "BAZ", "FOO BAZ", "FOO BAZ BAR"],
243 ["BAZ,FOO"]],
245 # Duplicated conditionals should be removed.
246 [["FOO", "BAR", "BAR"], ["BAR,FOO"]],
248 # Equivalent conditions in different forms should be
249 # reduced: which one is left is unfortunately order
250 # dependent.
251 [["BAR FOO", "FOO BAR"], ["FOO BAR"]],
252 [["FOO BAR", "BAR FOO"], ["BAR FOO"]]);
254 my $failed = 0;
255 foreach (@tests)
257 my ($inref, $outref) = @$_;
258 my @inconds = map { new Automake::Condition $_ } @$inref;
259 return 1
260 if threads->new(sub {
261 my @outconds = map { (new Automake::Condition $_)->string } @$outref;
262 return threads->new(sub {
263 my @res =
264 map { $_->string } (Automake::Condition::reduce_or (@inconds));
265 return threads->new(sub {
266 my $result = join (",", sort @res);
267 my $exresult = join (",", @outconds);
269 if ($result ne $exresult)
271 print '"' . join(",", @$inref) . '" => "' .
272 $result . '" expected "' .
273 $exresult . '"' . "\n";
274 $failed = 1;
276 return $failed;
277 })->join;
278 })->join;
279 })->join;
281 return $failed;
284 sub test_merge ()
286 my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
287 return threads->new(sub {
288 my $other = new Automake::Condition "COND3_FALSE";
289 return threads->new(sub {
290 my $both = $cond->merge ($other);
291 return threads->new(sub {
292 my $both2 = $cond->merge_conds ("COND3_FALSE");
293 return threads->new(sub {
294 $cond = $both->strip ($other);
295 my @conds = $cond->conds;
296 return 1 if $both->string ne "COND1_TRUE COND2_FALSE COND3_FALSE";
297 return 1 if $cond->string ne "COND1_TRUE COND2_FALSE";
298 return 1 if $both != $both2;
299 })->join;
300 })->join;
301 })->join;
302 })->join;
303 return 0;
306 exit (test_basics
307 || test_true_when
308 || test_reduce_and
309 || test_reduce_or
310 || test_merge);