• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2011 Steven Watanabe.
2# Distributed under the Boost Software License, Version 1.0.
3# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
4
5# Tools
6
7passed = 0 ;
8failed = 0 ;
9
10rule show-result ( id : test-result )
11{
12    if ! ( --quiet in $(ARGV) )
13    {
14        ECHO "$(test-result):" $(id) ;
15    }
16    $(test-result) = [ CALC $($(test-result)) + 1 ] ;
17}
18
19rule check-equal ( id : values * : expected * )
20{
21    local test-result ;
22    local location = [ BACKTRACE ] ;
23    location = $(location[5-6]) ;
24    location = "$(location[1]):$(location[2])" ;
25    if x$(values) = x$(expected)
26    {
27        test-result = passed ;
28    }
29    else
30    {
31        ECHO "error:" "[" $(values) "] != [" $(expected) "]" ;
32        test-result = failed ;
33    }
34    show-result "$(location):$(id)" : $(test-result) ;
35}
36
37rule mark-order ( id : result * )
38{
39    order += $(id) ;
40    return $(result) ;
41}
42
43rule check-order ( id : expected * )
44{
45    check-equal $(id) : $(order) : $(expected) ;
46    order = ;
47}
48
49# Check variable expansion
50
51{
52
53local v1 = 1 2 3 ;
54local v2 = 4 5 6 ;
55local v3 = 0 1 2 3 4 5 6 7 8 9 10 ;
56local g = g1 g2 ;
57local v4 = String/With/Mixed/Case ;
58local v5 = path\\with\\backslashes ;
59local v6 = <grist>generic/path.txt(member.txt) ;
60local v7 = <Grist1>Dir1/File1.cpp(M1.c) <Grist2>Dir2/File2.hpp(M2.c) ;
61local v8 = <Grist3>Dir3/File3.c(M3.c) <Grist4>Dir4/File4.h(M4.c) ;
62local select1 = GU BL DBST ;
63local case1 = L U ;
64local vars = 7 8 ;
65local sub = 2 1 ;
66local p0 = name ;
67local p1 = dir/name ;
68local p2 = dir/sub/name ;
69local j1 = , - ;
70
71check-equal var-product : $(v1)$(v2) : 14 15 16 24 25 26 34 35 36 ;
72
73check-equal var-set-grist : $(v1:G=grist) : <grist>1 <grist>2 <grist>3 ;
74check-equal var-set-grist-multi : $(v1:G=$(g)) : <g1>1 <g1>2 <g1>3 <g2>1 <g2>2 <g2>3 ;
75
76check-equal var-lower : $(v4:L) : string/with/mixed/case ;
77check-equal var-upper : $(v4:U) : STRING/WITH/MIXED/CASE ;
78check-equal var-LU : $(v4:LU) : STRING/WITH/MIXED/CASE ;
79check-equal var-slashes : $(v5:T) : path/with/backslashes ;
80check-equal var-grist : $(v6:G) : <grist> ;
81check-equal var-grist-none : $(v1:G) : "" "" "" ;
82check-equal var-base : $(v6:B) : path ;
83check-equal var-suffix : $(v6:S) : .txt ;
84check-equal var-dir : $(v6:D) : generic ;
85check-equal var-member : $(v6:M) : (member.txt) ;
86check-equal var-multi : $(v6:$(select1)) : <GRIST> path generic/path.txt ;
87
88check-equal var-join-0 : $(:J=,) : ;
89check-equal var-join-1 : $(p0:J=,) : name ;
90check-equal var-join-3 : $(v1:J=,) : 1,2,3 ;
91check-equal var-set-grist-join : $(v1:G=grist:J=,) : <grist>1,<grist>2,<grist>3 ;
92# behavior change.  In the past, a J= modifier would
93# cause only the last element of the other modifiers
94# to take effect.
95check-equal var-set-grist-multi-join : $(v1:G=$(g):J=,) : <g1>1,<g1>2,<g1>3 <g2>1,<g2>2,<g2>3 ;
96check-equal var-set-grist-multi-join-multi : $(v1:G=$(g):J=$(j1)) : <g1>1,<g1>2,<g1>3 <g1>1-<g1>2-<g1>3 <g2>1,<g2>2,<g2>3 <g2>1-<g2>2-<g2>3 ;
97
98check-equal var-D=-0 : name : $(p0:D=) ;
99check-equal var-D=-1 : name : $(p1:D=) ;
100check-equal var-D=-2 : name : $(p2:D=) ;
101check-equal var-D-0 : "" : $(p0:D) ;
102check-equal var-D-1 : dir : $(p1:D) ;
103check-equal var-D-2 : dir/sub : $(p2:D) ;
104check-equal var-S-1 : "" : $(p0:S) ;
105check-equal var-no-at-file-0 : ($(p0)) : [ MATCH ^@(.*) : "@($(p0))" ] ;
106check-equal var-no-at-file-1 : ($(p0)) : [ MATCH @(.*) : "--@($(p0))" ] ;
107
108if $(OS) = CYGWIN
109{
110    local cyg-root = $(:WE=/) ;
111    local cyg1 = /cygdrive/c/path1.txt ;
112    check-equal cygwin-to-cygdrive : $(cyg1:W) : C:\\path1.txt ;
113    local cyg2 = /bin/bash ;
114    check-equal cygwin-to-windows : $(cyg2:W) : $(cyg-root)\\bin\\bash ;
115    check-equal cygwin-combine-WT : $(cyg2:WT) : $(cyg-root)\\bin\\bash ;
116
117    local cyg3 = /home/boost/devel/trunk/bin.v2/ ; # exactly 31 characters
118    local win3 = $(cyg-root)\\home\\boost\\devel\\trunk\\bin.v2\\ ;
119    # This is is the easiest way to demonstrate a bug
120    # that used to cause undefined behavior.  Longer paths
121    # resulted in a use-after-free error, which happened
122    # to work most of the time.
123    check-equal cygwin-long-WU : $(cyg3:WU) : $(win3:U) ;
124
125    local cyg-grist = <grist>$(cyg1) ;
126    check-equal cygwin-grist : $(cyg-grist:W) : <grist>\\cygdrive\\c\\path1.txt ;
127
128    check-equal cygwin-WU : $(cyg2:WU) : $(cyg-root:U)\\BIN\\BASH ;
129    # behavior change: L now consistently applied after W.
130    # used to affect all except the drive letter.
131    check-equal cygwin-WL : $(cyg2:WL) : $(cyg-root:L)\\bin\\bash ;
132}
133
134# behavior change
135check-equal var-test1 : $(v7[2]:G:L) : <grist2> ;
136
137check-equal var-multi-product-smm : $(v$(vars)[$(sub)]:G=$(g):$(case1)) :
138    <g1>dir2/file2.hpp(m2.c) <G1>DIR2/FILE2.HPP(M2.C)
139    <g2>dir2/file2.hpp(m2.c) <G2>DIR2/FILE2.HPP(M2.C)
140    <g1>dir1/file1.cpp(m1.c) <G1>DIR1/FILE1.CPP(M1.C)
141    <g2>dir1/file1.cpp(m1.c) <G2>DIR1/FILE1.CPP(M1.C)
142    <g1>dir4/file4.h(m4.c) <G1>DIR4/FILE4.H(M4.C)
143    <g2>dir4/file4.h(m4.c) <G2>DIR4/FILE4.H(M4.C)
144    <g1>dir3/file3.c(m3.c) <G1>DIR3/FILE3.C(M3.C)
145    <g2>dir3/file3.c(m3.c) <G2>DIR3/FILE3.C(M3.C)
146;
147check-equal var-nopathmods : $(:E=//) : // ;
148
149# showcases all the idiosyncracies of indexing
150# key: h = high, l = low, p = positive, m = minus, e = end.
151
152check-equal var-subscript-one-p : $(v3[3]) : 2 ;
153check-equal var-subscript-one-m : $(v3[-3]) : 8 ;
154check-equal var-subscript-one-0 : $(v3[0]) : 0 ;
155check-equal var-subscript-one-h : $(v3[20]) : ;
156check-equal var-subscript-one-l : $(v3[-20]) : 0 ;
157check-equal var-subscript-range-pp : $(v3[2-4]) : 1 2 3 ;
158check-equal var-subscript-range-pm : $(v3[2--3]) : 1 2 3 4 5 6 7 8 ;
159check-equal var-subscript-range-pe : $(v3[2-]) : 1 2 3 4 5 6 7 8 9 10 ;
160check-equal var-subscript-range-ph : $(v3[2-20]) : 1 2 3 4 5 6 7 8 9 10 ;
161check-equal var-subscript-range-pl : $(v3[2--20]) : ;
162check-equal var-subscript-range-mp : $(v3[-3-10]) : 8 9 ;
163check-equal var-subscript-range-mm : $(v3[-4--2]) : 7 8 9 ;
164check-equal var-subscript-range-me : $(v3[-4-]) : 7 8 9 10 ;
165check-equal var-subscript-range-mh : $(v3[-4-20]) : 7 8 9 10 ;
166check-equal var-subscript-range-mh : $(v3[-4--20]) : ;
167check-equal var-subscript-range-0p : $(v3[0-2]) : 0 1 2 ;
168check-equal var-subscript-range-0m : $(v3[0--4]) : 0 1 2 3 4 5 6 7 8 ;
169check-equal var-subscript-range-0e : $(v3[0-]) : 0 1 2 3 4 5 6 7 8 9 10 ;
170check-equal var-subscript-range-0h : $(v3[0-20]) : 0 1 2 3 4 5 6 7 8 9 10 ;
171check-equal var-subscript-range-0l : $(v3[0--20]) : ;
172check-equal var-subscript-range-hp : $(v3[20-4]) : ;
173check-equal var-subscript-range-hm : $(v3[20--4]) : ;
174check-equal var-subscript-range-he : $(v3[20-]) : ;
175check-equal var-subscript-range-hh : $(v3[20-20]) : ;
176check-equal var-subscript-range-hl : $(v3[20--20]) : ;
177check-equal var-subscript-range-lp : $(v3[-13-4]) : 0 1 2 3 4 5 ;
178check-equal var-subscript-range-lm : $(v3[-13--4]) : 0 1 2 3 4 5 6 7 8 9 ;
179check-equal var-subscript-range-le : $(v3[-13-]) : 0 1 2 3 4 5 6 7 8 9 10 ;
180check-equal var-subscript-range-lh : $(v3[-13-20]) : 0 1 2 3 4 5 6 7 8 9 10 ;
181check-equal var-subscript-range-ll : $(v3[-13--13]) : 0 ;
182check-equal var-subscript-range-empty : $(v3[4-3]) : ;
183
184}
185
186# Check rules
187
188{
189
190rule test-rule
191{
192    return $(<) - $(>) - $(1) - $(2) - $(3) - $(4) - $(5) - $(6) - $(7) - $(8) - $(9) - $(10) - $(11) - $(12) - $(13) - $(14) - $(15) - $(16) - $(17) - $(18) - $(19) ;
193}
194
195check-equal rule-arguments-numbered :
196    [ test-rule a1 : a2 : a3 : a4 : a5 : a6 : a7 : a8 : a9 : a10 : a11 : a12 : a13 : a14 : a15 : a16 : a17 : a18 : a19 ] :
197    a1 - a2 - a1 - a2 - a3 - a4 - a5 - a6 - a7 - a8 - a9 - a10 - a11 - a12 - a13 - a14 - a15 - a16 - a17 - a18 - a19 ;
198
199rule test-rule
200{
201    return $(<:L) - $(>:L) - $(1:L) - $(2:L) - $(3:L) - $(4:L) - $(5:L) - $(6:L) - $(7:L) - $(8:L) - $(9:L) - $(10:L) - $(11:L) - $(12:L) - $(13:L) - $(14:L) - $(15:L) - $(16:L) - $(17:L) - $(18:L) - $(19:L) ;
202}
203
204# behavior change
205check-equal rule-arguments-numbered-lower :
206    [ test-rule a1 : a2 : a3 : a4 : a5 : a6 : a7 : a8 : a9 : a10 : a11 : a12 : a13 : a14 : a15 : a16 : a17 : a18 : a19 ] :
207    a1 - a2 - a1 - a2 - a3 - a4 - a5 - a6 - a7 - a8 - a9 - a10 - a11 - a12 - a13 - a14 - a15 - a16 - a17 - a18 - a19 ;
208
209
210rule test-rule ( p1 : p2 : p3 : p4 : p5 : p6 : p7 : p8 : p9 :
211                         p10 : p11 : p12 : p13 : p14 : p15 : p16 : p17 : p18 : p19 )
212
213
214{
215    return $(p1) - $(p2) - $(p3) - $(p4) - $(p5) - $(p6) - $(p7) - $(p8) - $(p9) - $(p10) - $(p11) - $(p12) - $(p13) - $(p14) - $(p15) - $(p16) - $(p17) - $(p18) - $(p19) ;
216}
217
218check-equal rule-arguments-named :
219    [ test-rule a1 : a2 : a3 : a4 : a5 : a6 : a7 : a8 : a9 : a10 : a11 : a12 : a13 : a14 : a15 : a16 : a17 : a18 : a19 ] :
220    a1 - a2 - a3 - a4 - a5 - a6 - a7 - a8 - a9 - a10 - a11 - a12 - a13 - a14 - a15 - a16 - a17 - a18 - a19 ;
221
222#
223# test rule indirection
224#
225rule select ( n list * )
226{
227    return $(list[$(n)]) ;
228}
229
230rule indirect1 ( rule + : args * )
231{
232    return [ $(rule) $(args) ] ;
233}
234
235check-equal rule-indirect-1 : [ indirect1 select 1 : a b c d e ] : a ;
236check-equal rule-indirect-2 : [ indirect1 select 2 : a b c d e ] : b ;
237
238x = reset ;
239rule reset-x ( new-value )
240{
241    x = $(new-value) ;
242}
243$(x)-x bar ;                          # invokes reset-x...
244check-equal rule-reset : $(x) : bar ; # which changes x
245
246rule bar-x ( new-value )
247{
248    mark-order r3 ;
249}
250
251# The arguments are evaluated in forward order
252# before the rule name
253$(x)-x [ mark-order r1 : [ reset-x reset ] ] : [ mark-order r2 ] ;
254check-order rule-order : r1 r2 ;
255
256# Cases that look like member calls
257rule looks.like-a-member ( args * )
258{
259    return $(args) ;
260}
261
262rule call-non-member ( rule + )
263{
264    return [ $(rule).like-a-member ] ;
265}
266
267rule call-non-member-with-args ( rule + )
268{
269    return [ $(rule).like-a-member a2 ] ;
270}
271
272check-equal rule-non-member : [ call-non-member looks ] : ;
273#check-equal rule-non-member-a1 : [ call-non-member looks a1 ] : looks.a1 ;
274check-equal rule-non-member-args : [ call-non-member-with-args looks ] : a2 ;
275#check-equal rule-non-member-args-a1 : [ call-non-member-with-args looks a1 ] : looks.a1 a2 ;
276
277}
278
279# Check append
280
281{
282
283local value = [ mark-order r1 : v1 v2 ] [ mark-order r2 : v3 v4 ] ;
284check-equal append : $(value) : v1 v2 v3 v4 ;
285check-order append-order : r1 r2 ;
286
287}
288
289# Check foreach
290
291{
292
293local v1 = 1 2 3 ;
294local x = old ;
295local result ;
296
297for local x in $(v1)
298{
299    result += $(x) + ;
300}
301
302check-equal foreach-local-item : $(result) : 1 + 2 + 3 + ;
303check-equal foreach-local : $(x) : old ;
304
305result = ;
306
307for x in $(v1)
308{
309    result += $(x) + ;
310}
311
312check-equal foreach-nonlocal-item : $(result) : 1 + 2 + 3 + ;
313check-equal foreach-nonlocal : $(x) : 3 ;
314
315rule call-foreach ( values * )
316{
317    for local x in $(values)
318    {
319        return $(x) ;
320    }
321}
322
323check-equal foreach-result : [ call-foreach 1 2 3 ] : 1 ;
324
325result = ;
326local varname = x ;
327x = old ;
328
329for local $(varname) in $(v1)
330{
331    result += $(x) + ;
332}
333
334check-equal foreach-no-expand : $(result) : old + old + old + ;
335
336result = ;
337
338for local v1 in $(v1)
339{
340   result += $(v1) + ;
341}
342
343check-equal foreach-order : $(result) : 1 + 2 + 3 + ;
344
345}
346
347# Check if
348
349{
350
351if true
352{
353    mark-order r1 ;
354}
355
356check-order if-true : r1 ;
357
358if $(false)
359{
360    mark-order r1 ;
361}
362
363check-order if-false : ;
364
365if true
366{
367    mark-order r1 ;
368}
369else
370{
371    mark-order r2 ;
372}
373
374check-order if-else-true : r1 ;
375
376if $(false)
377{
378    mark-order r1 ;
379}
380else
381{
382    mark-order r2 ;
383}
384
385check-order if-else-false : r2 ;
386
387rule test-rule
388{
389    if true
390    {
391        return result ;
392    }
393}
394
395check-equal if-true-result : [ test-rule ] : result ;
396
397rule test-rule
398{
399    local idx  = 1 2 ;
400    local values = true ;
401    while $(idx)
402    {
403        local v = $(values[$(idx[1])]) ;
404        idx = $(idx[2-]) ;
405        if $(v)
406        {
407            return result ;
408        }
409    }
410}
411
412check-equal if-false-result : [ test-rule ] : result ;
413
414rule test-rule
415{
416    if true
417    {
418        return r1 ;
419    }
420    else
421    {
422        return r2 ;
423    }
424}
425
426check-equal if-else-true-result : [ test-rule ] : r1 ;
427
428rule test-rule
429{
430    if $(false)
431    {
432        return r1 ;
433    }
434    else
435    {
436        return r2 ;
437    }
438}
439
440check-equal if-else-false-result : [ test-rule ] : r2 ;
441
442}
443
444# Check the evaluation of conditions
445
446{
447
448local test-result ;
449local v1 = "" "" "" ;
450local v2 = ;
451local v3 = a b c ;
452local v4 = a b c d ;
453local v5 = a b d ;
454local v6 = "" "" "" d ;
455
456rule test-comparison ( id : equal less greater )
457{
458    check-equal $(id)-empty-1 : [ eval-$(id) $(v1) : $(v2) ] : $(equal) ;
459    check-equal $(id)-empty-2 : [ eval-$(id) $(v1) : $(v2) ] : $(equal) ;
460    check-equal $(id)-equal : [ eval-$(id) $(v3) : $(v3) ] : $(equal) ;
461    check-equal $(id)-less-1 : [ eval-$(id) $(v3) : $(v4) ] : $(less) ;
462    check-equal $(id)-less-2 : [ eval-$(id) $(v3) : $(v5) ] : $(less) ;
463    check-equal $(id)-less-3 : [ eval-$(id) $(v4) : $(v5) ] : $(less) ;
464    check-equal $(id)-greater-1 : [ eval-$(id) $(v4) : $(v3) ] : $(greater) ;
465    check-equal $(id)-greater-2 : [ eval-$(id) $(v5) : $(v3) ] : $(greater) ;
466    check-equal $(id)-greater-3 : [ eval-$(id) $(v5) : $(v4) ] : $(greater) ;
467}
468
469rule eval-lt ( lhs * : rhs * )
470{
471    if $(lhs) < $(rhs) { return true ; }
472    else { return false ; }
473}
474
475test-comparison lt : false true false ;
476
477rule eval-gt ( lhs * : rhs * )
478{
479    if $(lhs) > $(rhs) { return true ; }
480    else { return false ; }
481}
482
483test-comparison gt : false false true ;
484
485rule eval-le ( lhs * : rhs * )
486{
487    if $(lhs) <= $(rhs) { return true ; }
488    else { return false ; }
489}
490
491test-comparison le : true true false ;
492
493rule eval-ge ( lhs * : rhs * )
494{
495    if $(lhs) >= $(rhs) { return true ; }
496    else { return false ; }
497}
498
499test-comparison ge : true false true ;
500
501rule eval-eq ( lhs * : rhs * )
502{
503    if $(lhs) = $(rhs) { return true ; }
504    else { return false ; }
505}
506
507test-comparison eq : true false false ;
508
509rule eval-ne ( lhs * : rhs * )
510{
511    if $(lhs) != $(rhs) { return true ; }
512    else { return false ; }
513}
514
515test-comparison ne : false true true ;
516
517rule eval-not-lt ( lhs * : rhs * )
518{
519    if ! ( $(lhs) < $(rhs) ) { return true ; }
520    else { return false ; }
521}
522
523test-comparison not-lt : true false true ;
524
525rule eval-not-gt ( lhs * : rhs * )
526{
527    if ! ( $(lhs) > $(rhs) ) { return true ; }
528    else { return false ; }
529}
530
531test-comparison not-gt : true true false ;
532
533rule eval-not-le ( lhs * : rhs * )
534{
535    if ! ( $(lhs) <= $(rhs) ) { return true ; }
536    else { return false ; }
537}
538
539test-comparison not-le : false false true ;
540
541rule eval-not-ge ( lhs * : rhs * )
542{
543    if ! ( $(lhs) >= $(rhs) ) { return true ; }
544    else { return false ; }
545}
546
547test-comparison not-ge : false true false ;
548
549rule eval-not-eq ( lhs * : rhs * )
550{
551    if ! ( $(lhs) = $(rhs) ) { return true ; }
552    else { return false ; }
553}
554
555test-comparison not-eq : false true true ;
556
557rule eval-not-ne ( lhs * : rhs * )
558{
559    if ! ( $(lhs) != $(rhs) )  { return true ; }
560    else { return false ; }
561}
562
563test-comparison not-ne : true false false ;
564
565local v7 = a a a a a a ;
566local v8 = c b ;
567local v9 = c d b ;
568local v10 = c a b c c b a a a ;
569
570rule test-in ( id : subset not-subset )
571{
572    check-equal $(id)-0-0 : [ eval-$(id) $(v2) : $(v2) ] : $(subset) ;
573    check-equal $(id)-0-empty : [ eval-$(id) $(v2) : $(v1) ] : $(subset) ;
574    check-equal $(id)-empty-0 : [ eval-$(id) $(v1) : $(v2) ] : $(not-subset) ;
575    check-equal $(id)-equal : [ eval-$(id) $(v3) : $(v3) ] : $(subset) ;
576    check-equal $(id)-simple : [ eval-$(id) $(v3) : $(v4) ] : $(subset) ;
577    check-equal $(id)-extra : [ eval-$(id) $(v4) : $(v3) ] : $(not-subset) ;
578    check-equal $(id)-multiple : [ eval-$(id) $(v7) : $(v3) ] : $(subset) ;
579    check-equal $(id)-unordered : [ eval-$(id) $(v8) : $(v3) ] : $(subset) ;
580    check-equal $(id)-unordered-extra : [ eval-$(id) $(v9) : $(v3) ] : $(not-subset) ;
581    check-equal $(id)-unordered-multiple : [ eval-$(id) $(v10) : $(v3) ] : $(subset) ;
582}
583
584rule eval-in ( lhs * : rhs * )
585{
586    if $(lhs) in $(rhs) { return true ; }
587    else { return false ; }
588}
589
590test-in "in" : true false ;
591
592rule eval-not-in ( lhs * : rhs * )
593{
594    if ! ( $(lhs) in $(rhs) ) { return true ; }
595    else { return false ; }
596}
597
598test-in not-in : false true ;
599
600rule test-truth-table ( id : tt tf ft ff )
601{
602    check-equal $(id)-tt : [ eval-$(id) 1 : 1 ] : $(tt) ;
603    check-equal $(id)-tf : [ eval-$(id) 1 : ] : $(tf) ;
604    check-equal $(id)-ft : [ eval-$(id) : 1 ] : $(ft) ;
605    check-equal $(id)-ff : [ eval-$(id) : ] : $(ff) ;
606}
607
608rule eval-and ( lhs ? : rhs ? )
609{
610    if $(lhs) && $(rhs) { return true ; }
611    else { return false ; }
612}
613
614test-truth-table and : true false false false ;
615
616rule eval-or ( lhs ? : rhs ? )
617{
618    if $(lhs) || $(rhs) { return true ; }
619    else { return false ; }
620}
621
622test-truth-table or : true true true false ;
623
624rule eval-not-and ( lhs ? : rhs ? )
625{
626    if ! ( $(lhs) && $(rhs) ) { return true ; }
627    else { return false ; }
628}
629
630test-truth-table not-and : false true true true ;
631
632rule eval-not-or ( lhs ? : rhs ? )
633{
634    if ! ( $(lhs) || $(rhs) ) { return true ; }
635    else { return false ; }
636}
637
638test-truth-table not-or : false false false true ;
639
640if [ mark-order r1 : test1 ] < [ mark-order r2 : test2 ] { }
641check-order lt-order : r1 r2 ;
642if [ mark-order r1 : test1 ] > [ mark-order r2 : test2 ] { }
643check-order gt-order : r1 r2 ;
644if [ mark-order r1 : test1 ] <= [ mark-order r2 : test2 ] { }
645check-order le-order : r1 r2 ;
646if [ mark-order r1 : test1 ] >= [ mark-order r2 : test2 ] { }
647check-order ge-order : r1 r2 ;
648if [ mark-order r1 : test1 ] = [ mark-order r2 : test2 ] { }
649check-order eq-order : r1 r2 ;
650if [ mark-order r1 : test1 ] != [ mark-order r2 : test2 ] { }
651check-order ne-order : r1 r2 ;
652if [ mark-order r1 : test1 ] in [ mark-order r2 : test2 ] { }
653check-order in-order : r1 r2 ;
654
655if [ mark-order r1 : test1 ] && [ mark-order r2 : test2 ] { }
656check-order and-order : r1 r2 ;
657if [ mark-order r1 ] && [ mark-order r2 : test2 ] { }
658check-order and-order-short-circuit : r1 ;
659
660if [ mark-order r1 ] || [ mark-order r2 : test2 ] { }
661check-order or-order : r1 r2 ;
662if [ mark-order r1 : test1 ] || [ mark-order r2 : test2 ] { }
663check-order or-order-short-circuit : r1 ;
664
665}
666
667# Check include
668
669{
670#FIXME:
671# plain include
672# include in module
673# include returns an empty list
674# rule arguments are available inside include
675}
676
677# Check local
678
679{
680
681local v1 = a b c ;
682local v2 = f g h ;
683
684{
685    local v1 ;
686    check-equal local-no-init : $(v1) : ;
687}
688
689check-equal local-restore : $(v1) : a b c ;
690
691{
692    local v1 = d e f ;
693    check-equal local-init : $(v1) : d e f ;
694}
695
696check-equal local-restore-init : $(v1) : a b c ;
697
698{
699    local v1 v2 ;
700    check-equal local-multiple-no-init : $(v1) - $(v2) : - ;
701}
702
703check-equal local-multiple-restore : $(v1) - $(v2) : a b c - f g h ;
704
705{
706    local v1 v2 = d e f ;
707    check-equal local-multiple-init : $(v1) - $(v2) : d e f - d e f ;
708}
709
710{
711    local v1 v1 = d e f ;
712    check-equal local-duplicate : $(v1) - $(v1) : d e f - d e f ;
713}
714
715check-equal local-duplicate-restore : $(v1) : a b c ;
716
717{
718    local [ mark-order r1 : v1 ] = [ mark-order r2 : d e f ] ;
719    check-order local-order : r1 r2 ;
720}
721
722}
723
724# Check module
725
726{
727    local var1 = root-module-var ;
728    module my_module
729    {
730        var1 = module-var ;
731        rule get ( )
732        {
733            return $(var1) ;
734        }
735        local rule not_really ( ) { return nothing ; }
736    }
737
738    check-equal module-var-not-root : $(var1) : root-module-var ;
739
740    check-equal module-rulenames : [ RULENAMES my_module ] : get ;
741
742    IMPORT_MODULE my_module ;
743    check-equal module-rule-import-module : [ my_module.get ] : module-var ;
744
745    IMPORT my_module : get : : module-get ;
746    check-equal module-rule-imort : [ module-get ] : module-var ;
747
748    IMPORT my_module : get : : module-get : LOCALIZE ;
749    check-equal module-rule-imort-localize : [ module-get ] : root-module-var ;
750
751}
752
753# Check class
754{
755#FIXME:
756# ...
757}
758
759# Check on
760
761{
762
763local target1 = test-on-target1 ;
764local target2 = test-on-target2 ;
765local targets = $(target1) $(target2) ;
766local v1 v2 v3 ;
767
768VAR on $(target1) = value1 ;
769V2 on $(target2) = value2 ;
770
771check-equal on-return : [ on $(target1) return $(VAR) ] : value1 ;
772
773rule test-rule
774{
775    return $(VAR) ;
776}
777
778check-equal on-rule : [ on $(target1) test-rule ] : value1 ;
779
780check-equal on-multiple : [ on $(targets) return $(V2) ] : ;
781
782rule test-rule
783{
784    on $(target1)
785    {
786        return $(VAR) ;
787    }
788}
789
790check-equal on-block : [ test-rule ] : value1 ;
791
792# FIXME: crazy implementation artifacts:
793
794v1 on test-on-target3 = x1 ;
795on test-on-target3
796{
797    v1 on test-on-target3 += x1 ;
798    v1 = y1 ;
799    v2 on test-on-target3 += x2 ;
800    v2 = y2 ;
801    v3 = y3 ;
802}
803
804check-equal on-swap-old1 : $(v1) : x1 ;
805check-equal on-swap-old2 : [ on test-on-target3 return $(v1) ] : y1 ;
806check-equal on-swap-new1 : $(v2) : x2 ;
807check-equal on-swap-new2 : [ on test-on-target3 return $(v2) ] : y2 ;
808check-equal on-no-swap : $(v3) : y3 ;
809
810}
811
812# Check rule
813
814{
815#FIXME:
816# argument order
817# expand rule name
818}
819
820# Check rules
821
822{
823#FIXME:
824}
825
826# Check set
827
828{
829local v1 ;
830local v2 ;
831local v3 ;
832local vars = v1 v2 v3 ;
833
834v1 = x1 ;
835check-equal set-set-empty : $(v1) : x1 ;
836v2 += x2 ;
837check-equal set-append-empty : $(v2) : x2 ;
838v3 ?= x3 ;
839check-equal set-default-empty : $(v3) : x3 ;
840
841v1 = y1 ;
842check-equal set-set-non-empty : $(v1) : y1 ;
843v2 += y2 ;
844check-equal set-append-non-empty : $(v2) : x2 y2 ;
845v3 ?= y3 ;
846check-equal set-default-non-empty : $(v3) : x3 ;
847
848v1 = ;
849v2 = ;
850v3 = ;
851$(vars) = z ;
852check-equal set-set-empty-group : $(v1) - $(v2) - $(v3) : z - z - z ;
853
854v1 = ;
855v2 = ;
856v3 = ;
857$(vars) += z ;
858check-equal set-append-empty-group : $(v1) - $(v2) - $(v3) : z - z - z ;
859
860v1 = ;
861v2 = ;
862v3 = ;
863$(vars) ?= z ;
864check-equal set-default-empty-group : $(v1) - $(v2) - $(v3) : z - z - z ;
865
866v1 = x1 ;
867v2 = x2 ;
868v3 = x3 ;
869$(vars) = z ;
870check-equal set-set-non-empty-group : $(v1) - $(v2) - $(v3) : z - z - z ;
871
872v1 = x1 ;
873v2 = x2 ;
874v3 = x3 ;
875$(vars) += z ;
876check-equal set-append-non-empty-group : $(v1) - $(v2) - $(v3) : x1 z - x2 z - x3 z ;
877
878v1 = x1 ;
879v2 = x2 ;
880v3 = x3 ;
881$(vars) ?= z ;
882check-equal set-default-non-empty-group : $(v1) - $(v2) - $(v3) : x1 - x2 - x3 ;
883
884v1 = x1 ;
885v2 = ;
886v3 = x3 ;
887$(vars) = z ;
888check-equal set-set-mixed-group : $(v1) - $(v2) - $(v3) : z - z - z ;
889
890v1 = x1 ;
891v2 = ;
892v3 = x3 ;
893$(vars) += z ;
894check-equal set-append-mixed-group : $(v1) - $(v2) - $(v3) : x1 z - z - x3 z ;
895
896v1 = x1 ;
897v2 = ;
898v3 = x3 ;
899$(vars) ?= z ;
900check-equal set-default-mixed-group : $(v1) - $(v2) - $(v3) : x1 - z - x3 ;
901
902vars = v1 v1 ;
903
904v1 = ;
905$(vars) = z ;
906check-equal set-set-duplicate-empty : $(v1) : z ;
907v1 = ;
908$(vars) += z ;
909check-equal set-append-duplicate-empty : $(v1) : z z ;
910v1 = ;
911$(vars) ?= z ;
912check-equal set-default-duplicate-empty : $(v1) : z ;
913
914v1 = x1 ;
915$(vars) = z ;
916check-equal set-set-duplicate-non-empty : $(v1) : z ;
917v1 = x1 ;
918$(vars) += z ;
919check-equal set-append-duplicate-non-empty : $(v1) : x1 z z ;
920v1 = x1 ;
921$(vars) ?= z ;
922check-equal set-default-duplicate-non-empty : $(v1) : x1 ;
923
924rule test-rule { v1 = x1 ; }
925check-equal set-set-result : [ test-rule ] : x1 ;
926rule test-rule { v1 += x1 ; }
927check-equal set-append-result : [ test-rule ] : x1 ;
928rule test-rule { v1 ?= x1 ; }
929check-equal set-default-result : [ test-rule ] : x1 ;
930
931[ mark-order r1 ] = [ mark-order r2 ] ;
932check-order set-set-order : r1 r2 ;
933[ mark-order r1 ] += [ mark-order r2 ] ;
934check-order set-append-order : r1 r2 ;
935[ mark-order r1 ] ?= [ mark-order r2 ] ;
936check-order set-default-order : r1 r2 ;
937
938}
939
940# Check setcomp
941
942{
943#FIXME
944# Expand arguments
945# Don't expand name
946}
947
948# Check setexec
949
950{
951#FIXME:
952# Don't expand name
953# Evaluate bindlist
954}
955
956# Check settings ;
957
958{
959
960local target1 = test-settings-target1 ;
961local target2 = test-settings-target2 ;
962local target3 = test-settings-target3 ;
963local targets = $(target2) $(target3) ;
964
965local vars = v1 v2 v3 ;
966
967v1 on $(target1) = x1 ;
968check-equal settings-set-empty : [ on $(target1) return $(v1) ] : x1 ;
969v2 on $(target1) += x2 ;
970check-equal settings-append-empty : [ on $(target1) return $(v2) ] : x2 ;
971v3 on $(target1) ?= x3 ;
972check-equal settings-default-empty : [ on $(target1) return $(v3) ] : x3 ;
973
974v1 on $(target1) = y1 ;
975check-equal settings-set-non-empty : [ on $(target1) return $(v1) ] : y1 ;
976v2 on $(target1) += y2 ;
977check-equal settings-append-non-empty : [ on $(target1) return $(v2) ] : x2 y2 ;
978v3 on $(target1) ?= y3 ;
979check-equal settings-default-non-empty : [ on $(target1) return $(v3) ] : x3 ;
980
981$(vars) on setting-target2 = z ;
982check-equal settings-set-empty-group : [ on setting-target2 return $(v1) ] - [ on setting-target2 return $(v2) ] - [ on setting-target2 return $(v3) ] : z - z - z ;
983
984$(vars) on setting-target3 += z ;
985check-equal settings-append-empty-group : [ on setting-target3 return $(v1) ] - [ on setting-target3 return $(v2) ] - [ on setting-target3 return $(v3) ] : z - z - z ;
986
987$(vars) on setting-target4 ?= z ;
988check-equal settings-default-empty-group : [ on setting-target4 return $(v1) ] - [ on setting-target4 return $(v2) ] - [ on setting-target4 return $(v3) ] : z - z - z ;
989
990v1 on $(target1) = x1 ;
991v2 on $(target1) = x2 ;
992v3 on $(target1) = x3 ;
993$(vars) on $(target1) = z ;
994check-equal settings-set-non-empty-group : [ on $(target1) return $(v1) ] - [ on $(target1) return $(v2) ] - [ on $(target1) return $(v3) ] : z - z - z ;
995
996v1 on $(target1) = x1 ;
997v2 on $(target1) = x2 ;
998v3 on $(target1) = x3 ;
999$(vars) on $(target1) += z ;
1000check-equal settings-append-non-empty-group : [ on $(target1) return $(v1) ] - [ on $(target1) return $(v2) ] - [ on $(target1) return $(v3) ] : x1 z - x2 z - x3 z ;
1001
1002v1 on $(target1) = x1 ;
1003v2 on $(target1) = x2 ;
1004v3 on $(target1) = x3 ;
1005$(vars) on $(target1) ?= z ;
1006check-equal settings-default-non-empty-group : [ on $(target1) return $(v1) ] - [ on $(target1) return $(v2) ] - [ on $(target1) return $(v3) ] : x1 - x2 - x3 ;
1007
1008v1 on setting-target5 = x1 ;
1009v3 on setting-target5 = x3 ;
1010$(vars) on setting-target5 = z ;
1011check-equal settings-set-mixed-group : [ on setting-target5 return $(v1) ] - [ on setting-target5 return $(v2) ] - [ on setting-target5 return $(v3) ] : z - z - z ;
1012
1013v1 on setting-target6 = x1 ;
1014v3 on setting-target6 = x3 ;
1015$(vars) on setting-target6 += z ;
1016check-equal settings-append-mixed-group : [ on setting-target6 return $(v1) ] - [ on setting-target6 return $(v2) ] - [ on setting-target6 return $(v3) ] : x1 z - z - x3 z ;
1017
1018v1 on setting-target7 = x1 ;
1019v3 on setting-target7 = x3 ;
1020$(vars) on setting-target7 ?= z ;
1021check-equal settings-default-mixed-group : [ on setting-target7 return $(v1) ] - [ on setting-target7 return $(v2) ] - [ on setting-target7 return $(v3) ] : x1 - z - x3 ;
1022
1023vars = v1 v1 ;
1024
1025$(vars) on setting-target8 = z ;
1026check-equal settings-set-duplicate-empty : [ on setting-target8 return $(v1) ] : z ;
1027$(vars) on setting-target9 += z ;
1028check-equal settings-append-duplicate-empty : [ on setting-target9 return $(v1) ] : z z ;
1029$(vars) on setting-target10 ?= z ;
1030check-equal settings-default-duplicate-empty : [ on setting-target10 return $(v1) ] : z ;
1031
1032v1 on $(target1) = x1 ;
1033$(vars) on $(target1) = z ;
1034check-equal settings-set-duplicate-non-empty : [ on $(target1) return $(v1) ] : z ;
1035v1 on $(target1) = x1 ;
1036$(vars) on $(target1) += z ;
1037check-equal settings-append-duplicate-non-empty : [ on $(target1) return $(v1) ] : x1 z z ;
1038v1 on $(target1) = x1 ;
1039$(vars) on $(target1) ?= z ;
1040check-equal settings-default-duplicate-non-empty : [ on $(target1) return $(v1) ] : x1 ;
1041
1042v1 on $(target1) = ;
1043v1 on $(target1) ?= z ;
1044check-equal settings-default-set-but-empty : [ on $(target1) return $(v1) ] : ;
1045
1046v1 on $(targets) = multi ;
1047check-equal settings-set-multi-empty : [ on $(target2) return $(v1) ] - [ on $(target3) return $(v1) ] : multi - multi ;
1048v2 on $(targets) += multi ;
1049check-equal settings-append-multi-empty : [ on $(target2) return $(v2) ] - [ on $(target3) return $(v2) ] : multi - multi ;
1050v3 on $(targets) ?= multi ;
1051check-equal settings-default-multi-empty : [ on $(target2) return $(v3) ] - [ on $(target3) return $(v3) ] : multi - multi ;
1052
1053v1 on $(targets) = multi2 ;
1054check-equal settings-set-multi-empty : [ on $(target2) return $(v1) ] - [ on $(target3) return $(v1) ] : multi2 - multi2 ;
1055v2 on $(targets) += multi2 ;
1056check-equal settings-append-multi-empty : [ on $(target2) return $(v2) ] - [ on $(target3) return $(v2) ] : multi multi2 - multi multi2 ;
1057v3 on $(targets) ?= multi2 ;
1058check-equal settings-default-multi-empty : [ on $(target2) return $(v3) ] - [ on $(target3) return $(v3) ] : multi - multi ;
1059
1060rule test-rule { v1 on $(target1) = x1 ; }
1061check-equal settings-set-result : [ test-rule ] : x1 ;
1062rule test-rule { v1 on $(target1) += x1 ; }
1063check-equal settings-append-result : [ test-rule ] : x1 ;
1064rule test-rule { v1 on $(target1) ?= x1 ; }
1065check-equal settings-default-result : [ test-rule ] : x1 ;
1066
1067[ mark-order r1 : var ] on [ mark-order r3 : $(target1) ] = [ mark-order r2 : value ] ;
1068check-order settings-set-order : r1 r2 r3 ;
1069[ mark-order r1 : var ] on [ mark-order r3 : $(target1) ] += [ mark-order r2 : value ] ;
1070check-order settings-append-order : r1 r2 r3 ;
1071[ mark-order r1 : var ] on [ mark-order r3 : $(target1) ] ?= [ mark-order r2 : value ] ;
1072check-order settings-default-order : r1 r2 r3 ;
1073
1074}
1075
1076# Check switch
1077
1078{
1079
1080local pattern = * ;
1081
1082switch value
1083{
1084    case * : mark-order r1 ;
1085}
1086
1087check-order switch-match-any : r1 ;
1088
1089switch value
1090{
1091    case v2 : mark-order r1 ;
1092}
1093
1094check-order switch-no-match : ;
1095
1096switch value
1097{
1098    case $(pattern) : mark-order r1 ;
1099}
1100
1101check-order switch-no-expand : ;
1102
1103switch value
1104{
1105    case value : mark-order r1 ;
1106    case * : mark-order r2 ;
1107}
1108
1109check-order switch-match-several : r1 ;
1110
1111rule test-rule ( value )
1112{
1113    switch $(value)
1114    {
1115        case value : return 1 ;
1116    }
1117}
1118
1119check-equal switch-result-match : [ test-rule value ] : 1 ;
1120check-equal switch-result-match : [ test-rule v1 ] : ;
1121
1122switch $()
1123{
1124    case "" : mark-order r1 ;
1125    case * : mark-order r2 ;
1126}
1127
1128check-order switch-empty : r1 ;
1129
1130local values = v1 v2 v3 ;
1131switch $(values)
1132{
1133    case v1 : mark-order r1 ;
1134    case v2 : mark-order r2 ;
1135    case v3 : mark-order r3 ;
1136}
1137
1138check-order switch-multiple : r1 ;
1139
1140# Test glob matching
1141
1142switch value { case * : mark-order r1 ; }
1143check-order switch-glob-star : r1 ;
1144
1145switch value { case va*e : mark-order r1 ; }
1146check-order switch-glob-star-1 : r1 ;
1147
1148switch value { case *a* : mark-order r1 ; }
1149check-order switch-glob-star-2 : r1 ;
1150
1151switch value { case *a*ue* : mark-order r1 ; }
1152check-order switch-glob-star-3 : r1 ;
1153
1154switch value { case *[eaiou]*ue : mark-order r1 ; }
1155check-order switch-glob-group : r1 ;
1156
1157switch value { case *[eaiou]ue : mark-order r1 ; }
1158check-order switch-glob-group-fail : ;
1159
1160switch value { case ?a?ue : mark-order r1 ; }
1161check-order switch-glob-any : r1 ;
1162
1163switch value { case ?lue : mark-order r1 ; }
1164check-order switch-glob-any-fail : ;
1165
1166}
1167
1168# Test while
1169
1170{
1171
1172local value = 1 2 3 ;
1173
1174while $(value)
1175{
1176    mark-order r$(value[1]) ;
1177    value = $(value[2-]) ;
1178}
1179
1180check-order while-exec : r1 r2 r3 ;
1181
1182rule test-rule
1183{
1184    local value = 1 2 3 ;
1185    while $(value)
1186    {
1187        value = $(value[2-]) ;
1188        return x ;
1189    }
1190}
1191
1192check-equal while-result : [ test-rule ] : x ;
1193
1194rule test-rule
1195{
1196    local value = 1 2 ;
1197    while $(value)
1198    {
1199        value = $(value[2-]) ;
1200        local inner = $(value) ;
1201        while $(inner)
1202        {
1203            inner = $(inner[2-]) ;
1204            return x ;
1205        }
1206    }
1207}
1208
1209check-equal while-result-2 : [ test-rule ] : x ;
1210
1211}
1212
1213
1214#
1215# test break
1216#
1217
1218{
1219
1220local z = original ;
1221local done ;
1222while ! $(done)
1223{
1224    local z = inner ;
1225    mark-order r1 ;
1226    break ;
1227    mark-order r2 ;
1228    done = true ;
1229}
1230
1231check-order break-while-exec : r1 ;
1232check-equal break-while-cleanup : $(z) : original ;
1233
1234local values = v1 v2 ;
1235
1236for y in $(values)
1237{
1238    local z = inner ;
1239    mark-order r1-$(y) ;
1240    break ;
1241    mark-order r2-$(y) ;
1242}
1243
1244check-order break-for-exec : r1-v1 ;
1245check-equal break-for-cleanup : $(z) : original ;
1246
1247for local y in $(values)
1248{
1249    local z = inner ;
1250    mark-order r1-$(y) ;
1251    break ;
1252    mark-order r2-$(y) ;
1253}
1254
1255check-order break-for-local-exec : r1-v1 ;
1256check-equal break-for-local-cleanup : $(z) : original ;
1257
1258local z1 = z1val ;
1259local z2 = z2val ;
1260done = ;
1261while ! $(done)
1262{
1263    local z1 = z1new ;
1264    mark-order r1 ;
1265    for local y in $(values)
1266    {
1267        local z2 = z2new ;
1268        mark-order r2 ;
1269        break ;
1270        mark-order r3 ;
1271    }
1272    mark-order r4 ;
1273    break ;
1274    mark-order r5 ;
1275    done = true ;
1276}
1277
1278check-order break-nested-exec : r1 r2 r4 ;
1279check-equal break-nested-cleanup1 : $(z1) : z1val ;
1280check-equal break-nested-cleanup2 : $(z2) : z2val ;
1281
1282}
1283
1284#
1285# test continue
1286#
1287
1288{
1289
1290local z = original ;
1291local done ;
1292while ! [ mark-order r1 : $(done) ]
1293{
1294    local z = inner ;
1295    done = true ;
1296    mark-order r2 ;
1297    continue ;
1298    mark-order r3 ;
1299}
1300
1301check-order continue-while-exec : r1 r2 r1 ;
1302check-equal continue-while-cleanup : $(z) : original ;
1303
1304local values = v1 v2 ;
1305for y in $(values)
1306{
1307    local z = inner ;
1308    mark-order r1-$(y) ;
1309    continue ;
1310    mark-order r2-$(y) ;
1311}
1312
1313check-order continue-for-exec : r1-v1 r1-v2 ;
1314check-equal continue-for-cleanup : $(z) : original ;
1315
1316for local y in $(values)
1317{
1318    local z = inner ;
1319    mark-order r1-$(y) ;
1320    continue ;
1321    mark-order r2-$(y) ;
1322}
1323
1324check-order continue-for-local-exec : r1-v1 r1-v2 ;
1325check-equal continue-for-local-cleanup : $(z) : original ;
1326
1327local z1 = z1val ;
1328local z2 = z2val ;
1329done = ;
1330while ! [ mark-order r1 : $(done) ]
1331{
1332    local z1 = z1new ;
1333    done = true ;
1334    mark-order r2 ;
1335    for local y in $(values)
1336    {
1337        local z2 = z2new ;
1338        mark-order r3-$(y) ;
1339        continue ;
1340        mark-order r4-$(y) ;
1341    }
1342    mark-order r5 ;
1343    continue ;
1344    mark-order r6 ;
1345}
1346
1347check-order continue-nested-exec : r1 r2 r3-v1 r3-v2 r5 r1 ;
1348check-equal continue-nested-cleanup1 : $(z1) : z1val ;
1349check-equal continue-nested-cleanup2 : $(z2) : z2val ;
1350
1351}
1352
1353#
1354# test CALLER_MODULE and backtrace
1355#
1356
1357{
1358    local base = [ BACKTRACE ] ;
1359    base = $(base[2]) ;
1360    rule backtrace ( )
1361    {
1362        local bt = [ BACKTRACE ] ;
1363        check-equal backtrace-1-file : $(bt) :
1364            test.jam [ CALC $(base) +  4 ] ""       backtrace
1365            test.jam [ CALC $(base) + 28 ] module2. module2.f
1366            test.jam [ CALC $(base) + 19 ] module1. module1.f
1367            test.jam [ CALC $(base) + 32 ] ""       "module scope"
1368        ;
1369    }
1370    module module1
1371    {
1372        IMPORT_MODULE module2 : module1 ;
1373        rule f ( )
1374        {
1375            local m = [ CALLER_MODULE ] ;
1376            check-equal caller-module-root : $(m) ;
1377            module2.f ;
1378        }
1379    }
1380    module module2
1381    {
1382        rule f ( )
1383        {
1384            local m = [ CALLER_MODULE ] ;
1385            check-equal caller-module : module1 : $(m) ;
1386            backtrace ;
1387        }
1388    }
1389    IMPORT_MODULE module1 ;
1390    module1.f ;
1391}
1392
1393
1394# Test NORMALIZE_PATH
1395
1396{
1397check-equal normalize-path : "."     : [ NORMALIZE_PATH ] ;
1398check-equal normalize-path : "."     : [ NORMALIZE_PATH "" ] ;
1399check-equal normalize-path : "."     : [ NORMALIZE_PATH "." ] ;
1400check-equal normalize-path : ".."    : [ NORMALIZE_PATH ".." ] ;
1401check-equal normalize-path : "/"     : [ NORMALIZE_PATH "/" ] ;
1402check-equal normalize-path : "/"     : [ NORMALIZE_PATH "\\" ] ;
1403check-equal normalize-path : "/"     : [ NORMALIZE_PATH "//" ] ;
1404check-equal normalize-path : "/"     : [ NORMALIZE_PATH "\\\\" ] ;
1405check-equal normalize-path : "/"     : [ NORMALIZE_PATH "//\\\\//\\\\" ] ;
1406check-equal normalize-path : "/"     : [ NORMALIZE_PATH "/." ] ;
1407check-equal normalize-path : "/"     : [ NORMALIZE_PATH "/./" ] ;
1408check-equal normalize-path : "/"     : [ NORMALIZE_PATH "\\\\///.///\\\\\\" ] ;
1409check-equal normalize-path : "."     : [ NORMALIZE_PATH "./././././." ] ;
1410check-equal normalize-path : "/"     : [ NORMALIZE_PATH "/./././././." ] ;
1411check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo" ] ;
1412check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo/" ] ;
1413check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo\\" ] ;
1414check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo\\\\/////" ] ;
1415check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo\\\\/////././." ] ;
1416check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo\\\\/////./././" ] ;
1417check-equal normalize-path : "."     : [ NORMALIZE_PATH "foo/.." ] ;
1418check-equal normalize-path : "."     : [ NORMALIZE_PATH "foo////.." ] ;
1419check-equal normalize-path : "/"     : [ NORMALIZE_PATH "///foo/\\\\/.." ] ;
1420check-equal normalize-path : "/"     : [ NORMALIZE_PATH "\\\\\\foo\\//\\.." ] ;
1421check-equal normalize-path : "."     : [ NORMALIZE_PATH "foo/./.." ] ;
1422check-equal normalize-path : "."     : [ NORMALIZE_PATH "foo/././././.." ] ;
1423check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo/./././bar/./././.././././baz/./././.." ] ;
1424check-equal normalize-path : "/foo"  : [ NORMALIZE_PATH "/foo/./././bar/./././.././././baz/./././.." ] ;
1425check-equal normalize-path : "foo"   : [ NORMALIZE_PATH "foo/./././bar/./././////.././././baz/./././.." ] ;
1426check-equal normalize-path : "/foo"  : [ NORMALIZE_PATH "/foo/./././bar/./././////.././././baz/./././.." ] ;
1427check-equal normalize-path : ".."    : [ NORMALIZE_PATH "./.." ] ;
1428check-equal normalize-path : ".."    : [ NORMALIZE_PATH "././././.." ] ;
1429check-equal normalize-path : "../.." : [ NORMALIZE_PATH "../.." ] ;
1430check-equal normalize-path : "../.." : [ NORMALIZE_PATH "./../.." ] ;
1431check-equal normalize-path : "../.." : [ NORMALIZE_PATH "././././../.." ] ;
1432check-equal normalize-path : "../.." : [ NORMALIZE_PATH "./.././././.." ] ;
1433check-equal normalize-path : "../.." : [ NORMALIZE_PATH "././././.././././.." ] ;
1434check-equal normalize-path : "../.." : [ NORMALIZE_PATH "..//\\\\\\//.." ] ;
1435check-equal normalize-path : "../.." : [ NORMALIZE_PATH "../..\\\\/\\\\" ] ;
1436check-equal normalize-path : "."     : [ NORMALIZE_PATH "foo/../bar/../baz/.." ] ;
1437check-equal normalize-path : "."     : [ NORMALIZE_PATH "foo////..////bar////.//////.////../baz/.." ] ;
1438check-equal normalize-path : "/"     : [ NORMALIZE_PATH "/foo/../bar/../baz/.." ] ;
1439check-equal normalize-path : "/"     : [ NORMALIZE_PATH "/foo////..////bar////.//////.////../baz/.." ] ;
1440
1441# Invalid rooted paths with leading dotdots.
1442check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/.." ] ;
1443check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/../" ] ;
1444check-equal normalize-path-invalid : : [ NORMALIZE_PATH "//\\\\//\\\\/.." ] ;
1445check-equal normalize-path-invalid : : [ NORMALIZE_PATH "\\\\//\\\\//\\.." ] ;
1446check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/../.." ] ;
1447check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/../../.." ] ;
1448check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/foo/bar/../baz/../../.." ] ;
1449check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/../for/././../././bar/././../././.." ] ;
1450check-equal normalize-path-invalid : : [ NORMALIZE_PATH "/../foo/bar" ] ;
1451
1452check-equal normalize-path : "../d" : [ NORMALIZE_PATH "../d" ] ;
1453check-equal normalize-path : "../d" : [ NORMALIZE_PATH ".." "d" ] ;
1454check-equal normalize-path : "../../d" : [ NORMALIZE_PATH ".." ".." "d" ] ;
1455check-equal normalize-path : "../d" : [ NORMALIZE_PATH "" ".." "d" ] ;
1456
1457}
1458
1459# Test W32_GETREGNAMES
1460
1461{
1462
1463if $(NT)
1464{
1465    local sound = "Beep" "ExtendedSounds" ;
1466    local r1 = [ W32_GETREGNAMES "HKEY_CURRENT_USER\\Control Panel\\Sound" :
1467        values ] ;
1468    check-equal w32_getregnames : $(sound:L) : [ SORT $(r1:L) ] ;
1469    local r2 = [ W32_GETREGNAMES "HKCU\\Control Panel\\Sound" : values ] ;
1470    check-equal w32_getregnames : $(sound:L) : [ SORT $(r2:L) ] ;
1471
1472    #   Some Windows platforms may have additional keys under
1473    # 'CurrentControlSet' which we then remove here so they would not be
1474    # reported as errors by our test.
1475    local rule remove-policies ( param * )
1476    {
1477        local found ;
1478        local r ;
1479        for local x in $(param:L)
1480        {
1481            if ! x in $(found) &&
1482                $(x) in "addservices" "policies" "deleted device ids" "software"
1483            {
1484                found += $(x) ;
1485            }
1486            else
1487            {
1488                r += $(x) ;
1489            }
1490        }
1491        return $(r) ;
1492    }
1493    local CurrentControlSet = "Control" "Enum" "Hardware Profiles" "Services" ;
1494    local r3 = [ W32_GETREGNAMES "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet"
1495        : subkeys ] ;
1496    check-equal w32_getregnames : $(CurrentControlSet:L) : [ remove-policies
1497        $(r3:L) ] ;
1498    local r4 = [ W32_GETREGNAMES "HKLM\\SYSTEM\\CurrentControlSet" : subkeys ] ;
1499    check-equal w32_getregnames : $(CurrentControlSet:L) : [ remove-policies
1500        $(r4:L) ] ;
1501}
1502
1503}
1504
1505# Test SHELL
1506
1507{
1508
1509local c = "echo value" ;
1510if $(OS) = VMS { c = "PIPE WRITE SYS$OUTPUT \"value\"" ; }
1511
1512check-equal shell : "value\n"   : [ SHELL $(c) ] ;
1513check-equal shell : ""          : [ SHELL $(c) : no-output ] ;
1514check-equal shell : "value\n" 0 : [ SHELL $(c) : exit-status ] ;
1515check-equal shell : ""      0   : [ SHELL $(c) : no-output : exit-status ] ;
1516check-equal shell : ""      0   : [ SHELL $(c) : no-output : exit-status : strip-eol ] ;
1517check-equal command : "value\n"   : [ COMMAND $(c) ] ;
1518check-equal command : ""          : [ COMMAND $(c) : no-output ] ;
1519check-equal command : "value\n" 0 : [ COMMAND $(c) : exit-status ] ;
1520check-equal command : ""      0   : [ COMMAND $(c) : no-output : exit-status ] ;
1521
1522# buffered output
1523
1524local expected = "When the shell output buffer splits on whitespace, the whitespace shouldn't be trimmed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             end." ;
1525local buffered = "echo \"$(expected)\"" ;
1526if $(OS) = VMS { buffered = "PIPE WRITE SYS$OUTPUT \"$(expected)\"" ; }
1527if $(OS) = NT { buffered = "echo $(expected)" ; }
1528
1529check-equal shell : "$(expected)\n"   : [ SHELL $(buffered) ] ;
1530check-equal shell : ""                : [ SHELL $(buffered) : no-output ] ;
1531check-equal shell : "$(expected)\n" 0 : [ SHELL $(buffered) : exit-status ] ;
1532check-equal shell : "$(expected)" 0 : [ SHELL $(buffered) : strip-eol : exit-status ] ;
1533check-equal shell : ""      0         : [ SHELL $(buffered) : no-output : exit-status ] ;
1534check-equal shell : ""      0         : [ SHELL $(buffered) : no-output : exit-status : strip-eol ] ;
1535check-equal shell : "$(expected)" 0 : [ SHELL $(buffered) : strip-eol : exit-status ] ;
1536
1537check-equal command : "$(expected)\n"   : [ COMMAND $(buffered) ] ;
1538check-equal command : ""                : [ COMMAND $(buffered) : no-output ] ;
1539check-equal command : "$(expected)\n" 0 : [ COMMAND $(buffered) : exit-status ] ;
1540check-equal command : "$(expected)" 0 : [ COMMAND $(buffered) : strip-eol : exit-status ] ;
1541check-equal command : ""      0         : [ COMMAND $(buffered) : no-output : exit-status ] ;
1542
1543}
1544
1545# Test SUBST
1546
1547{
1548
1549# Check that unmatched subst returns an empty list
1550check-equal subst-nomatch : [ SUBST "abc" "d+" x ] : ;
1551
1552# Check that a matched subst works
1553check-equal subst-match : [ SUBST "ddd" "d+" x ] : x ;
1554
1555# Check that we can get multiple substitutions from a single invocation
1556check-equal subst-multiple : [ SUBST "x/y/z" "([^/]*)/([^/]*).*" "\\1" $2 "\\1-\\2" ] : x y x-y ;
1557
1558}
1559
1560# Test summary
1561
1562if $(failed) = 0
1563{
1564    status = 0 ;
1565}
1566else
1567{
1568    status = 1 ;
1569}
1570
1571EXIT $(passed) passed $(failed) failed : $(status) ;
1572