Dropping --opcodes support

This commit is contained in:
Paul 2023-09-11 11:55:30 +00:00
parent 16ae76cad7
commit 8e3e63d35a
6 changed files with 93 additions and 123 deletions

View File

@ -130,7 +130,6 @@ static std::string const g_strGeneratedSources = "generated-sources";
static std::string const g_strGeneratedSourcesRuntime = "generated-sources-runtime"; static std::string const g_strGeneratedSourcesRuntime = "generated-sources-runtime";
static std::string const g_strNatspecDev = "devdoc"; static std::string const g_strNatspecDev = "devdoc";
static std::string const g_strNatspecUser = "userdoc"; static std::string const g_strNatspecUser = "userdoc";
static std::string const g_strOpcodes = "opcodes";
static std::string const g_strSignatureHashes = "hashes"; static std::string const g_strSignatureHashes = "hashes";
static std::string const g_strSourceList = "sourceList"; static std::string const g_strSourceList = "sourceList";
static std::string const g_strSources = "sources"; static std::string const g_strSources = "sources";
@ -154,7 +153,6 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options)
_options.compiler.outputs.metadata || _options.compiler.outputs.metadata ||
_options.compiler.outputs.natspecUser || _options.compiler.outputs.natspecUser ||
_options.compiler.outputs.natspecDev || _options.compiler.outputs.natspecDev ||
_options.compiler.outputs.opcodes ||
_options.compiler.outputs.signatureHashes || _options.compiler.outputs.signatureHashes ||
_options.compiler.outputs.storageLayout; _options.compiler.outputs.storageLayout;
} }
@ -192,20 +190,6 @@ void CommandLineInterface::handleBinary(std::string const& _contract)
} }
} }
void CommandLineInterface::handleOpcode(std::string const& _contract)
{
solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
if (!m_options.output.dir.empty())
createFile(m_compiler->filesystemFriendlyName(_contract) + ".opcode", evmasm::disassemble(m_compiler->object(_contract).bytecode, m_options.output.evmVersion));
else
{
sout() << "Opcodes:" << std::endl;
sout() << std::uppercase << evmasm::disassemble(m_compiler->object(_contract).bytecode, m_options.output.evmVersion);
sout() << std::endl;
}
}
void CommandLineInterface::handleIR(std::string const& _contractName) void CommandLineInterface::handleIR(std::string const& _contractName)
{ {
solAssert(CompilerInputModes.count(m_options.input.mode) == 1); solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
@ -295,8 +279,6 @@ void CommandLineInterface::handleBytecode(std::string const& _contract)
{ {
solAssert(CompilerInputModes.count(m_options.input.mode) == 1); solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
if (m_options.compiler.outputs.opcodes)
handleOpcode(_contract);
if (m_options.compiler.outputs.binary || m_options.compiler.outputs.binaryRuntime) if (m_options.compiler.outputs.binary || m_options.compiler.outputs.binaryRuntime)
handleBinary(_contract); handleBinary(_contract);
} }
@ -752,13 +734,11 @@ void CommandLineInterface::compile()
m_options.compiler.estimateGas || m_options.compiler.estimateGas ||
m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asm_ ||
m_options.compiler.outputs.asmJson || m_options.compiler.outputs.asmJson ||
m_options.compiler.outputs.opcodes ||
m_options.compiler.outputs.binary || m_options.compiler.outputs.binary ||
m_options.compiler.outputs.binaryRuntime || m_options.compiler.outputs.binaryRuntime ||
(m_options.compiler.combinedJsonRequests && ( (m_options.compiler.combinedJsonRequests && (
m_options.compiler.combinedJsonRequests->binary || m_options.compiler.combinedJsonRequests->binary ||
m_options.compiler.combinedJsonRequests->binaryRuntime || m_options.compiler.combinedJsonRequests->binaryRuntime ||
m_options.compiler.combinedJsonRequests->opcodes ||
m_options.compiler.combinedJsonRequests->asm_ || m_options.compiler.combinedJsonRequests->asm_ ||
m_options.compiler.combinedJsonRequests->generatedSources || m_options.compiler.combinedJsonRequests->generatedSources ||
m_options.compiler.combinedJsonRequests->generatedSourcesRuntime || m_options.compiler.combinedJsonRequests->generatedSourcesRuntime ||
@ -858,8 +838,6 @@ void CommandLineInterface::handleCombinedJSON()
contractData[g_strBinary] = m_compiler->object(contractName).toHex(); contractData[g_strBinary] = m_compiler->object(contractName).toHex();
if (m_options.compiler.combinedJsonRequests->binaryRuntime && compilationSuccess) if (m_options.compiler.combinedJsonRequests->binaryRuntime && compilationSuccess)
contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex(); contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex();
if (m_options.compiler.combinedJsonRequests->opcodes && compilationSuccess)
contractData[g_strOpcodes] = evmasm::disassemble(m_compiler->object(contractName).bytecode, m_options.output.evmVersion);
if (m_options.compiler.combinedJsonRequests->asm_ && compilationSuccess) if (m_options.compiler.combinedJsonRequests->asm_ && compilationSuccess)
contractData[g_strAsm] = m_compiler->assemblyJSON(contractName); contractData[g_strAsm] = m_compiler->assemblyJSON(contractName);
if (m_options.compiler.combinedJsonRequests->storageLayout && compilationSuccess) if (m_options.compiler.combinedJsonRequests->storageLayout && compilationSuccess)

View File

@ -99,7 +99,6 @@ private:
void handleCombinedJSON(); void handleCombinedJSON();
void handleAst(); void handleAst();
void handleBinary(std::string const& _contract); void handleBinary(std::string const& _contract);
void handleOpcode(std::string const& _contract);
void handleIR(std::string const& _contract); void handleIR(std::string const& _contract);
void handleIRAst(std::string const& _contract); void handleIRAst(std::string const& _contract);
void handleIROptimized(std::string const& _contract); void handleIROptimized(std::string const& _contract);

View File

@ -723,7 +723,6 @@ General Information)").c_str(),
(CompilerOutputs::componentName(&CompilerOutputs::astCompactJson).c_str(), "AST of all source files in a compact JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::astCompactJson).c_str(), "AST of all source files in a compact JSON format.")
(CompilerOutputs::componentName(&CompilerOutputs::asm_).c_str(), "EVM assembly of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::asm_).c_str(), "EVM assembly of the contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::asmJson).c_str(), "EVM assembly of the contracts in JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::asmJson).c_str(), "EVM assembly of the contracts in JSON format.")
(CompilerOutputs::componentName(&CompilerOutputs::opcodes).c_str(), "Opcodes of the contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::binary).c_str(), "Binary of the contracts in hex.") (CompilerOutputs::componentName(&CompilerOutputs::binary).c_str(), "Binary of the contracts in hex.")
(CompilerOutputs::componentName(&CompilerOutputs::binaryRuntime).c_str(), "Binary of the runtime part of the contracts in hex.") (CompilerOutputs::componentName(&CompilerOutputs::binaryRuntime).c_str(), "Binary of the runtime part of the contracts in hex.")
(CompilerOutputs::componentName(&CompilerOutputs::abi).c_str(), "ABI specification of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::abi).c_str(), "ABI specification of the contracts.")

View File

@ -72,7 +72,6 @@ struct CompilerOutputs
{"ast-compact-json", &CompilerOutputs::astCompactJson}, {"ast-compact-json", &CompilerOutputs::astCompactJson},
{"asm", &CompilerOutputs::asm_}, {"asm", &CompilerOutputs::asm_},
{"asm-json", &CompilerOutputs::asmJson}, {"asm-json", &CompilerOutputs::asmJson},
{"opcodes", &CompilerOutputs::opcodes},
{"bin", &CompilerOutputs::binary}, {"bin", &CompilerOutputs::binary},
{"bin-runtime", &CompilerOutputs::binaryRuntime}, {"bin-runtime", &CompilerOutputs::binaryRuntime},
{"abi", &CompilerOutputs::abi}, {"abi", &CompilerOutputs::abi},
@ -92,7 +91,6 @@ struct CompilerOutputs
bool astCompactJson = false; bool astCompactJson = false;
bool asm_ = false; bool asm_ = false;
bool asmJson = false; bool asmJson = false;
bool opcodes = false;
bool binary = false; bool binary = false;
bool binaryRuntime = false; bool binaryRuntime = false;
bool abi = false; bool abi = false;
@ -121,7 +119,6 @@ struct CombinedJsonRequests
{"metadata", &CombinedJsonRequests::metadata}, {"metadata", &CombinedJsonRequests::metadata},
{"bin", &CombinedJsonRequests::binary}, {"bin", &CombinedJsonRequests::binary},
{"bin-runtime", &CombinedJsonRequests::binaryRuntime}, {"bin-runtime", &CombinedJsonRequests::binaryRuntime},
{"opcodes", &CombinedJsonRequests::opcodes},
{"asm", &CombinedJsonRequests::asm_}, {"asm", &CombinedJsonRequests::asm_},
{"storage-layout", &CombinedJsonRequests::storageLayout}, {"storage-layout", &CombinedJsonRequests::storageLayout},
{"generated-sources", &CombinedJsonRequests::generatedSources}, {"generated-sources", &CombinedJsonRequests::generatedSources},
@ -142,7 +139,6 @@ struct CombinedJsonRequests
bool metadata = false; bool metadata = false;
bool binary = false; bool binary = false;
bool binaryRuntime = false; bool binaryRuntime = false;
bool opcodes = false;
bool asm_ = false; bool asm_ = false;
bool storageLayout = false; bool storageLayout = false;
bool generatedSources = false; bool generatedSources = false;

View File

@ -42,20 +42,19 @@
#include <string> #include <string>
#include <vector> #include <vector>
using namespace std;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::test; using namespace solidity::test;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
using PathSet = set<boost::filesystem::path>; using PathSet = std::set<boost::filesystem::path>;
#define TEST_CASE_NAME (boost::unit_test::framework::current_test_case().p_name) #define TEST_CASE_NAME (boost::unit_test::framework::current_test_case().p_name)
namespace namespace
{ {
ostream& operator<<(ostream& _out, vector<ImportRemapper::Remapping> const& _remappings) std::ostream& operator<<(std::ostream& _out, std::vector<ImportRemapper::Remapping> const& _remappings)
{ {
static auto remappingToString = [](auto const& _remapping) static auto remappingToString = [](auto const& _remapping)
{ {
@ -66,17 +65,17 @@ ostream& operator<<(ostream& _out, vector<ImportRemapper::Remapping> const& _rem
return _out; return _out;
} }
ostream& operator<<(ostream& _out, map<string, string> const& _map) std::ostream& operator<<(std::ostream& _out, std::map<std::string, std::string> const& _map)
{ {
_out << "{" << endl; _out << "{" << std::endl;
for (auto const& [key, value]: _map) for (auto const& [key, value]: _map)
_out << "" << key << ": " << value << "," << endl; _out << "" << key << ": " << value << "," << std::endl;
_out << "}"; _out << "}";
return _out; return _out;
} }
ostream& operator<<(ostream& _out, PathSet const& _paths) std::ostream& operator<<(std::ostream& _out, PathSet const& _paths)
{ {
static auto pathString = [](auto const& _path) { return _path.string(); }; static auto pathString = [](auto const& _path) { return _path.string(); };
@ -93,15 +92,15 @@ namespace boost::test_tools::tt_detail
// The recommended solution is to overload print_log_value<> struct and make it use our operator. // The recommended solution is to overload print_log_value<> struct and make it use our operator.
template<> template<>
struct print_log_value<vector<ImportRemapper::Remapping>> struct print_log_value<std::vector<ImportRemapper::Remapping>>
{ {
void operator()(std::ostream& _out, vector<ImportRemapper::Remapping> const& _value) { ::operator<<(_out, _value); } void operator()(std::ostream& _out, std::vector<ImportRemapper::Remapping> const& _value) { ::operator<<(_out, _value); }
}; };
template<> template<>
struct print_log_value<map<string, string>> struct print_log_value<std::map<std::string, std::string>>
{ {
void operator()(std::ostream& _out, map<string, string> const& _value) { ::operator<<(_out, _value); } void operator()(std::ostream& _out, std::map<std::string, std::string> const& _value) { ::operator<<(_out, _value); }
}; };
template<> template<>
@ -149,7 +148,7 @@ BOOST_AUTO_TEST_CASE(version)
BOOST_AUTO_TEST_CASE(multiple_input_modes) BOOST_AUTO_TEST_CASE(multiple_input_modes)
{ {
array<string, 9> inputModeOptions = { std::array<std::string, 9> inputModeOptions = {
"--help", "--help",
"--license", "--license",
"--version", "--version",
@ -160,13 +159,13 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes)
"--yul", "--yul",
"--import-ast", "--import-ast",
}; };
string expectedMessage = std::string expectedMessage =
"The following options are mutually exclusive: " "The following options are mutually exclusive: "
"--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --lsp. " "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --lsp. "
"Select at most one."; "Select at most one.";
for (string const& mode1: inputModeOptions) for (std::string const& mode1: inputModeOptions)
for (string const& mode2: inputModeOptions) for (std::string const& mode2: inputModeOptions)
if (mode1 != mode2) if (mode1 != mode2)
BOOST_CHECK_EXCEPTION( BOOST_CHECK_EXCEPTION(
parseCommandLineAndReadInputFiles({"solc", mode1, mode2}), parseCommandLineAndReadInputFiles({"solc", mode1, mode2}),
@ -188,11 +187,11 @@ BOOST_AUTO_TEST_CASE(cli_input)
soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", ""); soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", "");
soltestAssert(expectedDir2.is_absolute() || expectedDir2.root_path() == "/", ""); soltestAssert(expectedDir2.is_absolute() || expectedDir2.root_path() == "/", "");
vector<ImportRemapper::Remapping> expectedRemappings = { std::vector<ImportRemapper::Remapping> expectedRemappings = {
{"", "a", "b/c/d"}, {"", "a", "b/c/d"},
{"a", "b", "c/d/e/"}, {"a", "b", "c/d/e/"},
}; };
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"<stdin>", ""}, {"<stdin>", ""},
{(expectedDir1 / "input1.sol").generic_string(), ""}, {(expectedDir1 / "input1.sol").generic_string(), ""},
{(expectedDir2 / "input2.sol").generic_string(), ""}, {(expectedDir2 / "input2.sol").generic_string(), ""},
@ -233,7 +232,7 @@ BOOST_AUTO_TEST_CASE(cli_ignore_missing_some_files_exist)
soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", ""); soltestAssert(expectedDir1.is_absolute() || expectedDir1.root_path() == "/", "");
// NOTE: Allowed paths should not be added for skipped files. // NOTE: Allowed paths should not be added for skipped files.
map<string, string> expectedSources = {{(expectedDir1 / "input1.sol").generic_string(), ""}}; std::map<std::string, std::string> expectedSources = {{(expectedDir1 / "input1.sol").generic_string(), ""}};
PathSet expectedAllowedPaths = {boost::filesystem::canonical(tempDir1)}; PathSet expectedAllowedPaths = {boost::filesystem::canonical(tempDir1)};
OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles({ OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles({
@ -254,7 +253,7 @@ BOOST_AUTO_TEST_CASE(cli_ignore_missing_no_files_exist)
{ {
TemporaryDirectory tempDir(TEST_CASE_NAME); TemporaryDirectory tempDir(TEST_CASE_NAME);
string expectedMessage = std::string expectedMessage =
"\"" + (tempDir.path() / "input1.sol").string() + "\" is not found. Skipping.\n" "\"" + (tempDir.path() / "input1.sol").string() + "\" is not found. Skipping.\n"
"\"" + (tempDir.path() / "input2.sol").string() + "\" is not found. Skipping.\n" "\"" + (tempDir.path() / "input2.sol").string() + "\" is not found. Skipping.\n"
"All specified input files either do not exist or are not regular files.\n"; "All specified input files either do not exist or are not regular files.\n";
@ -273,7 +272,7 @@ BOOST_AUTO_TEST_CASE(cli_not_a_file)
{ {
TemporaryDirectory tempDir(TEST_CASE_NAME); TemporaryDirectory tempDir(TEST_CASE_NAME);
string expectedMessage = "\"" + tempDir.path().string() + "\" is not a valid file."; std::string expectedMessage = "\"" + tempDir.path().string() + "\" is not a valid file.";
BOOST_CHECK_EXCEPTION( BOOST_CHECK_EXCEPTION(
parseCommandLineAndReadInputFiles({"solc", tempDir.path().string()}), parseCommandLineAndReadInputFiles({"solc", tempDir.path().string()}),
@ -330,7 +329,7 @@ BOOST_AUTO_TEST_CASE(standard_json_one_input_file)
TemporaryDirectory tempDir(TEST_CASE_NAME); TemporaryDirectory tempDir(TEST_CASE_NAME);
createFilesWithParentDirs({tempDir.path() / "input.json"}); createFilesWithParentDirs({tempDir.path() / "input.json"});
vector<string> commandLine = {"solc", "--standard-json", (tempDir.path() / "input.json").string()}; std::vector<std::string> commandLine = {"solc", "--standard-json", (tempDir.path() / "input.json").string()};
OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles(commandLine); OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles(commandLine);
BOOST_TEST(result.success); BOOST_TEST(result.success);
BOOST_TEST(result.stderrContent == ""); BOOST_TEST(result.stderrContent == "");
@ -342,7 +341,7 @@ BOOST_AUTO_TEST_CASE(standard_json_one_input_file)
BOOST_AUTO_TEST_CASE(standard_json_two_input_files) BOOST_AUTO_TEST_CASE(standard_json_two_input_files)
{ {
string expectedMessage = std::string expectedMessage =
"Too many input files for --standard-json.\n" "Too many input files for --standard-json.\n"
"Please either specify a single file name or provide its content on standard input."; "Please either specify a single file name or provide its content on standard input.";
@ -355,7 +354,7 @@ BOOST_AUTO_TEST_CASE(standard_json_two_input_files)
BOOST_AUTO_TEST_CASE(standard_json_one_input_file_and_stdin) BOOST_AUTO_TEST_CASE(standard_json_one_input_file_and_stdin)
{ {
string expectedMessage = std::string expectedMessage =
"Too many input files for --standard-json.\n" "Too many input files for --standard-json.\n"
"Please either specify a single file name or provide its content on standard input."; "Please either specify a single file name or provide its content on standard input.";
@ -371,7 +370,7 @@ BOOST_AUTO_TEST_CASE(standard_json_ignore_missing)
TemporaryDirectory tempDir(TEST_CASE_NAME); TemporaryDirectory tempDir(TEST_CASE_NAME);
// This option is pretty much useless Standard JSON mode. // This option is pretty much useless Standard JSON mode.
string expectedMessage = std::string expectedMessage =
"All specified input files either do not exist or are not regular files."; "All specified input files either do not exist or are not regular files.";
BOOST_CHECK_EXCEPTION( BOOST_CHECK_EXCEPTION(
@ -388,7 +387,7 @@ BOOST_AUTO_TEST_CASE(standard_json_ignore_missing)
BOOST_AUTO_TEST_CASE(standard_json_remapping) BOOST_AUTO_TEST_CASE(standard_json_remapping)
{ {
string expectedMessage = std::string expectedMessage =
"Import remappings are not accepted on the command line in Standard JSON mode.\n" "Import remappings are not accepted on the command line in Standard JSON mode.\n"
"Please put them under 'settings.remappings' in the JSON input."; "Please put them under 'settings.remappings' in the JSON input.";
@ -415,7 +414,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_no_base_path)
boost::filesystem::path expectedOtherDir = "/" / otherDirNoSymlinks.relative_path(); boost::filesystem::path expectedOtherDir = "/" / otherDirNoSymlinks.relative_path();
soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", ""); soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", "");
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"contract1.sol", // Relative path "contract1.sol", // Relative path
"c/d/contract2.sol", // Relative path with subdirectories "c/d/contract2.sol", // Relative path with subdirectories
@ -432,7 +431,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_no_base_path)
}; };
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"contract1.sol", ""}, {"contract1.sol", ""},
{"c/d/contract2.sol", ""}, {"c/d/contract2.sol", ""},
{"contract3.sol", ""}, {"contract3.sol", ""},
@ -475,7 +474,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_same_as_work_dir)
soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", ""); soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", "");
soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", ""); soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", "");
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=" + currentDirNoSymlinks.string(), "--base-path=" + currentDirNoSymlinks.string(),
"contract1.sol", // Relative path "contract1.sol", // Relative path
@ -494,7 +493,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_same_as_work_dir)
expectedOptions.input.basePath = currentDirNoSymlinks; expectedOptions.input.basePath = currentDirNoSymlinks;
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"contract1.sol", ""}, {"contract1.sol", ""},
{"c/d/contract2.sol", ""}, {"c/d/contract2.sol", ""},
{"contract3.sol", ""}, {"contract3.sol", ""},
@ -544,7 +543,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_different_from_wor
soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", ""); soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", "");
soltestAssert(expectedBaseDir.is_absolute() || expectedBaseDir.root_path() == "/", ""); soltestAssert(expectedBaseDir.is_absolute() || expectedBaseDir.root_path() == "/", "");
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=" + baseDirNoSymlinks.string(), "--base-path=" + baseDirNoSymlinks.string(),
"contract1.sol", // Relative path "contract1.sol", // Relative path
@ -565,7 +564,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_different_from_wor
expectedOptions.input.basePath = baseDirNoSymlinks; expectedOptions.input.basePath = baseDirNoSymlinks;
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{expectedWorkDir.generic_string() + "/contract1.sol", ""}, {expectedWorkDir.generic_string() + "/contract1.sol", ""},
{expectedWorkDir.generic_string() + "/c/d/contract2.sol", ""}, {expectedWorkDir.generic_string() + "/c/d/contract2.sol", ""},
{expectedCurrentDir.generic_string() + "/contract3.sol", ""}, {expectedCurrentDir.generic_string() + "/contract3.sol", ""},
@ -610,7 +609,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_relative_base_path)
soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", ""); soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", "");
soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", ""); soltestAssert(expectedOtherDir.is_absolute() || expectedOtherDir.root_path() == "/", "");
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=base", "--base-path=base",
"contract1.sol", // Relative path outside of base path "contract1.sol", // Relative path outside of base path
@ -633,7 +632,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_relative_base_path)
expectedOptions.input.basePath = "base"; expectedOptions.input.basePath = "base";
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{expectedWorkDir.generic_string() + "/contract1.sol", ""}, {expectedWorkDir.generic_string() + "/contract1.sol", ""},
{"contract2.sol", ""}, {"contract2.sol", ""},
{expectedWorkDir.generic_string() + "/contract3.sol", ""}, {expectedWorkDir.generic_string() + "/contract3.sol", ""},
@ -667,7 +666,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_normalization_and_weird_name
TemporaryWorkingDirectory tempWorkDir(tempDir.path() / "x/y/z"); TemporaryWorkingDirectory tempWorkDir(tempDir.path() / "x/y/z");
soltestAssert(tempDir.path().is_absolute(), ""); soltestAssert(tempDir.path().is_absolute(), "");
string uncPath = "//" + tempDir.path().relative_path().generic_string(); std::string uncPath = "//" + tempDir.path().relative_path().generic_string();
soltestAssert(FileReader::isUNCPath(uncPath), ""); soltestAssert(FileReader::isUNCPath(uncPath), "");
boost::filesystem::path tempDirNoSymlinks = boost::filesystem::canonical(tempDir); boost::filesystem::path tempDirNoSymlinks = boost::filesystem::canonical(tempDir);
@ -675,7 +674,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_normalization_and_weird_name
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path();
soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", ""); soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", "");
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
#if !defined(_WIN32) #if !defined(_WIN32)
@ -763,7 +762,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_normalization_and_weird_name
}; };
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
#if !defined(_WIN32) #if !defined(_WIN32)
{"file:/c/d/contract1.sol", ""}, {"file:/c/d/contract1.sol", ""},
{"file:/c/d/contract2.sol", ""}, {"file:/c/d/contract2.sol", ""},
@ -843,7 +842,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_symlinks)
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path();
soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", ""); soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", "");
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=../r/sym/z/", "--base-path=../r/sym/z/",
@ -863,7 +862,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_symlinks)
expectedOptions.input.basePath = "../r/sym/z/"; expectedOptions.input.basePath = "../r/sym/z/";
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"contract.sol", ""}, {"contract.sol", ""},
{(expectedWorkDir.parent_path() / "x/y/z/contract.sol").generic_string(), ""}, {(expectedWorkDir.parent_path() / "x/y/z/contract.sol").generic_string(), ""},
{"contract_symlink.sol", ""}, {"contract_symlink.sol", ""},
@ -893,14 +892,14 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_base_path_and_stdin)
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path();
vector<string> commandLine = {"solc", "--base-path=base", "-"}; std::vector<std::string> commandLine = {"solc", "--base-path=base", "-"};
CommandLineOptions expectedOptions; CommandLineOptions expectedOptions;
expectedOptions.input.addStdin = true; expectedOptions.input.addStdin = true;
expectedOptions.input.basePath = "base"; expectedOptions.input.basePath = "base";
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"<stdin>", ""}, {"<stdin>", ""},
}; };
FileReader::FileSystemPathSet expectedAllowedDirectories = {}; FileReader::FileSystemPathSet expectedAllowedDirectories = {};
@ -922,7 +921,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME); TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME);
TemporaryWorkingDirectory tempWorkDir(tempDir); TemporaryWorkingDirectory tempWorkDir(tempDir);
string const mainContractSource = withPreamble( std::string const mainContractSource = withPreamble(
"import \"contract.sol\";\n" "import \"contract.sol\";\n"
"import \"contract_via_callback.sol\";\n" "import \"contract_via_callback.sol\";\n"
"import \"include.sol\";\n" "import \"include.sol\";\n"
@ -933,7 +932,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
"import \"lib_via_callback.sol\";\n" "import \"lib_via_callback.sol\";\n"
); );
string const onlyPreamble = withPreamble(""); std::string const onlyPreamble = withPreamble("");
createFilesWithParentDirs( createFilesWithParentDirs(
{ {
tempDir.path() / "base/contract.sol", tempDir.path() / "base/contract.sol",
@ -952,7 +951,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
boost::filesystem::path canonicalWorkDir = boost::filesystem::canonical(tempDir); boost::filesystem::path canonicalWorkDir = boost::filesystem::canonical(tempDir);
boost::filesystem::path expectedWorkDir = "/" / canonicalWorkDir.relative_path(); boost::filesystem::path expectedWorkDir = "/" / canonicalWorkDir.relative_path();
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--no-color", "--no-color",
"--base-path=base/", "--base-path=base/",
@ -983,7 +982,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
expectedOptions.formatting.coloredOutput = false; expectedOptions.formatting.coloredOutput = false;
expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.initialize = true;
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"main.sol", mainContractSource}, {"main.sol", mainContractSource},
{"contract.sol", onlyPreamble}, {"contract.sol", onlyPreamble},
{"contract_via_callback.sol", onlyPreamble}, {"contract_via_callback.sol", onlyPreamble},
@ -995,7 +994,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
{"lib_via_callback.sol", onlyPreamble}, {"lib_via_callback.sol", onlyPreamble},
}; };
vector<boost::filesystem::path> expectedIncludePaths = { std::vector<boost::filesystem::path> expectedIncludePaths = {
expectedWorkDir / "include/", expectedWorkDir / "include/",
expectedWorkDir / "lib/nested", expectedWorkDir / "lib/nested",
expectedWorkDir / "lib/", expectedWorkDir / "lib/",
@ -1008,11 +1007,11 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
canonicalWorkDir / "lib", canonicalWorkDir / "lib",
}; };
string const expectedStdoutContent = "Compiler run successful. No contracts to compile.\n"; std::string const expectedStdoutContent = "Compiler run successful. No contracts to compile.\n";
OptionsReaderAndMessages result = runCLI(commandLine, ""); OptionsReaderAndMessages result = runCLI(commandLine, "");
BOOST_TEST(result.stderrContent == ""); BOOST_TEST(result.stderrContent == "");
if (SemVerVersion{string(VersionString)}.isPrerelease()) if (SemVerVersion{std::string(VersionString)}.isPrerelease())
BOOST_TEST(result.stdoutContent == ""); BOOST_TEST(result.stdoutContent == "");
else else
BOOST_TEST(result.stdoutContent == expectedStdoutContent); BOOST_TEST(result.stdoutContent == expectedStdoutContent);
@ -1026,16 +1025,16 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
BOOST_AUTO_TEST_CASE(cli_no_contracts_to_compile) BOOST_AUTO_TEST_CASE(cli_no_contracts_to_compile)
{ {
string const contractSource = R"( std::string const contractSource = R"(
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0; pragma solidity >=0.0;
enum Status { test } enum Status { test }
)"; )";
string const expectedStdoutContent = "Compiler run successful. No contracts to compile.\n"; std::string const expectedStdoutContent = "Compiler run successful. No contracts to compile.\n";
OptionsReaderAndMessages result = runCLI({"solc", "-"}, contractSource); OptionsReaderAndMessages result = runCLI({"solc", "-"}, contractSource);
if (SemVerVersion{string(VersionString)}.isPrerelease()) if (SemVerVersion{std::string(VersionString)}.isPrerelease())
BOOST_TEST(result.stdoutContent == ""); BOOST_TEST(result.stdoutContent == "");
else else
BOOST_TEST(result.stdoutContent == expectedStdoutContent); BOOST_TEST(result.stdoutContent == expectedStdoutContent);
@ -1044,17 +1043,17 @@ BOOST_AUTO_TEST_CASE(cli_no_contracts_to_compile)
BOOST_AUTO_TEST_CASE(cli_no_output) BOOST_AUTO_TEST_CASE(cli_no_output)
{ {
string const contractSource = R"( std::string const contractSource = R"(
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0; pragma solidity >=0.0;
abstract contract A { abstract contract A {
function B() public virtual returns(uint); function B() public virtual returns(uint);
})"; })";
string const expectedStdoutContent = "Compiler run successful. No output generated.\n"; std::string const expectedStdoutContent = "Compiler run successful. No output generated.\n";
OptionsReaderAndMessages result = runCLI({"solc", "-"}, contractSource); OptionsReaderAndMessages result = runCLI({"solc", "-"}, contractSource);
if (SemVerVersion{string(VersionString)}.isPrerelease()) if (SemVerVersion{std::string(VersionString)}.isPrerelease())
BOOST_TEST(result.stdoutContent == ""); BOOST_TEST(result.stdoutContent == "");
else else
BOOST_TEST(result.stdoutContent == expectedStdoutContent); BOOST_TEST(result.stdoutContent == expectedStdoutContent);
@ -1066,14 +1065,14 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths)
TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME); TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME);
TemporaryWorkingDirectory tempWorkDir(tempDir); TemporaryWorkingDirectory tempWorkDir(tempDir);
string const mainContractSource = withPreamble( std::string const mainContractSource = withPreamble(
"import 'contract_via_callback.sol';\n" "import 'contract_via_callback.sol';\n"
"import 'include_via_callback.sol';\n" "import 'include_via_callback.sol';\n"
"import 'nested_via_callback.sol';\n" "import 'nested_via_callback.sol';\n"
"import 'lib_via_callback.sol';\n" "import 'lib_via_callback.sol';\n"
); );
string const standardJsonInput = R"( std::string const standardJsonInput = R"(
{ {
"language": "Solidity", "language": "Solidity",
"sources": { "sources": {
@ -1082,7 +1081,7 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths)
} }
)"; )";
string const onlyPreamble = withPreamble(""); std::string const onlyPreamble = withPreamble("");
createFilesWithParentDirs( createFilesWithParentDirs(
{ {
tempDir.path() / "base/contract_via_callback.sol", tempDir.path() / "base/contract_via_callback.sol",
@ -1095,7 +1094,7 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths)
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path();
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=base/", "--base-path=base/",
"--include-path=include/", "--include-path=include/",
@ -1119,14 +1118,14 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths)
// NOTE: Source code from Standard JSON does not end up in FileReader. This is not a problem // NOTE: Source code from Standard JSON does not end up in FileReader. This is not a problem
// because FileReader is only used once to initialize the compiler stack and after that // because FileReader is only used once to initialize the compiler stack and after that
// its sources are irrelevant (even though the callback still stores everything it loads). // its sources are irrelevant (even though the callback still stores everything it loads).
map<string, string> expectedSources = { std::map<std::string, std::string> expectedSources = {
{"contract_via_callback.sol", onlyPreamble}, {"contract_via_callback.sol", onlyPreamble},
{"include_via_callback.sol", onlyPreamble}, {"include_via_callback.sol", onlyPreamble},
{"nested_via_callback.sol", onlyPreamble}, {"nested_via_callback.sol", onlyPreamble},
{"lib_via_callback.sol", onlyPreamble}, {"lib_via_callback.sol", onlyPreamble},
}; };
vector<boost::filesystem::path> expectedIncludePaths = { std::vector<boost::filesystem::path> expectedIncludePaths = {
expectedWorkDir / "include/", expectedWorkDir / "include/",
expectedWorkDir / "lib/nested", expectedWorkDir / "lib/nested",
expectedWorkDir / "lib/", expectedWorkDir / "lib/",
@ -1137,15 +1136,15 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths)
OptionsReaderAndMessages result = runCLI(commandLine, standardJsonInput); OptionsReaderAndMessages result = runCLI(commandLine, standardJsonInput);
Json::Value parsedStdout; Json::Value parsedStdout;
string jsonParsingErrors; std::string jsonParsingErrors;
BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors)); BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors));
BOOST_TEST(jsonParsingErrors == ""); BOOST_TEST(jsonParsingErrors == "");
for (Json::Value const& errorDict: parsedStdout["errors"]) for (Json::Value const& errorDict: parsedStdout["errors"])
// The error list might contain pre-release compiler warning // The error list might contain pre-release compiler warning
BOOST_TEST(errorDict["severity"] != "error"); BOOST_TEST(errorDict["severity"] != "error");
BOOST_TEST( BOOST_TEST(
(parsedStdout["sources"].getMemberNames() | ranges::to<set>) == (parsedStdout["sources"].getMemberNames() | ranges::to<std::set>) ==
(expectedSources | ranges::views::keys | ranges::to<set>) + set<string>{"main.sol"} (expectedSources | ranges::views::keys | ranges::to<std::set>) + std::set<std::string>{"main.sol"}
); );
BOOST_REQUIRE(result.success); BOOST_REQUIRE(result.success);
@ -1162,7 +1161,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_empty_path)
TemporaryWorkingDirectory tempWorkDir(tempDir); TemporaryWorkingDirectory tempWorkDir(tempDir);
createFilesWithParentDirs({tempDir.path() / "base/main.sol"}); createFilesWithParentDirs({tempDir.path() / "base/main.sol"});
string expectedMessage = "Empty values are not allowed in --include-path."; std::string expectedMessage = "Empty values are not allowed in --include-path.";
BOOST_CHECK_EXCEPTION( BOOST_CHECK_EXCEPTION(
parseCommandLineAndReadInputFiles({ parseCommandLineAndReadInputFiles({
@ -1183,7 +1182,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_without_base_path)
TemporaryWorkingDirectory tempWorkDir(tempDir); TemporaryWorkingDirectory tempWorkDir(tempDir);
createFilesWithParentDirs({tempDir.path() / "contract.sol"}); createFilesWithParentDirs({tempDir.path() / "contract.sol"});
string expectedMessage = "--include-path option requires a non-empty base path."; std::string expectedMessage = "--include-path option requires a non-empty base path.";
BOOST_CHECK_EXCEPTION( BOOST_CHECK_EXCEPTION(
parseCommandLineAndReadInputFiles({"solc", "--include-path", "include/", "contract.sol"}), parseCommandLineAndReadInputFiles({"solc", "--include-path", "include/", "contract.sol"}),
@ -1205,7 +1204,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_should_detect_source_unit_name_collisions
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path();
string expectedMessage = std::string expectedMessage =
"Source unit name collision detected. " "Source unit name collision detected. "
"The specified values of base path and/or include paths would result in multiple " "The specified values of base path and/or include paths would result in multiple "
"input files being assigned the same source unit name:\n" "input files being assigned the same source unit name:\n"
@ -1253,7 +1252,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_should_detect_source_unit_name_collisions
{ {
// No conflict if files with the same name exist but only one is given to the compiler. // No conflict if files with the same name exist but only one is given to the compiler.
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=dir3/", "--base-path=dir3/",
"--include-path=dir1/", "--include-path=dir1/",
@ -1268,7 +1267,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_should_detect_source_unit_name_collisions
{ {
// The same file specified multiple times is not a conflict. // The same file specified multiple times is not a conflict.
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=dir3/", "--base-path=dir3/",
"--include-path=dir1/", "--include-path=dir1/",
@ -1292,7 +1291,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_should_allow_duplicate_paths)
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path();
boost::filesystem::path expectedTempDir = "/" / tempDir.path().relative_path(); boost::filesystem::path expectedTempDir = "/" / tempDir.path().relative_path();
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--base-path=dir1/", "--base-path=dir1/",
"--include-path", "dir1", "--include-path", "dir1",
@ -1308,7 +1307,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_should_allow_duplicate_paths)
}; };
// Duplicates do not affect the result but are not removed from the include path list. // Duplicates do not affect the result but are not removed from the include path list.
vector<boost::filesystem::path> expectedIncludePaths = { std::vector<boost::filesystem::path> expectedIncludePaths = {
expectedWorkDir / "dir1", expectedWorkDir / "dir1",
expectedWorkDir / "dir1", expectedWorkDir / "dir1",
expectedWorkDir / "dir1/", expectedWorkDir / "dir1/",
@ -1335,13 +1334,13 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import)
TemporaryWorkingDirectory tempWorkDir(tempDir); TemporaryWorkingDirectory tempWorkDir(tempDir);
// Ambiguous: both base/contract.sol and include/contract.sol match the import. // Ambiguous: both base/contract.sol and include/contract.sol match the import.
string const mainContractSource = withPreamble("import \"contract.sol\";"); std::string const mainContractSource = withPreamble("import \"contract.sol\";");
createFilesWithParentDirs({"base/contract.sol", "include/contract.sol"}, withPreamble("")); createFilesWithParentDirs({"base/contract.sol", "include/contract.sol"}, withPreamble(""));
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path(); boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::canonical(tempDir).relative_path();
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"--no-color", "--no-color",
"--base-path=base/", "--base-path=base/",
@ -1349,7 +1348,7 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import)
"-", "-",
}; };
string expectedMessage = std::string expectedMessage =
"Error: Source \"contract.sol\" not found: Ambiguous import. " "Error: Source \"contract.sol\" not found: Ambiguous import. "
"Multiple matching files found inside base path and/or include paths: \"" + "Multiple matching files found inside base path and/or include paths: \"" +
(expectedWorkDir / "base/contract.sol").generic_string() + "\", \"" + (expectedWorkDir / "base/contract.sol").generic_string() + "\", \"" +

View File

@ -47,9 +47,9 @@ using namespace solidity::yul;
namespace namespace
{ {
CommandLineOptions parseCommandLine(vector<string> const& _commandLine) CommandLineOptions parseCommandLine(std::vector<std::string> const& _commandLine)
{ {
vector<char const*> argv = test::makeArgv(_commandLine); std::vector<char const*> argv = test::makeArgv(_commandLine);
CommandLineParser cliParser; CommandLineParser cliParser;
cliParser.parse(static_cast<int>(_commandLine.size()), argv.data()); cliParser.parse(static_cast<int>(_commandLine.size()), argv.data());
@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(no_options)
BOOST_AUTO_TEST_CASE(help_license_version) BOOST_AUTO_TEST_CASE(help_license_version)
{ {
map<string, InputMode> expectedModePerOption = { std::map<std::string, InputMode> expectedModePerOption = {
{"--help", InputMode::Help}, {"--help", InputMode::Help},
{"--license", InputMode::License}, {"--license", InputMode::License},
{"--version", InputMode::Version}, {"--version", InputMode::Version},
@ -130,11 +130,11 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
"--libraries=" "--libraries="
"dir1/file1.sol:L=0x1234567890123456789012345678901234567890," "dir1/file1.sol:L=0x1234567890123456789012345678901234567890,"
"dir2/file2.sol:L=0x1111122222333334444455555666667777788888", "dir2/file2.sol:L=0x1111122222333334444455555666667777788888",
"--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi", "--ast-compact-json", "--asm", "--asm-json", "--bin", "--bin-runtime", "--abi",
"--ir", "--ir-ast-json", "--ir-optimized", "--ir-optimized-ast-json", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout", "--ir", "--ir-ast-json", "--ir-optimized", "--ir-optimized-ast-json", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout",
"--gas", "--gas",
"--combined-json=" "--combined-json="
"abi,metadata,bin,bin-runtime,opcodes,asm,storage-layout,generated-sources,generated-sources-runtime," "abi,metadata,bin,bin-runtime,asm,storage-layout,generated-sources,generated-sources-runtime,"
"srcmap,srcmap-runtime,function-debug,function-debug-runtime,hashes,devdoc,userdoc,ast", "srcmap,srcmap-runtime,function-debug,function-debug-runtime,hashes,devdoc,userdoc,ast",
"--metadata-hash=swarm", "--metadata-hash=swarm",
"--metadata-literal", "--metadata-literal",
@ -193,14 +193,13 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true,
}; };
expectedOptions.compiler.estimateGas = true; expectedOptions.compiler.estimateGas = true;
expectedOptions.compiler.combinedJsonRequests = { expectedOptions.compiler.combinedJsonRequests = {
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true,
}; };
expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1; expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1;
expectedOptions.metadata.literalSources = true; expectedOptions.metadata.literalSources = true;
@ -264,7 +263,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
for (auto const& [assemblyOptions, expectedMachine, expectedLanguage]: allowedCombinations) for (auto const& [assemblyOptions, expectedMachine, expectedLanguage]: allowedCombinations)
{ {
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"contract.yul", "contract.yul",
"/tmp/projects/token.yul", "/tmp/projects/token.yul",
@ -298,7 +297,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
}; };
commandLine += assemblyOptions; commandLine += assemblyOptions;
if (expectedLanguage == YulStack::Language::StrictAssembly) if (expectedLanguage == YulStack::Language::StrictAssembly)
commandLine += vector<string>{ commandLine += std::vector<std::string>{
"--optimize", "--optimize",
"--optimize-runs=1000", "--optimize-runs=1000",
"--yul-optimizations=agf", "--yul-optimizations=agf",
@ -351,7 +350,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
BOOST_AUTO_TEST_CASE(standard_json_mode_options) BOOST_AUTO_TEST_CASE(standard_json_mode_options)
{ {
vector<string> commandLine = { std::vector<std::string> commandLine = {
"solc", "solc",
"input.json", "input.json",
"--standard-json", "--standard-json",
@ -420,16 +419,16 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations)
}; };
for (auto const& [optionName, inputModes]: invalidOptionInputModeCombinations) for (auto const& [optionName, inputModes]: invalidOptionInputModeCombinations)
for (string const& inputMode: inputModes) for (std::string const& inputMode: inputModes)
{ {
stringstream serr; stringstream serr;
size_t separatorPosition = optionName.find("="); size_t separatorPosition = optionName.find("=");
string optionNameWithoutValue = optionName.substr(0, separatorPosition); std::string optionNameWithoutValue = optionName.substr(0, separatorPosition);
soltestAssert(!optionNameWithoutValue.empty()); soltestAssert(!optionNameWithoutValue.empty());
vector<string> commandLine = {"solc", optionName, "file", inputMode}; std::vector<std::string> commandLine = {"solc", optionName, "file", inputMode};
string expectedMessage = "The following options are not supported in the current input mode: " + optionNameWithoutValue; std::string expectedMessage = "The following options are not supported in the current input mode: " + optionNameWithoutValue;
auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedMessage; }; auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedMessage; };
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage); BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage);
@ -445,7 +444,7 @@ BOOST_AUTO_TEST_CASE(optimizer_flags)
OptimiserSettings evmasmOnly = OptimiserSettings::standard(); OptimiserSettings evmasmOnly = OptimiserSettings::standard();
evmasmOnly.runYulOptimiser = false; evmasmOnly.runYulOptimiser = false;
map<vector<string>, OptimiserSettings> settingsMap = { std::map<std::vector<std::string>, OptimiserSettings> settingsMap = {
{{}, OptimiserSettings::minimal()}, {{}, OptimiserSettings::minimal()},
{{"--optimize"}, OptimiserSettings::standard()}, {{"--optimize"}, OptimiserSettings::standard()},
{{"--no-optimize-yul"}, OptimiserSettings::minimal()}, {{"--no-optimize-yul"}, OptimiserSettings::minimal()},
@ -454,7 +453,7 @@ BOOST_AUTO_TEST_CASE(optimizer_flags)
{{"--optimize", "--optimize-yul"}, OptimiserSettings::standard()}, {{"--optimize", "--optimize-yul"}, OptimiserSettings::standard()},
}; };
map<InputMode, string> inputModeFlagMap = { std::map<InputMode, std::string> inputModeFlagMap = {
{InputMode::Compiler, ""}, {InputMode::Compiler, ""},
{InputMode::CompilerWithASTImport, "--import-ast"}, {InputMode::CompilerWithASTImport, "--import-ast"},
{InputMode::Assembler, "--strict-assembly"}, {InputMode::Assembler, "--strict-assembly"},
@ -463,7 +462,7 @@ BOOST_AUTO_TEST_CASE(optimizer_flags)
for (auto const& [inputMode, inputModeFlag]: inputModeFlagMap) for (auto const& [inputMode, inputModeFlag]: inputModeFlagMap)
for (auto const& [optimizerFlags, expectedOptimizerSettings]: settingsMap) for (auto const& [optimizerFlags, expectedOptimizerSettings]: settingsMap)
{ {
vector<string> commandLine = {"solc", inputModeFlag, "file"}; std::vector<std::string> commandLine = {"solc", inputModeFlag, "file"};
commandLine += optimizerFlags; commandLine += optimizerFlags;
BOOST_CHECK(parseCommandLine(commandLine).optimiserSettings() == expectedOptimizerSettings); BOOST_CHECK(parseCommandLine(commandLine).optimiserSettings() == expectedOptimizerSettings);
} }
@ -478,7 +477,7 @@ BOOST_AUTO_TEST_CASE(default_optimiser_sequence)
BOOST_AUTO_TEST_CASE(valid_optimiser_sequences) BOOST_AUTO_TEST_CASE(valid_optimiser_sequences)
{ {
vector<string> validSequenceInputs { std::vector<std::string> validSequenceInputs {
":", // Empty optimization sequence and empty cleanup sequence ":", // Empty optimization sequence and empty cleanup sequence
":fDn", // Empty optimization sequence and specified cleanup sequence ":fDn", // Empty optimization sequence and specified cleanup sequence
"dhfoDgvulfnTUtnIf:", // Specified optimization sequence and empty cleanup sequence "dhfoDgvulfnTUtnIf:", // Specified optimization sequence and empty cleanup sequence
@ -513,7 +512,7 @@ BOOST_AUTO_TEST_CASE(valid_optimiser_sequences)
BOOST_AUTO_TEST_CASE(invalid_optimiser_sequences) BOOST_AUTO_TEST_CASE(invalid_optimiser_sequences)
{ {
vector<string> const invalidSequenceInputs { std::vector<std::string> const invalidSequenceInputs {
"abcdefg{hijklmno}pqr[st]uvwxyz", // Invalid abbreviation "abcdefg{hijklmno}pqr[st]uvwxyz", // Invalid abbreviation
"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
@ -531,7 +530,7 @@ BOOST_AUTO_TEST_CASE(invalid_optimiser_sequences)
"dhfoDgvulfnTU:tnIf:fdN" // Too many cleanup sequence delimiters "dhfoDgvulfnTU:tnIf:fdN" // Too many cleanup sequence delimiters
}; };
vector<string> const expectedErrorMessages { std::vector<std::string> const expectedErrorMessages {
"'b' is not a valid step abbreviation", "'b' is not a valid step abbreviation",
"Brackets nested too deep", "Brackets nested too deep",
"Unbalanced brackets", "Unbalanced brackets",
@ -542,12 +541,12 @@ BOOST_AUTO_TEST_CASE(invalid_optimiser_sequences)
BOOST_CHECK_EQUAL(invalidSequenceInputs.size(), expectedErrorMessages.size()); BOOST_CHECK_EQUAL(invalidSequenceInputs.size(), expectedErrorMessages.size());
string const baseExpectedErrorMessage = "Invalid optimizer step sequence in --yul-optimizations: "; std::string const baseExpectedErrorMessage = "Invalid optimizer step sequence in --yul-optimizations: ";
for (size_t i = 0; i < invalidSequenceInputs.size(); ++i) for (size_t i = 0; i < invalidSequenceInputs.size(); ++i)
{ {
vector<string> const commandLineOptions = {"solc", "contract.sol", "--optimize", "--yul-optimizations=" + invalidSequenceInputs[i]}; std::vector<std::string> const commandLineOptions = {"solc", "contract.sol", "--optimize", "--yul-optimizations=" + invalidSequenceInputs[i]};
string const expectedErrorMessage = baseExpectedErrorMessage + expectedErrorMessages[i]; std::string const expectedErrorMessage = baseExpectedErrorMessage + expectedErrorMessages[i];
auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; };
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage);
} }