soltest: Handle CLI validation errors gracefully

This commit is contained in:
Kamil Śliwak 2021-11-15 17:51:18 +01:00
parent cf6704ae06
commit 7c83559881
2 changed files with 95 additions and 75 deletions

View File

@ -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())
{ {

View File

@ -222,75 +222,88 @@ bool initializeOptions()
// 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";
bool shouldContinue = initializeOptions(); try
if (!shouldContinue)
exit(0);
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(0);
if (ts.smt && options.disableSMT) if (!solidity::test::loadVMs(solidity::test::CommonOptions::get()))
continue; exit(1);
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(1);
"ABIEncoderTest", }
"SolidityAuctionRegistrar", catch (std::runtime_error const& exception)
"SolidityWallet", {
"GasMeterTests", cerr << exception.what() << endl;
"GasCostTests", exit(1);
"SolidityEndToEndTest",
"SolidityOptimizer"
})
removeTestSuite(suite);
} }
return nullptr; return nullptr;