1#!/usr/local/bin/python3.8
2
3import BoostBuild
4
5def test_basic():
6    '''Tests that feature=value works'''
7    t = BoostBuild.Tester()
8    t.write('Jamroot.jam', '''
9    import feature : feature ;
10    import toolset : flags ;
11    feature f1 : 1 2 ;
12    make output.txt : : @run ;
13    flags run OPTIONS <f1> ;
14    actions run { echo $(OPTIONS) > $(<) }
15    ''')
16    t.run_build_system(['f1=2'])
17    t.expect_content("bin/*/output.txt", "2")
18    t.cleanup()
19
20def test_implicit():
21    '''Tests that implicit features can be named without a feature'''
22    t = BoostBuild.Tester()
23    t.write('Jamroot.jam', '''
24    import feature : feature ;
25    import toolset : flags ;
26    feature f1 : v1 v2 : implicit ;
27    make output.txt : : @run ;
28    flags run OPTIONS <f1> ;
29    actions run { echo $(OPTIONS) > $(<) }
30    ''')
31    t.run_build_system(['v2'])
32    t.expect_content("bin/*/output.txt", "v2")
33    t.cleanup()
34
35def test_optional():
36    '''Tests that feature= works for optional features'''
37    t = BoostBuild.Tester()
38    t.write('Jamroot.jam', '''
39    import feature : feature ;
40    import toolset : flags ;
41    feature f1 : 1 2 : optional ;
42    make output.txt : : @run ;
43    flags run OPTIONS <f1> ;
44    actions run { echo b $(OPTIONS) > $(<) }
45    ''')
46    t.run_build_system(['f1='])
47    t.expect_content("bin/*/output.txt", "b")
48    t.cleanup()
49
50def test_free():
51    '''Free features named on the command line apply to all targets
52    everywhere.  Free features can contain any characters, even those
53    that have a special meaning.'''
54    t = BoostBuild.Tester()
55    t.write('Jamroot.jam', '''
56    import feature : feature ;
57    import toolset : flags ;
58    feature f1 : : free ;
59    make output1.txt : : @run : <dependency>output2.txt ;
60    make output2.txt : : @run ;
61    explicit output2.txt ;
62    flags run OPTIONS <f1> ;
63    actions run { echo $(OPTIONS) > $(<) }
64    ''')
65    t.run_build_system(['f1=x,/:-'])
66    t.expect_content("bin*/output1.txt", "x,/:-")
67    t.expect_content("bin*/output2.txt", "x,/:-")
68    t.cleanup()
69
70def test_subfeature():
71    '''Subfeatures should be expressed as feature=value-subvalue'''
72    t = BoostBuild.Tester()
73    t.write('Jamroot.jam', '''
74    import feature : feature subfeature ;
75    import toolset : flags ;
76    feature f1 : 1 2 ;
77    subfeature f1 2 : sub : x y ;
78    make output.txt : : @run ;
79    flags run OPTIONS <f1-2:sub> ;
80    actions run { echo $(OPTIONS) > $(<) }
81    ''')
82    t.run_build_system(['f1=2-y'])
83    t.expect_content("bin/*/output.txt", "y")
84    t.cleanup()
85
86def test_multiple_values():
87    '''Multiple values of a feature can be given in a comma-separated list'''
88    t = BoostBuild.Tester()
89    t.write('Jamroot.jam', '''
90    import feature : feature ;
91    import toolset : flags ;
92    feature f1 : 1 2 3 ;
93    make output.txt : : @run ;
94    flags run OPTIONS <f1> ;
95    actions run { echo $(OPTIONS) > $(<) }
96    ''')
97    t.run_build_system(['f1=2,3'])
98    t.expect_content("bin*/f1-2*/output.txt", "2")
99    t.expect_content("bin*/f1-3*/output.txt", "3")
100    t.cleanup()
101
102def test_multiple_properties():
103    '''Multiple properties can be grouped with /'''
104    t = BoostBuild.Tester()
105    t.write('Jamroot.jam', '''
106    import feature : feature ;
107    import toolset : flags ;
108    feature f1 : 1 2 ;
109    feature f2 : 3 4 ;
110    make output.txt : : @run ;
111    flags run OPTIONS <f1> ;
112    flags run OPTIONS <f2> ;
113    actions run { echo $(OPTIONS) > $(<) }
114    ''')
115    t.run_build_system(['f1=2/f2=4'])
116    t.expect_content("bin/*/output.txt", "2 4")
117    t.cleanup()
118
119def test_cross_product():
120    '''If multiple properties are specified on the command line
121    we expand to every possible maximum set of non-conflicting features.
122    This test should be run after testing individual components in
123    isolation.'''
124    t = BoostBuild.Tester()
125    t.write('Jamroot.jam', '''
126    import feature : feature ;
127    import toolset : flags ;
128    # Make features symmetric to make the paths easier to distinguish
129    feature f1 : 11 12 13 14 15 : symmetric ;
130    feature f2 : 21 22 23 : symmetric ;
131    feature f3 : v1 v2 v3 v4 : implicit symmetric ;
132    feature f4 : : free ;
133    make output.txt : : @run ;
134    flags run OPTIONS <f1> ;
135    flags run OPTIONS <f2> ;
136    flags run OPTIONS <f3> ;
137    flags run OPTIONS <f4> ;
138    actions run { echo $(OPTIONS) > $(<) }
139    ''')
140    t.run_build_system(['f1=12,13/f2=22', 'v2', 'v3', 'f1=14', 'f2=23',
141                       'f4=xxx', 'f4=yyy', 'v4/f1=15/f4=zzz'])
142    t.expect_content("bin*/v2*/f1-12/f2-22*/output.txt", "12 22 v2 xxx yyy")
143    t.expect_addition("bin*/v2*/f1-12/f2-22*/output.txt")
144    t.expect_content("bin*/v2*/f1-13/f2-22*/output.txt", "13 22 v2 xxx yyy")
145    t.expect_addition("bin*/v2*/f1-13/f2-22*/output.txt")
146    t.expect_content("bin*/v2*/f1-14/f2-23*/output.txt", "14 23 v2 xxx yyy")
147    t.expect_addition("bin*/v2*/f1-14/f2-23*/output.txt")
148    t.expect_content("bin*/v3*/f1-12/f2-22*/output.txt", "12 22 v3 xxx yyy")
149    t.expect_addition("bin*/v3*/f1-12/f2-22*/output.txt")
150    t.expect_content("bin*/v3*/f1-13/f2-22*/output.txt", "13 22 v3 xxx yyy")
151    t.expect_addition("bin*/v3*/f1-13/f2-22*/output.txt")
152    t.expect_content("bin*/v3*/f1-14/f2-23*/output.txt", "14 23 v3 xxx yyy")
153    t.expect_addition("bin*/v3*/f1-14/f2-23*/output.txt")
154    t.expect_content("bin*/v4*/f1-15/f2-23*/output.txt", "15 23 v4 xxx yyy zzz")
155    t.expect_addition("bin*/v4*/f1-15/f2-23*/output.txt")
156    t.expect_nothing_more()
157    t.cleanup()
158
159test_basic()
160test_implicit()
161test_optional()
162test_free()
163test_subfeature()
164test_multiple_values()
165test_multiple_properties()
166test_cross_product()
167