tesseract v5.3.3.20231005
googletest-failfast-unittest.py
Go to the documentation of this file.
1#!/usr/bin/env python
2#
3# Copyright 2020 Google Inc. All Rights Reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""Unit test for Google Test fail_fast.
32
33A user can specify if a Google Test program should continue test execution
34after a test failure via the GTEST_FAIL_FAST environment variable or the
35--gtest_fail_fast flag. The default value of the flag can also be changed
36by Bazel fail fast environment variable TESTBRIDGE_TEST_RUNNER_FAIL_FAST.
37
38This script tests such functionality by invoking googletest-failfast-unittest_
39(a program written with Google Test) with different environments and command
40line flags.
41"""
42
43import os
44import gtest_test_utils
45
46# Constants.
47
48# Bazel testbridge environment variable for fail fast
49BAZEL_FAIL_FAST_ENV_VAR = 'TESTBRIDGE_TEST_RUNNER_FAIL_FAST'
50
51# The environment variable for specifying fail fast.
52FAIL_FAST_ENV_VAR = 'GTEST_FAIL_FAST'
53
54# The command line flag for specifying fail fast.
55FAIL_FAST_FLAG = 'gtest_fail_fast'
56
57# The command line flag to run disabled tests.
58RUN_DISABLED_FLAG = 'gtest_also_run_disabled_tests'
59
60# The command line flag for specifying a filter.
61FILTER_FLAG = 'gtest_filter'
62
63# Command to run the googletest-failfast-unittest_ program.
65 'googletest-failfast-unittest_')
66
67# The command line flag to tell Google Test to output the list of tests it
68# will run.
69LIST_TESTS_FLAG = '--gtest_list_tests'
70
71# Indicates whether Google Test supports death tests.
72SUPPORTS_DEATH_TESTS = 'HasDeathTest' in gtest_test_utils.Subprocess(
73 [COMMAND, LIST_TESTS_FLAG]).output
74
75# Utilities.
76
77environ = os.environ.copy()
78
79
80def SetEnvVar(env_var, value):
81 """Sets the env variable to 'value'; unsets it when 'value' is None."""
82
83 if value is not None:
84 environ[env_var] = value
85 elif env_var in environ:
86 del environ[env_var]
87
88
89def RunAndReturnOutput(test_suite=None, fail_fast=None, run_disabled=False):
90 """Runs the test program and returns its output."""
91
92 args = []
93 xml_path = os.path.join(gtest_test_utils.GetTempDir(),
94 '.GTestFailFastUnitTest.xml')
95 args += ['--gtest_output=xml:' + xml_path]
96 if fail_fast is not None:
97 if isinstance(fail_fast, str):
98 args += ['--%s=%s' % (FAIL_FAST_FLAG, fail_fast)]
99 elif fail_fast:
100 args += ['--%s' % FAIL_FAST_FLAG]
101 else:
102 args += ['--no%s' % FAIL_FAST_FLAG]
103 if test_suite:
104 args += ['--%s=%s.*' % (FILTER_FLAG, test_suite)]
105 if run_disabled:
106 args += ['--%s' % RUN_DISABLED_FLAG]
107 txt_out = gtest_test_utils.Subprocess([COMMAND] + args, env=environ).output
108 with open(xml_path) as xml_file:
109 return txt_out, xml_file.read()
110
111
112# The unit test.
114 """Tests the env variable or the command line flag for fail_fast."""
115
117 """Tests the behavior of not specifying the fail_fast."""
118
119 txt, _ = RunAndReturnOutput()
120 self.assertIn('22 FAILED TEST', txt)
121
123 txt, _ = RunAndReturnOutput(test_suite='HasSimpleTest', fail_fast=True)
124 self.assertIn('1 FAILED TEST', txt)
125 self.assertIn('[ SKIPPED ] 3 tests', txt)
126
127 txt, _ = RunAndReturnOutput(test_suite='HasSimpleTest', fail_fast=False)
128 self.assertIn('4 FAILED TEST', txt)
129 self.assertNotIn('[ SKIPPED ]', txt)
130
132 """Tests the behavior of specifying fail_fast via Googletest env var."""
133
134 try:
135 SetEnvVar(FAIL_FAST_ENV_VAR, '1')
136 txt, _ = RunAndReturnOutput('HasSimpleTest')
137 self.assertIn('1 FAILED TEST', txt)
138 self.assertIn('[ SKIPPED ] 3 tests', txt)
139
140 SetEnvVar(FAIL_FAST_ENV_VAR, '0')
141 txt, _ = RunAndReturnOutput('HasSimpleTest')
142 self.assertIn('4 FAILED TEST', txt)
143 self.assertNotIn('[ SKIPPED ]', txt)
144 finally:
145 SetEnvVar(FAIL_FAST_ENV_VAR, None)
146
148 """Tests the behavior of specifying fail_fast via Bazel testbridge."""
149
150 try:
151 SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '1')
152 txt, _ = RunAndReturnOutput('HasSimpleTest')
153 self.assertIn('1 FAILED TEST', txt)
154 self.assertIn('[ SKIPPED ] 3 tests', txt)
155
156 SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '0')
157 txt, _ = RunAndReturnOutput('HasSimpleTest')
158 self.assertIn('4 FAILED TEST', txt)
159 self.assertNotIn('[ SKIPPED ]', txt)
160 finally:
161 SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, None)
162
164 """Tests precedence of flag over env var."""
165
166 try:
167 SetEnvVar(FAIL_FAST_ENV_VAR, '0')
168 txt, _ = RunAndReturnOutput('HasSimpleTest', True)
169 self.assertIn('1 FAILED TEST', txt)
170 self.assertIn('[ SKIPPED ] 3 tests', txt)
171 finally:
172 SetEnvVar(FAIL_FAST_ENV_VAR, None)
173
175 """Tests that the Googletest native env var over Bazel testbridge."""
176
177 try:
178 SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, '0')
179 SetEnvVar(FAIL_FAST_ENV_VAR, '1')
180 txt, _ = RunAndReturnOutput('HasSimpleTest')
181 self.assertIn('1 FAILED TEST', txt)
182 self.assertIn('[ SKIPPED ] 3 tests', txt)
183 finally:
184 SetEnvVar(FAIL_FAST_ENV_VAR, None)
185 SetEnvVar(BAZEL_FAIL_FAST_ENV_VAR, None)
186
188 txt, _ = RunAndReturnOutput(test_suite='HasSkipTest', fail_fast=True)
189 self.assertIn('1 FAILED TEST', txt)
190 self.assertIn('[ SKIPPED ] 3 tests', txt)
191 for expected_count, callback in [(1, 'OnTestSuiteStart'),
192 (5, 'OnTestStart'),
193 (5, 'OnTestEnd'),
194 (5, 'OnTestPartResult'),
195 (1, 'OnTestSuiteEnd')]:
196 self.assertEqual(
197 expected_count, txt.count(callback),
198 'Expected %d calls to callback %s match count on output: %s ' %
199 (expected_count, callback, txt))
200
201 txt, _ = RunAndReturnOutput(test_suite='HasSkipTest', fail_fast=False)
202 self.assertIn('3 FAILED TEST', txt)
203 self.assertIn('[ SKIPPED ] 1 test', txt)
204 for expected_count, callback in [(1, 'OnTestSuiteStart'),
205 (5, 'OnTestStart'),
206 (5, 'OnTestEnd'),
207 (5, 'OnTestPartResult'),
208 (1, 'OnTestSuiteEnd')]:
209 self.assertEqual(
210 expected_count, txt.count(callback),
211 'Expected %d calls to callback %s match count on output: %s ' %
212 (expected_count, callback, txt))
213
214 def assertXmlResultCount(self, result, count, xml):
215 self.assertEqual(
216 count, xml.count('result="%s"' % result),
217 'Expected \'result="%s"\' match count of %s: %s ' %
218 (result, count, xml))
219
220 def assertXmlStatusCount(self, status, count, xml):
221 self.assertEqual(
222 count, xml.count('status="%s"' % status),
223 'Expected \'status="%s"\' match count of %s: %s ' %
224 (status, count, xml))
225
227 fail_fast,
228 test_suite,
229 passed_count,
230 failure_count,
231 skipped_count,
232 suppressed_count,
233 run_disabled=False):
234 """Assert XML and text output of a test execution."""
235
236 txt, xml = RunAndReturnOutput(test_suite, fail_fast, run_disabled)
237 if failure_count > 0:
238 self.assertIn('%s FAILED TEST' % failure_count, txt)
239 if suppressed_count > 0:
240 self.assertIn('%s DISABLED TEST' % suppressed_count, txt)
241 if skipped_count > 0:
242 self.assertIn('[ SKIPPED ] %s tests' % skipped_count, txt)
243 self.assertXmlStatusCount('run',
244 passed_count + failure_count + skipped_count, xml)
245 self.assertXmlStatusCount('notrun', suppressed_count, xml)
246 self.assertXmlResultCount('completed', passed_count + failure_count, xml)
247 self.assertXmlResultCount('skipped', skipped_count, xml)
248 self.assertXmlResultCount('suppressed', suppressed_count, xml)
249
251 test_suite,
252 passed_count,
253 failure_count,
254 skipped_count,
255 suppressed_count,
256 run_disabled=False):
257 """Assert --fail_fast via flag."""
258
259 for fail_fast in ('true', '1', 't', True):
260 self.assertFailFastXmlAndTxtOutput(fail_fast, test_suite, passed_count,
261 failure_count, skipped_count,
262 suppressed_count, run_disabled)
263
265 test_suite,
266 passed_count,
267 failure_count,
268 skipped_count,
269 suppressed_count,
270 run_disabled=False):
271 """Assert --nofail_fast via flag."""
272
273 for fail_fast in ('false', '0', 'f', False):
274 self.assertFailFastXmlAndTxtOutput(fail_fast, test_suite, passed_count,
275 failure_count, skipped_count,
276 suppressed_count, run_disabled)
277
279 """Tests the behavior of fail_fast and TEST_F."""
281 test_suite='HasFixtureTest',
282 passed_count=1,
283 failure_count=1,
284 skipped_count=3,
285 suppressed_count=0)
287 test_suite='HasFixtureTest',
288 passed_count=1,
289 failure_count=4,
290 skipped_count=0,
291 suppressed_count=0)
292
294 """Tests the behavior of fail_fast and TEST."""
296 test_suite='HasSimpleTest',
297 passed_count=1,
298 failure_count=1,
299 skipped_count=3,
300 suppressed_count=0)
302 test_suite='HasSimpleTest',
303 passed_count=1,
304 failure_count=4,
305 skipped_count=0,
306 suppressed_count=0)
307
309 """Tests the behavior of fail_fast and TEST_P."""
311 test_suite='HasParametersSuite/HasParametersTest',
312 passed_count=0,
313 failure_count=1,
314 skipped_count=3,
315 suppressed_count=0)
317 test_suite='HasParametersSuite/HasParametersTest',
318 passed_count=0,
319 failure_count=4,
320 skipped_count=0,
321 suppressed_count=0)
322
324 """Tests the behavior of fail_fast and Disabled test cases."""
326 test_suite='HasDisabledTest',
327 passed_count=1,
328 failure_count=1,
329 skipped_count=2,
330 suppressed_count=1,
331 run_disabled=False)
333 test_suite='HasDisabledTest',
334 passed_count=1,
335 failure_count=3,
336 skipped_count=0,
337 suppressed_count=1,
338 run_disabled=False)
339
341 """Tests the behavior of fail_fast and Disabled test cases enabled."""
343 test_suite='HasDisabledTest',
344 passed_count=1,
345 failure_count=1,
346 skipped_count=3,
347 suppressed_count=0,
348 run_disabled=True)
350 test_suite='HasDisabledTest',
351 passed_count=1,
352 failure_count=4,
353 skipped_count=0,
354 suppressed_count=0,
355 run_disabled=True)
356
358 """Tests the behavior of fail_fast and Disabled test suites."""
360 test_suite='DISABLED_HasDisabledSuite',
361 passed_count=0,
362 failure_count=0,
363 skipped_count=0,
364 suppressed_count=5,
365 run_disabled=False)
367 test_suite='DISABLED_HasDisabledSuite',
368 passed_count=0,
369 failure_count=0,
370 skipped_count=0,
371 suppressed_count=5,
372 run_disabled=False)
373
375 """Tests the behavior of fail_fast and Disabled test suites enabled."""
377 test_suite='DISABLED_HasDisabledSuite',
378 passed_count=1,
379 failure_count=1,
380 skipped_count=3,
381 suppressed_count=0,
382 run_disabled=True)
384 test_suite='DISABLED_HasDisabledSuite',
385 passed_count=1,
386 failure_count=4,
387 skipped_count=0,
388 suppressed_count=0,
389 run_disabled=True)
390
391 if SUPPORTS_DEATH_TESTS:
392
394 """Tests the behavior of fail_fast and death tests."""
396 test_suite='HasDeathTest',
397 passed_count=1,
398 failure_count=1,
399 skipped_count=3,
400 suppressed_count=0)
402 test_suite='HasDeathTest',
403 passed_count=1,
404 failure_count=4,
405 skipped_count=0,
406 suppressed_count=0)
407
408
409if __name__ == '__main__':
def RunAndReturnOutput(test_suite=None, fail_fast=None, run_disabled=False)
def GetTestExecutablePath(executable_name, build_dir=None)
def assertFailFastXmlAndTxtOutput(self, fail_fast, test_suite, passed_count, failure_count, skipped_count, suppressed_count, run_disabled=False)
def assertNotFailFastBehavior(self, test_suite, passed_count, failure_count, skipped_count, suppressed_count, run_disabled=False)
def assertFailFastBehavior(self, test_suite, passed_count, failure_count, skipped_count, suppressed_count, run_disabled=False)