Skip to content

Commit ce22c0f

Browse files
committed
Standardize exit codes for various failures
The main reason for this is to be able to distinguish between different errors (or "errors") based on the return code. Before this change, it was impossible to use the exit code to figure out whether a test binary failed because all tests were skipped or because exactly 4 assertions have failed. This meant that using `catch_discover_tests` and telling it to check for exit code == 4 to determine skipped tests could lead to false negatives.
1 parent 18df97d commit ce22c0f

File tree

2 files changed

+21
-17
lines changed

2 files changed

+21
-17
lines changed

src/catch2/catch_session.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@
3434
namespace Catch {
3535

3636
namespace {
37-
const int MaxExitCode = 255;
37+
static constexpr int TestFailureExitCode = 42;
38+
static constexpr int UnspecifiedErrorExitCode = 1;
39+
static constexpr int AllTestsSkippedExitCode = 4;
40+
static constexpr int NoTestsRunExitCode = 2;
41+
static constexpr int UnmatchedTestSpecExitCode = 3;
42+
static constexpr int InvalidTestSpecExitCode = 5;
43+
3844

3945
IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) {
4046
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
@@ -198,8 +204,7 @@ namespace Catch {
198204
}
199205

200206
int Session::applyCommandLine( int argc, char const * const * argv ) {
201-
if( m_startupExceptions )
202-
return 1;
207+
if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; }
203208

204209
auto result = m_cli.parse( Clara::Args( argc, argv ) );
205210

@@ -215,7 +220,7 @@ namespace Catch {
215220
<< TextFlow::Column( result.errorMessage() ).indent( 2 )
216221
<< "\n\n";
217222
errStream->stream() << "Run with -? for usage\n\n" << std::flush;
218-
return MaxExitCode;
223+
return UnspecifiedErrorExitCode;
219224
}
220225

221226
if( m_configData.showHelp )
@@ -285,8 +290,7 @@ namespace Catch {
285290
}
286291

287292
int Session::runInternal() {
288-
if( m_startupExceptions )
289-
return 1;
293+
if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; }
290294

291295
if (m_configData.showHelp || m_configData.libIdentify) {
292296
return 0;
@@ -297,7 +301,7 @@ namespace Catch {
297301
<< ") must be greater than the shard index ("
298302
<< m_configData.shardIndex << ")\n"
299303
<< std::flush;
300-
return 1;
304+
return UnspecifiedErrorExitCode;
301305
}
302306

303307
CATCH_TRY {
@@ -320,7 +324,7 @@ namespace Catch {
320324
for ( auto const& spec : invalidSpecs ) {
321325
reporter->reportInvalidTestSpec( spec );
322326
}
323-
return 1;
327+
return InvalidTestSpecExitCode;
324328
}
325329

326330

@@ -334,29 +338,29 @@ namespace Catch {
334338

335339
if ( tests.hadUnmatchedTestSpecs()
336340
&& m_config->warnAboutUnmatchedTestSpecs() ) {
337-
return 3;
341+
// UnmatchedTestSpecExitCode
342+
return UnmatchedTestSpecExitCode;
338343
}
339344

340345
if ( totals.testCases.total() == 0
341346
&& !m_config->zeroTestsCountAsSuccess() ) {
342-
return 2;
347+
return NoTestsRunExitCode;
343348
}
344349

345350
if ( totals.testCases.total() > 0 &&
346351
totals.testCases.total() == totals.testCases.skipped
347352
&& !m_config->zeroTestsCountAsSuccess() ) {
348-
return 4;
353+
return AllTestsSkippedExitCode;
349354
}
350355

351-
// Note that on unices only the lower 8 bits are usually used, clamping
352-
// the return value to 255 prevents false negative when some multiple
353-
// of 256 tests has failed
354-
return (std::min) (MaxExitCode, static_cast<int>(totals.assertions.failed));
356+
if ( totals.assertions.failed ) { return TestFailureExitCode; }
357+
return 0;
358+
355359
}
356360
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
357361
catch( std::exception& ex ) {
358362
Catch::cerr() << ex.what() << '\n' << std::flush;
359-
return MaxExitCode;
363+
return UnspecifiedErrorExitCode;
360364
}
361365
#endif
362366
}

tests/TestScripts/testBazelReporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
)
5353
stdout = ret.stdout
5454
except subprocess.SubprocessError as ex:
55-
if ex.returncode == 1:
55+
if ex.returncode == 42:
5656
# The test cases are allowed to fail.
5757
test_passing = False
5858
stdout = ex.stdout

0 commit comments

Comments
 (0)