mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11110 from ethereum/issue_10475_isoltest_external_sources
[isoltest] Add support for external sources.
This commit is contained in:
@@ -256,7 +256,7 @@ TestCase::TestResult SemanticTest::runTest(
|
||||
{
|
||||
soltestAssert(
|
||||
m_allowNonExistingFunctions ||
|
||||
m_compiler.methodIdentifiers(m_compiler.lastContractName()).isMember(test.call().signature),
|
||||
m_compiler.methodIdentifiers(m_compiler.lastContractName(m_sources.mainSourceFile)).isMember(test.call().signature),
|
||||
"The function " + test.call().signature + " is not known to the compiler"
|
||||
);
|
||||
|
||||
@@ -283,7 +283,7 @@ TestCase::TestResult SemanticTest::runTest(
|
||||
|
||||
test.setFailure(!m_transactionSuccessful);
|
||||
test.setRawBytes(std::move(output));
|
||||
test.setContractABI(m_compiler.contractABI(m_compiler.lastContractName()));
|
||||
test.setContractABI(m_compiler.contractABI(m_compiler.lastContractName(m_sources.mainSourceFile)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,42 +379,62 @@ void SemanticTest::printSource(ostream& _stream, string const& _linePrefix, bool
|
||||
if (m_sources.sources.empty())
|
||||
return;
|
||||
|
||||
bool outputNames = (m_sources.sources.size() != 1 || !m_sources.sources.begin()->first.empty());
|
||||
bool outputNames = (m_sources.sources.size() - m_sources.externalSources.size() != 1 || !m_sources.sources.begin()->first.empty());
|
||||
|
||||
set<string> externals;
|
||||
for (auto const& [name, path]: m_sources.externalSources)
|
||||
{
|
||||
externals.insert(name);
|
||||
string externalSource;
|
||||
if (name == path)
|
||||
externalSource = name;
|
||||
else
|
||||
externalSource = name + "=" + path.generic_string();
|
||||
|
||||
if (_formatted)
|
||||
_stream << _linePrefix << formatting::CYAN << "==== ExternalSource: " << externalSource << " ===="s << formatting::RESET << endl;
|
||||
else
|
||||
_stream << _linePrefix << "==== ExternalSource: " << externalSource << " ===="s << endl;
|
||||
}
|
||||
|
||||
for (auto const& [name, source]: m_sources.sources)
|
||||
if (_formatted)
|
||||
if (externals.find(name) == externals.end())
|
||||
{
|
||||
if (source.empty())
|
||||
continue;
|
||||
|
||||
if (outputNames)
|
||||
_stream << _linePrefix << formatting::CYAN << "==== Source: " << name << " ====" << formatting::RESET << endl;
|
||||
vector<char const*> sourceFormatting(source.length(), formatting::RESET);
|
||||
|
||||
_stream << _linePrefix << sourceFormatting.front() << source.front();
|
||||
for (size_t i = 1; i < source.length(); i++)
|
||||
if (_formatted)
|
||||
{
|
||||
if (sourceFormatting[i] != sourceFormatting[i - 1])
|
||||
_stream << sourceFormatting[i];
|
||||
if (source[i] != '\n')
|
||||
_stream << source[i];
|
||||
else
|
||||
if (source.empty())
|
||||
continue;
|
||||
|
||||
if (outputNames)
|
||||
_stream << _linePrefix << formatting::CYAN << "==== Source: " << name
|
||||
<< " ====" << formatting::RESET << endl;
|
||||
|
||||
vector<char const*> sourceFormatting(source.length(), formatting::RESET);
|
||||
_stream << _linePrefix << sourceFormatting.front() << source.front();
|
||||
for (size_t i = 1; i < source.length(); i++)
|
||||
{
|
||||
_stream << formatting::RESET << endl;
|
||||
if (i + 1 < source.length())
|
||||
_stream << _linePrefix << sourceFormatting[i];
|
||||
if (sourceFormatting[i] != sourceFormatting[i - 1])
|
||||
_stream << sourceFormatting[i];
|
||||
if (source[i] != '\n')
|
||||
_stream << source[i];
|
||||
else
|
||||
{
|
||||
_stream << formatting::RESET << endl;
|
||||
if (i + 1 < source.length())
|
||||
_stream << _linePrefix << sourceFormatting[i];
|
||||
}
|
||||
}
|
||||
_stream << formatting::RESET;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outputNames)
|
||||
_stream << _linePrefix << "==== Source: " + name << " ====" << endl;
|
||||
stringstream stream(source);
|
||||
string line;
|
||||
while (getline(stream, line))
|
||||
_stream << _linePrefix << line << endl;
|
||||
}
|
||||
_stream << formatting::RESET;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outputNames)
|
||||
_stream << _linePrefix << "==== Source: " + name << " ====" << endl;
|
||||
stringstream stream(source);
|
||||
string line;
|
||||
while (getline(stream, line))
|
||||
_stream << _linePrefix << line << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +475,6 @@ bool SemanticTest::deploy(
|
||||
map<string, solidity::test::Address> const& _libraries
|
||||
)
|
||||
{
|
||||
auto output = compileAndRunWithoutCheck(m_sources.sources, _value, _contractName, _arguments, _libraries);
|
||||
auto output = compileAndRunWithoutCheck(m_sources.sources, _value, _contractName, _arguments, _libraries, m_sources.mainSourceFile);
|
||||
return !output.empty() && m_transactionSuccessful;
|
||||
}
|
||||
|
||||
@@ -36,10 +36,13 @@ using namespace std;
|
||||
|
||||
bytes SolidityExecutionFramework::multiSourceCompileContract(
|
||||
map<string, string> const& _sourceCode,
|
||||
optional<string> const& _mainSourceName,
|
||||
string const& _contractName,
|
||||
map<string, Address> const& _libraryAddresses
|
||||
)
|
||||
{
|
||||
if (_mainSourceName.has_value())
|
||||
solAssert(_sourceCode.find(_mainSourceName.value()) != _sourceCode.end(), "");
|
||||
map<string, string> sourcesWithPreamble = _sourceCode;
|
||||
for (auto& entry: sourcesWithPreamble)
|
||||
entry.second = addPreamble(entry.second);
|
||||
@@ -68,7 +71,7 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
||||
formatter.printErrorInformation(*error);
|
||||
BOOST_ERROR("Compiling contract failed");
|
||||
}
|
||||
std::string contractName(_contractName.empty() ? m_compiler.lastContractName() : _contractName);
|
||||
string contractName(_contractName.empty() ? m_compiler.lastContractName(_mainSourceName) : _contractName);
|
||||
evmasm::LinkerObject obj;
|
||||
if (m_compileViaYul)
|
||||
{
|
||||
@@ -98,7 +101,7 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
||||
try
|
||||
{
|
||||
asmStack.optimize();
|
||||
obj = std::move(*asmStack.assemble(yul::AssemblyStack::Machine::EVM).bytecode);
|
||||
obj = move(*asmStack.assemble(yul::AssemblyStack::Machine::EVM).bytecode);
|
||||
obj.link(_libraryAddresses);
|
||||
break;
|
||||
}
|
||||
@@ -126,6 +129,7 @@ bytes SolidityExecutionFramework::compileContract(
|
||||
{
|
||||
return multiSourceCompileContract(
|
||||
{{"", _sourceCode}},
|
||||
nullopt,
|
||||
_contractName,
|
||||
_libraryAddresses
|
||||
);
|
||||
|
||||
@@ -49,10 +49,11 @@ public:
|
||||
u256 const& _value = 0,
|
||||
std::string const& _contractName = "",
|
||||
bytes const& _arguments = {},
|
||||
std::map<std::string, solidity::test::Address> const& _libraryAddresses = {}
|
||||
std::map<std::string, solidity::test::Address> const& _libraryAddresses = {},
|
||||
std::optional<std::string> const& _sourceName = std::nullopt
|
||||
) override
|
||||
{
|
||||
bytes bytecode = multiSourceCompileContract(_sourceCode, _contractName, _libraryAddresses);
|
||||
bytes bytecode = multiSourceCompileContract(_sourceCode, _sourceName, _contractName, _libraryAddresses);
|
||||
sendMessage(bytecode + _arguments, true, _value);
|
||||
return m_output;
|
||||
}
|
||||
@@ -65,6 +66,7 @@ public:
|
||||
|
||||
bytes multiSourceCompileContract(
|
||||
std::map<std::string, std::string> const& _sources,
|
||||
std::optional<std::string> const& _mainSourceName = std::nullopt,
|
||||
std::string const& _contractName = "",
|
||||
std::map<std::string, solidity::test::Address> const& _libraryAddresses = {}
|
||||
);
|
||||
|
||||
@@ -65,7 +65,7 @@ string SyntaxTest::addPreamble(string const& _sourceCode)
|
||||
void SyntaxTest::setupCompiler()
|
||||
{
|
||||
compiler().reset();
|
||||
auto sourcesWithPragma = m_sources;
|
||||
auto sourcesWithPragma = m_sources.sources;
|
||||
for (auto& source: sourcesWithPragma)
|
||||
source.second = addPreamble(source.second);
|
||||
compiler().setSources(sourcesWithPragma);
|
||||
@@ -122,8 +122,8 @@ void SyntaxTest::filterObtainedErrors()
|
||||
solAssert(location->source, "");
|
||||
sourceName = location->source->name();
|
||||
|
||||
solAssert(m_sources.count(sourceName) == 1, "");
|
||||
int preambleSize = static_cast<int>(location->source->source().size()) - static_cast<int>(m_sources[sourceName].size());
|
||||
solAssert(m_sources.sources.count(sourceName) == 1, "");
|
||||
int preambleSize = static_cast<int>(location->source->source().size()) - static_cast<int>(m_sources.sources[sourceName].size());
|
||||
solAssert(preambleSize >= 0, "");
|
||||
|
||||
// ignore the version & license pragma inserted by the testing tool when calculating locations.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
contract External {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract External {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import "external.sol";
|
||||
import "other_external.sol";
|
||||
@@ -0,0 +1 @@
|
||||
import "subdir/import.sol";
|
||||
@@ -0,0 +1,2 @@
|
||||
contract OtherExternal {
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import "sub_external.sol";
|
||||
@@ -0,0 +1,2 @@
|
||||
contract SubExternal {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract A {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract C {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract D {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract D {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract C {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import {C} from "../../c.sol";
|
||||
contract B {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import {B} from "../B/b.sol";
|
||||
contract G {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract A {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import {A} from "./a.sol";
|
||||
import {B} from "./B/b.sol";
|
||||
import {C} from "../c.sol";
|
||||
import {D} from "../D/d.sol";
|
||||
import {G} from "./E/../F/../G/./g.sol";
|
||||
import {H} from "../../../../_relative_imports/h.sol";
|
||||
contract Contract {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract H {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
contract B {
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
contract A {
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import {A} from "./a.sol";
|
||||
import {B} from "../b.sol";
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
contract Dot_A {
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
contract Dot_Dot_B {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
==== ExternalSource: a=_external/external.sol=sol ====
|
||||
import {External} from "a";
|
||||
contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,10 @@
|
||||
==== ExternalSource: _external/external.sol ====
|
||||
==== ExternalSource: _external/other_external.sol ====
|
||||
import {External} from "_external/external.sol";
|
||||
import {OtherExternal} from "_external/other_external.sol";
|
||||
contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,14 @@
|
||||
==== ExternalSource: _external/external.sol ====
|
||||
==== Source: s1.sol ====
|
||||
import {External} from "_external/external.sol";
|
||||
contract S1 {
|
||||
}
|
||||
==== Source: s2.sol ====
|
||||
import {S1} from "s1.sol";
|
||||
contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
==== ExternalSource: _non_normalized_paths//a.sol ====
|
||||
==== ExternalSource: C/////c.sol=_non_normalized_paths/c.sol ====
|
||||
==== ExternalSource: C/../////D/d.sol=_non_normalized_paths///d.sol ====
|
||||
import {A} from "_non_normalized_paths//a.sol";
|
||||
import {C} from "C/////c.sol";
|
||||
import {D} from "C/../////D/d.sol";
|
||||
contract Contract {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,14 @@
|
||||
==== ExternalSource: _relative_imports/dir/contract.sol ====
|
||||
==== ExternalSource: _relative_imports/dir/a.sol ====
|
||||
==== ExternalSource: _relative_imports/dir/B/b.sol ====
|
||||
==== ExternalSource: _relative_imports/c.sol ====
|
||||
==== ExternalSource: _relative_imports/D/d.sol ====
|
||||
==== ExternalSource: _relative_imports/dir/G/g.sol ====
|
||||
==== ExternalSource: _relative_imports/h.sol ====
|
||||
import {A, B, C, D, G, H, Contract} from "_relative_imports/dir/contract.sol";
|
||||
contract CC {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,8 @@
|
||||
==== ExternalSource: _external/external.sol ====
|
||||
import {External} from "_external/external.sol";
|
||||
contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,10 @@
|
||||
==== ExternalSource: _external/external.sol ====
|
||||
==== ExternalSource: _external/other_external.sol ====
|
||||
import {External} from "_external/external.sol";
|
||||
import {OtherExternal} from "_external/other_external.sol";
|
||||
contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,10 @@
|
||||
==== ExternalSource: _external/import_with_subdir.sol ====
|
||||
==== ExternalSource: subdir/import.sol=_external/subdir/import.sol ====
|
||||
==== ExternalSource: sub_external.sol=_external/subdir/sub_external.sol ====
|
||||
import {SubExternal} from "sub_external.sol";
|
||||
contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,12 @@
|
||||
==== ExternalSource: ./a.sol=_source_name_starting_with_dots/dot_a.sol ====
|
||||
==== ExternalSource: ../b.sol=_source_name_starting_with_dots/dot_dot_b.sol ====
|
||||
==== ExternalSource: _source_name_starting_with_dots/dir/a.sol ====
|
||||
==== ExternalSource: _source_name_starting_with_dots/b.sol ====
|
||||
==== ExternalSource: _source_name_starting_with_dots/dir/contract.sol ====
|
||||
import {A, B} from "_source_name_starting_with_dots/dir/contract.sol";
|
||||
contract Contract {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
@@ -0,0 +1,12 @@
|
||||
==== ExternalSource: ExtSource.sol=_external/external.sol ====
|
||||
==== ExternalSource: /ExtSource.sol=_external/other_external.sol ====
|
||||
import "ExtSource.sol";
|
||||
import "/ExtSource.sol";
|
||||
contract C {
|
||||
External _external;
|
||||
OtherExternal _otherExternal;
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor()
|
||||
Reference in New Issue
Block a user