mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12283 from ethereum/soltest-graceful-error-handling
Graceful error handling in soltest/isoltest + improved soltestAssert()
This commit is contained in:
commit
e74f03056c
@ -58,13 +58,13 @@ struct InvalidAstError: virtual util::Exception {};
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define solAssert_1(CONDITION) \
|
#define solAssert_1(CONDITION) \
|
||||||
solAssert_2(CONDITION, "")
|
solAssert_2((CONDITION), "")
|
||||||
|
|
||||||
#define solAssert_2(CONDITION, DESCRIPTION) \
|
#define solAssert_2(CONDITION, DESCRIPTION) \
|
||||||
assertThrowWithDefaultDescription( \
|
assertThrowWithDefaultDescription( \
|
||||||
CONDITION, \
|
(CONDITION), \
|
||||||
::solidity::langutil::InternalCompilerError, \
|
::solidity::langutil::InternalCompilerError, \
|
||||||
DESCRIPTION, \
|
(DESCRIPTION), \
|
||||||
"Solidity assertion failed" \
|
"Solidity assertion failed" \
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,13 +77,13 @@ struct InvalidAstError: virtual util::Exception {};
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define solUnimplementedAssert_1(CONDITION) \
|
#define solUnimplementedAssert_1(CONDITION) \
|
||||||
solUnimplementedAssert_2(CONDITION, "")
|
solUnimplementedAssert_2((CONDITION), "")
|
||||||
|
|
||||||
#define solUnimplementedAssert_2(CONDITION, DESCRIPTION) \
|
#define solUnimplementedAssert_2(CONDITION, DESCRIPTION) \
|
||||||
assertThrowWithDefaultDescription( \
|
assertThrowWithDefaultDescription( \
|
||||||
CONDITION, \
|
(CONDITION), \
|
||||||
::solidity::langutil::UnimplementedFeatureError, \
|
::solidity::langutil::UnimplementedFeatureError, \
|
||||||
DESCRIPTION, \
|
(DESCRIPTION), \
|
||||||
"Unimplemented feature" \
|
"Unimplemented feature" \
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -105,9 +105,9 @@ struct InvalidAstError: virtual util::Exception {};
|
|||||||
|
|
||||||
#define astAssert_2(CONDITION, DESCRIPTION) \
|
#define astAssert_2(CONDITION, DESCRIPTION) \
|
||||||
assertThrowWithDefaultDescription( \
|
assertThrowWithDefaultDescription( \
|
||||||
CONDITION, \
|
(CONDITION), \
|
||||||
::solidity::langutil::InvalidAstError, \
|
::solidity::langutil::InvalidAstError, \
|
||||||
DESCRIPTION, \
|
(DESCRIPTION), \
|
||||||
"AST assertion failed" \
|
"AST assertion failed" \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,13 +38,13 @@ struct SMTLogicError: virtual util::Exception {};
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define smtAssert_1(CONDITION) \
|
#define smtAssert_1(CONDITION) \
|
||||||
smtAssert_2(CONDITION, "")
|
smtAssert_2((CONDITION), "")
|
||||||
|
|
||||||
#define smtAssert_2(CONDITION, DESCRIPTION) \
|
#define smtAssert_2(CONDITION, DESCRIPTION) \
|
||||||
assertThrowWithDefaultDescription( \
|
assertThrowWithDefaultDescription( \
|
||||||
CONDITION, \
|
(CONDITION), \
|
||||||
::solidity::smtutil::SMTLogicError, \
|
::solidity::smtutil::SMTLogicError, \
|
||||||
DESCRIPTION, \
|
(DESCRIPTION), \
|
||||||
"SMT assertion failed" \
|
"SMT assertion failed" \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ inline std::string stringOrDefault(std::string _string, std::string _defaultStri
|
|||||||
if (!(_condition)) \
|
if (!(_condition)) \
|
||||||
solThrow( \
|
solThrow( \
|
||||||
_exceptionType, \
|
_exceptionType, \
|
||||||
::solidity::util::assertions::stringOrDefault(_description, _defaultDescription) \
|
::solidity::util::assertions::stringOrDefault((_description), (_defaultDescription)) \
|
||||||
); \
|
); \
|
||||||
} \
|
} \
|
||||||
while (false)
|
while (false)
|
||||||
@ -72,6 +72,6 @@ inline std::string stringOrDefault(std::string _string, std::string _defaultStri
|
|||||||
/// Use it as assertThrow(1 == 1, ExceptionType, "Mathematics is wrong.");
|
/// Use it as assertThrow(1 == 1, ExceptionType, "Mathematics is wrong.");
|
||||||
/// The second parameter must be an exception class (rather than an instance).
|
/// The second parameter must be an exception class (rather than an instance).
|
||||||
#define assertThrow(_condition, _exceptionType, _description) \
|
#define assertThrow(_condition, _exceptionType, _description) \
|
||||||
assertThrowWithDefaultDescription(_condition, _exceptionType, _description, "Assertion failed")
|
assertThrowWithDefaultDescription((_condition), _exceptionType, (_description), "Assertion failed")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ struct Exception: virtual std::exception, virtual boost::exception
|
|||||||
#define solThrow(_exceptionType, _description) \
|
#define solThrow(_exceptionType, _description) \
|
||||||
::boost::throw_exception( \
|
::boost::throw_exception( \
|
||||||
_exceptionType() << \
|
_exceptionType() << \
|
||||||
::solidity::util::errinfo_comment(_description) << \
|
::solidity::util::errinfo_comment((_description)) << \
|
||||||
::boost::throw_function(ETH_FUNC) << \
|
::boost::throw_function(ETH_FUNC) << \
|
||||||
::boost::throw_file(__FILE__) << \
|
::boost::throw_file(__FILE__) << \
|
||||||
::boost::throw_line(__LINE__) \
|
::boost::throw_line(__LINE__) \
|
||||||
|
@ -63,13 +63,13 @@ struct StackTooDeepError: virtual YulException
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define yulAssert_1(CONDITION) \
|
#define yulAssert_1(CONDITION) \
|
||||||
yulAssert_2(CONDITION, "")
|
yulAssert_2((CONDITION), "")
|
||||||
|
|
||||||
#define yulAssert_2(CONDITION, DESCRIPTION) \
|
#define yulAssert_2(CONDITION, DESCRIPTION) \
|
||||||
assertThrowWithDefaultDescription( \
|
assertThrowWithDefaultDescription( \
|
||||||
CONDITION, \
|
(CONDITION), \
|
||||||
::solidity::yul::YulAssertion, \
|
::solidity::yul::YulAssertion, \
|
||||||
DESCRIPTION, \
|
(DESCRIPTION), \
|
||||||
"Yul assertion failed" \
|
"Yul assertion failed" \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -159,26 +159,33 @@ bool CommonOptions::parse(int argc, char const* const* argv)
|
|||||||
po::variables_map arguments;
|
po::variables_map arguments;
|
||||||
addOptions();
|
addOptions();
|
||||||
|
|
||||||
po::command_line_parser cmdLineParser(argc, argv);
|
try
|
||||||
cmdLineParser.options(options);
|
{
|
||||||
auto parsedOptions = cmdLineParser.run();
|
po::command_line_parser cmdLineParser(argc, argv);
|
||||||
po::store(parsedOptions, arguments);
|
cmdLineParser.options(options);
|
||||||
po::notify(arguments);
|
auto parsedOptions = cmdLineParser.run();
|
||||||
|
po::store(parsedOptions, arguments);
|
||||||
|
po::notify(arguments);
|
||||||
|
|
||||||
for (auto const& parsedOption: parsedOptions.options)
|
for (auto const& parsedOption: parsedOptions.options)
|
||||||
if (parsedOption.position_key >= 0)
|
if (parsedOption.position_key >= 0)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
parsedOption.original_tokens.empty() ||
|
parsedOption.original_tokens.empty() ||
|
||||||
(parsedOption.original_tokens.size() == 1 && parsedOption.original_tokens.front().empty())
|
(parsedOption.original_tokens.size() == 1 && parsedOption.original_tokens.front().empty())
|
||||||
)
|
)
|
||||||
continue; // ignore empty options
|
continue; // ignore empty options
|
||||||
std::stringstream errorMessage;
|
std::stringstream errorMessage;
|
||||||
errorMessage << "Unrecognized option: ";
|
errorMessage << "Unrecognized option: ";
|
||||||
for (auto const& token: parsedOption.original_tokens)
|
for (auto const& token: parsedOption.original_tokens)
|
||||||
errorMessage << token;
|
errorMessage << token;
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error(errorMessage.str()));
|
BOOST_THROW_EXCEPTION(std::runtime_error(errorMessage.str()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (po::error const& exception)
|
||||||
|
{
|
||||||
|
solThrow(ConfigException, exception.what());
|
||||||
|
}
|
||||||
|
|
||||||
if (vmPaths.empty())
|
if (vmPaths.empty())
|
||||||
{
|
{
|
||||||
|
@ -75,6 +75,9 @@ struct CommonOptions
|
|||||||
langutil::EVMVersion evmVersion() const;
|
langutil::EVMVersion evmVersion() const;
|
||||||
|
|
||||||
virtual void addOptions();
|
virtual void addOptions();
|
||||||
|
// @returns true if the program should continue, false if it should exit immediately without
|
||||||
|
// reporting an error.
|
||||||
|
// Throws ConfigException or std::runtime_error if parsing fails.
|
||||||
virtual bool parse(int argc, char const* const* argv);
|
virtual bool parse(int argc, char const* const* argv);
|
||||||
// Throws a ConfigException on error
|
// Throws a ConfigException on error
|
||||||
virtual void validate() const;
|
virtual void validate() const;
|
||||||
|
@ -204,88 +204,106 @@ int registerTests(
|
|||||||
return numTestsAdded;
|
return numTestsAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeOptions()
|
bool initializeOptions()
|
||||||
{
|
{
|
||||||
auto const& suite = boost::unit_test::framework::master_test_suite();
|
auto const& suite = boost::unit_test::framework::master_test_suite();
|
||||||
|
|
||||||
auto options = std::make_unique<solidity::test::CommonOptions>();
|
auto options = std::make_unique<solidity::test::CommonOptions>();
|
||||||
solAssert(options->parse(suite.argc, suite.argv), "Failed to parse options!");
|
bool shouldContinue = options->parse(suite.argc, suite.argv);
|
||||||
|
if (!shouldContinue)
|
||||||
|
return false;
|
||||||
options->validate();
|
options->validate();
|
||||||
|
|
||||||
solidity::test::CommonOptions::setSingleton(std::move(options));
|
solidity::test::CommonOptions::setSingleton(std::move(options));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Prototype -- why isn't this declared in the boost headers?
|
// TODO: Prototype -- why isn't this declared in the boost headers?
|
||||||
// TODO: replace this with a (global) fixture.
|
// TODO: replace this with a (global) fixture.
|
||||||
test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] );
|
test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]);
|
||||||
|
|
||||||
test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
|
test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[])
|
||||||
{
|
{
|
||||||
using namespace solidity::test;
|
using namespace solidity::test;
|
||||||
|
|
||||||
master_test_suite_t& master = framework::master_test_suite();
|
master_test_suite_t& master = framework::master_test_suite();
|
||||||
master.p_name.value = "SolidityTests";
|
master.p_name.value = "SolidityTests";
|
||||||
|
|
||||||
initializeOptions();
|
try
|
||||||
|
|
||||||
if (!solidity::test::loadVMs(solidity::test::CommonOptions::get()))
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
if (solidity::test::CommonOptions::get().disableSemanticTests)
|
|
||||||
cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl;
|
|
||||||
|
|
||||||
if (!solidity::test::CommonOptions::get().enforceGasTest)
|
|
||||||
cout << endl << "WARNING :: Gas Cost Expectations are not being enforced" << endl << endl;
|
|
||||||
|
|
||||||
Batcher batcher(CommonOptions::get().selectedBatch, CommonOptions::get().batches);
|
|
||||||
if (CommonOptions::get().batches > 1)
|
|
||||||
cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << endl;
|
|
||||||
|
|
||||||
// Batch the boost tests
|
|
||||||
BoostBatcher boostBatcher(batcher);
|
|
||||||
traverse_test_tree(master, boostBatcher, true);
|
|
||||||
|
|
||||||
// Include the interactive tests in the automatic tests as well
|
|
||||||
for (auto const& ts: g_interactiveTestsuites)
|
|
||||||
{
|
{
|
||||||
auto const& options = solidity::test::CommonOptions::get();
|
bool shouldContinue = initializeOptions();
|
||||||
|
if (!shouldContinue)
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
if (ts.smt && options.disableSMT)
|
if (!solidity::test::loadVMs(solidity::test::CommonOptions::get()))
|
||||||
continue;
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (ts.needsVM && solidity::test::CommonOptions::get().disableSemanticTests)
|
if (solidity::test::CommonOptions::get().disableSemanticTests)
|
||||||
continue;
|
cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl;
|
||||||
|
|
||||||
//TODO
|
if (!solidity::test::CommonOptions::get().enforceGasTest)
|
||||||
//solAssert(
|
cout << endl << "WARNING :: Gas Cost Expectations are not being enforced" << endl << endl;
|
||||||
registerTests(
|
|
||||||
master,
|
Batcher batcher(CommonOptions::get().selectedBatch, CommonOptions::get().batches);
|
||||||
options.testPath / ts.path,
|
if (CommonOptions::get().batches > 1)
|
||||||
ts.subpath,
|
cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << endl;
|
||||||
options.enforceViaYul,
|
|
||||||
options.enforceCompileToEwasm,
|
// Batch the boost tests
|
||||||
ts.labels,
|
BoostBatcher boostBatcher(batcher);
|
||||||
ts.testCaseCreator,
|
traverse_test_tree(master, boostBatcher, true);
|
||||||
batcher
|
|
||||||
);
|
// Include the interactive tests in the automatic tests as well
|
||||||
// > 0, std::string("no ") + ts.title + " tests found");
|
for (auto const& ts: g_interactiveTestsuites)
|
||||||
|
{
|
||||||
|
auto const& options = solidity::test::CommonOptions::get();
|
||||||
|
|
||||||
|
if (ts.smt && options.disableSMT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ts.needsVM && solidity::test::CommonOptions::get().disableSemanticTests)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
//solAssert(
|
||||||
|
registerTests(
|
||||||
|
master,
|
||||||
|
options.testPath / ts.path,
|
||||||
|
ts.subpath,
|
||||||
|
options.enforceViaYul,
|
||||||
|
options.enforceCompileToEwasm,
|
||||||
|
ts.labels,
|
||||||
|
ts.testCaseCreator,
|
||||||
|
batcher
|
||||||
|
);
|
||||||
|
// > 0, std::string("no ") + ts.title + " tests found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (solidity::test::CommonOptions::get().disableSemanticTests)
|
||||||
|
{
|
||||||
|
for (auto suite: {
|
||||||
|
"ABIDecoderTest",
|
||||||
|
"ABIEncoderTest",
|
||||||
|
"SolidityAuctionRegistrar",
|
||||||
|
"SolidityWallet",
|
||||||
|
"GasMeterTests",
|
||||||
|
"GasCostTests",
|
||||||
|
"SolidityEndToEndTest",
|
||||||
|
"SolidityOptimizer"
|
||||||
|
})
|
||||||
|
removeTestSuite(suite);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (solidity::test::ConfigException const& exception)
|
||||||
if (solidity::test::CommonOptions::get().disableSemanticTests)
|
|
||||||
{
|
{
|
||||||
for (auto suite: {
|
cerr << exception.what() << endl;
|
||||||
"ABIDecoderTest",
|
exit(EXIT_FAILURE);
|
||||||
"ABIEncoderTest",
|
}
|
||||||
"SolidityAuctionRegistrar",
|
catch (std::runtime_error const& exception)
|
||||||
"SolidityWallet",
|
{
|
||||||
"GasMeterTests",
|
cerr << exception.what() << endl;
|
||||||
"GasCostTests",
|
exit(EXIT_FAILURE);
|
||||||
"SolidityEndToEndTest",
|
|
||||||
"SolidityOptimizer"
|
|
||||||
})
|
|
||||||
removeTestSuite(suite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -15,20 +15,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libsolutil/AnsiColorized.h>
|
#include <libsolutil/AnsiColorized.h>
|
||||||
|
#include <libsolutil/Assertions.h>
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
#include <libsolutil/Exceptions.h>
|
#include <libsolutil/Exceptions.h>
|
||||||
|
|
||||||
|
#include <boost/preprocessor/cat.hpp>
|
||||||
|
#include <boost/preprocessor/facilities/empty.hpp>
|
||||||
|
#include <boost/preprocessor/facilities/overload.hpp>
|
||||||
|
|
||||||
namespace solidity::frontend::test
|
namespace solidity::frontend::test
|
||||||
{
|
{
|
||||||
|
|
||||||
#define soltestAssert(CONDITION, DESCRIPTION) \
|
struct InternalSoltestError: virtual util::Exception {};
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
if (!(CONDITION)) \
|
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error(DESCRIPTION)); \
|
|
||||||
} \
|
|
||||||
while (false)
|
|
||||||
|
|
||||||
|
#if !BOOST_PP_VARIADICS_MSVC
|
||||||
|
#define soltestAssert(...) BOOST_PP_OVERLOAD(soltestAssert_,__VA_ARGS__)(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define soltestAssert(...) BOOST_PP_CAT(BOOST_PP_OVERLOAD(soltestAssert_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY())
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define soltestAssert_1(CONDITION) \
|
||||||
|
soltestAssert_2((CONDITION), "")
|
||||||
|
|
||||||
|
#define soltestAssert_2(CONDITION, DESCRIPTION) \
|
||||||
|
assertThrowWithDefaultDescription( \
|
||||||
|
(CONDITION), \
|
||||||
|
::solidity::frontend::test::InternalSoltestError, \
|
||||||
|
(DESCRIPTION), \
|
||||||
|
"Soltest assertion failed" \
|
||||||
|
)
|
||||||
|
|
||||||
class TestParserError: virtual public util::Exception
|
class TestParserError: virtual public util::Exception
|
||||||
{
|
{
|
||||||
|
@ -75,9 +75,9 @@ void IsolTestOptions::addOptions()
|
|||||||
|
|
||||||
bool IsolTestOptions::parse(int _argc, char const* const* _argv)
|
bool IsolTestOptions::parse(int _argc, char const* const* _argv)
|
||||||
{
|
{
|
||||||
bool const res = CommonOptions::parse(_argc, _argv);
|
bool const shouldContinue = CommonOptions::parse(_argc, _argv);
|
||||||
|
|
||||||
if (showHelp || !res)
|
if (showHelp || !shouldContinue)
|
||||||
{
|
{
|
||||||
std::cout << options << std::endl;
|
std::cout << options << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -85,7 +85,7 @@ bool IsolTestOptions::parse(int _argc, char const* const* _argv)
|
|||||||
|
|
||||||
enforceGasTest = enforceGasTest || (evmVersion() == langutil::EVMVersion{} && !useABIEncoderV1);
|
enforceGasTest = enforceGasTest || (evmVersion() == langutil::EVMVersion{} && !useABIEncoderV1);
|
||||||
|
|
||||||
return res;
|
return shouldContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IsolTestOptions::validate() const
|
void IsolTestOptions::validate() const
|
||||||
|
@ -433,8 +433,9 @@ int main(int argc, char const *argv[])
|
|||||||
{
|
{
|
||||||
auto options = std::make_unique<IsolTestOptions>();
|
auto options = std::make_unique<IsolTestOptions>();
|
||||||
|
|
||||||
if (!options->parse(argc, argv))
|
bool shouldContinue = options->parse(argc, argv);
|
||||||
return -1;
|
if (!shouldContinue)
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
options->validate();
|
options->validate();
|
||||||
CommonOptions::setSingleton(std::move(options));
|
CommonOptions::setSingleton(std::move(options));
|
||||||
@ -443,7 +444,7 @@ int main(int argc, char const *argv[])
|
|||||||
auto& options = dynamic_cast<IsolTestOptions const&>(CommonOptions::get());
|
auto& options = dynamic_cast<IsolTestOptions const&>(CommonOptions::get());
|
||||||
|
|
||||||
if (!solidity::test::loadVMs(options))
|
if (!solidity::test::loadVMs(options))
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
if (options.disableSemanticTests)
|
if (options.disableSemanticTests)
|
||||||
cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl;
|
cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl;
|
||||||
@ -479,7 +480,7 @@ int main(int argc, char const *argv[])
|
|||||||
if (stats)
|
if (stats)
|
||||||
global_stats += *stats;
|
global_stats += *stats;
|
||||||
else
|
else
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << endl << "Summary: ";
|
cout << endl << "Summary: ";
|
||||||
@ -497,11 +498,22 @@ int main(int argc, char const *argv[])
|
|||||||
if (options.disableSemanticTests)
|
if (options.disableSemanticTests)
|
||||||
cout << "\nNOTE: Skipped semantics tests.\n" << endl;
|
cout << "\nNOTE: Skipped semantics tests.\n" << endl;
|
||||||
|
|
||||||
return global_stats ? 0 : 1;
|
return global_stats ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
catch (std::exception const& _exception)
|
catch (boost::program_options::error const& exception)
|
||||||
{
|
{
|
||||||
cerr << _exception.what() << endl;
|
cerr << exception.what() << endl;
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
catch (std::runtime_error const& exception)
|
||||||
|
{
|
||||||
|
cerr << exception.what() << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
cerr << "Unhandled exception caught." << endl;
|
||||||
|
cerr << boost::current_exception_diagnostic_information() << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user