Imported Upstream version 1.57.0
[platform/upstream/boost.git] / tools / build / src / tools / testing-aux.jam
1 # This module is imported by testing.py. The definitions here are
2 # too tricky to do in Python
3
4 # Causes the 'target' to exist after bjam invocation if and only if all the
5 # dependencies were successfully built.
6 #
7 rule expect-success ( target : dependency + : requirements * )
8 {
9     **passed** $(target) : $(sources) ;
10 }
11 IMPORT testing : expect-success : : testing.expect-success ;
12
13 # Causes the 'target' to exist after bjam invocation if and only if all some of
14 # the dependencies were not successfully built.
15 #
16 rule expect-failure ( target : dependency + : properties * )
17 {
18     local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ;
19     local marker = $(dependency:G=$(grist)*fail) ;
20     (failed-as-expected) $(marker) ;
21     FAIL_EXPECTED $(dependency) ;
22     LOCATE on $(marker) = [ on $(dependency) return $(LOCATE) ] ;
23     RMOLD $(marker) ;
24     DEPENDS $(marker) : $(dependency) ;
25     DEPENDS $(target) : $(marker) ;
26     **passed** $(target) : $(marker) ;
27 }
28 IMPORT testing : expect-failure : : testing.expect-failure ;
29
30 # The rule/action combination used to report successful passing of a test.
31 #
32 rule **passed**
33 {
34     # Force deletion of the target, in case any dependencies failed to build.
35     RMOLD $(<) ;
36 }
37
38
39 # Used to create test files signifying passed tests.
40 #
41 actions **passed**
42 {
43     echo passed > "$(<)"
44 }
45
46
47 # Used to create replacement object files that do not get created during tests
48 # that are expected to fail.
49 #
50 actions (failed-as-expected)
51 {
52     echo failed as expected > "$(<)"
53 }
54
55 # Runs executable 'sources' and stores stdout in file 'target'. Unless
56 # --preserve-test-targets command line option has been specified, removes the
57 # executable. The 'target-to-remove' parameter controls what should be removed:
58 #   - if 'none', does not remove anything, ever
59 #   - if empty, removes 'source'
60 #   - if non-empty and not 'none', contains a list of sources to remove.
61 #
62 rule capture-output ( target : source : properties * : targets-to-remove * )
63 {
64     output-file on $(target) = $(target:S=.output) ;
65     LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ;
66
67     # The INCLUDES kill a warning about independent target...
68     INCLUDES $(target) : $(target:S=.output) ;
69     # but it also puts .output into dependency graph, so we must tell jam it is
70     # OK if it cannot find the target or updating rule.
71     NOCARE $(target:S=.output) ;
72
73     # This has two-fold effect. First it adds input files to the dependendency
74     # graph, preventing a warning. Second, it causes input files to be bound
75     # before target is created. Therefore, they are bound using SEARCH setting
76     # on them and not LOCATE setting of $(target), as in other case (due to jam
77     # bug).
78     DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ;
79
80     if $(targets-to-remove) = none
81     {
82         targets-to-remove = ;
83     }
84     else if ! $(targets-to-remove)
85     {
86         targets-to-remove = $(source) ;
87     }
88
89     if [ on $(target) return $(REMOVE_TEST_TARGETS) ]
90     {
91         TEMPORARY $(targets-to-remove) ;
92         # Set a second action on target that will be executed after capture
93         # output action. The 'RmTemps' rule has the 'ignore' modifier so it is
94         # always considered succeeded. This is needed for 'run-fail' test. For
95         # that test the target will be marked with FAIL_EXPECTED, and without
96         # 'ignore' successful execution will be negated and be reported as
97         # failure. With 'ignore' we do not detect a case where removing files
98         # fails, but it is not likely to happen.
99         RmTemps $(target) : $(targets-to-remove) ;
100     }
101 }
102
103
104 if [ os.name ] = NT
105 {
106     .STATUS        = %status% ;
107     .SET_STATUS    = "set status=%ERRORLEVEL%" ;
108     .RUN_OUTPUT_NL = "echo." ;
109     .STATUS_0      = "%status% EQU 0 (" ;
110     .STATUS_NOT_0  = "%status% NEQ 0 (" ;
111     .VERBOSE       = "%verbose% EQU 1 (" ;
112     .ENDIF         = ")" ;
113     .SHELL_SET     = "set " ;
114     .CATENATE      = type ;
115     .CP            = copy ;
116 }
117 else
118 {
119     .STATUS        = "$status" ;
120     .SET_STATUS    = "status=$?" ;
121     .RUN_OUTPUT_NL = "echo" ;
122     .STATUS_0      = "test $status -eq 0 ; then" ;
123     .STATUS_NOT_0  = "test $status -ne 0 ; then" ;
124     .VERBOSE       = "test $verbose -eq 1 ; then" ;
125     .ENDIF         = "fi" ;
126     .SHELL_SET     = "" ;
127     .CATENATE      = cat ;
128     .CP            = cp ;
129 }
130
131
132 .VERBOSE_TEST = 0 ;
133 if --verbose-test in [ modules.peek : ARGV ]
134 {
135     .VERBOSE_TEST = 1 ;
136 }
137
138
139 .RM = [ common.rm-command ] ;
140
141
142 actions capture-output bind INPUT_FILES output-file
143 {
144     $(PATH_SETUP)
145     $(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1
146     $(.SET_STATUS)
147     $(.RUN_OUTPUT_NL) >> "$(output-file)"
148     echo EXIT STATUS: $(.STATUS) >> "$(output-file)"
149     if $(.STATUS_0)
150         $(.CP) "$(output-file)" "$(<)"
151     $(.ENDIF)
152     $(.SHELL_SET)verbose=$(.VERBOSE_TEST)
153     if $(.STATUS_NOT_0)
154         $(.SHELL_SET)verbose=1
155     $(.ENDIF)
156     if $(.VERBOSE)
157         echo ====== BEGIN OUTPUT ======
158         $(.CATENATE) "$(output-file)"
159         echo ====== END OUTPUT ======
160     $(.ENDIF)
161     exit $(.STATUS)
162 }
163
164 IMPORT testing : capture-output : : testing.capture-output ;
165
166
167 actions quietly updated ignore piecemeal together RmTemps
168 {
169     $(.RM) "$(>)"
170 }
171
172
173 .MAKE_FILE = [ common.file-creation-command ] ;
174
175 actions unit-test
176 {
177     $(PATH_SETUP)
178     $(LAUNCHER) "$(>)" $(ARGS) && $(.MAKE_FILE) "$(<)"
179 }
180
181 # Note that this rule may be called multiple times for a single target in case
182 # there are multiple actions operating on the same target in sequence. One such
183 # example are msvc exe targets first created by a linker action and then updated
184 # with an embedded manifest file by a separate action.
185 rule record-time ( target : source : start end user system )
186 {
187     local src-string = [$(source:G=:J=",")"] " ;
188     USER_TIME on $(target) += $(src-string)$(user) ;
189     SYSTEM_TIME on $(target) += $(src-string)$(system) ;
190
191     # We need the following variables because attempting to perform such
192     # variable expansion in actions would not work due to quotes getting treated
193     # as regular characters.
194     USER_TIME_SECONDS on $(target) += $(src-string)$(user)" seconds" ;
195     SYSTEM_TIME_SECONDS on $(target) += $(src-string)$(system)" seconds" ;
196 }
197
198 # Calling this rule requests that Boost Build time how long it takes to build
199 # the 'source' target and display the results both on the standard output and in
200 # the 'target' file.
201 #
202 rule time ( target : sources + : properties *  )
203 {
204     # Set up rule for recording timing information.
205     __TIMING_RULE__ on $(sources) = testing.record-time $(target) ;
206
207     # Make sure the sources get rebuilt any time we need to retrieve that
208     # information.
209     REBUILDS $(target) : $(sources) ;
210 }
211
212
213 actions time
214 {
215     echo user: $(USER_TIME)
216     echo system: $(SYSTEM_TIME)
217
218     echo user: $(USER_TIME_SECONDS) > "$(<)"
219     echo system: $(SYSTEM_TIME_SECONDS) >> "$(<)"
220 }