Browse Source

Merge branch 'develop' into develop-evmcc

Conflicts:
	windows/LibEthereum.vcxproj
cl-refactor
Paweł Bylica 10 years ago
parent
commit
e9e9213f52
  1. 6
      alethzero/MainWin.cpp
  2. 8
      libdevcore/CommonData.cpp
  3. 2
      libethcore/CommonEth.cpp
  4. 4
      libevm/VM.h
  5. 15
      libsolidity/AST.cpp
  6. 2
      libsolidity/AST.h
  7. 8
      libsolidity/ASTPrinter.cpp
  8. 4
      libsolidity/ASTPrinter.h
  9. 40
      libsolidity/Compiler.cpp
  10. 100
      libsolidity/CompilerStack.cpp
  11. 41
      libsolidity/CompilerStack.h
  12. 39
      solc/main.cpp
  13. 47
      test/TestHelper.cpp
  14. 14
      test/solidityCompiler.cpp
  15. 169
      test/solidityEndToEndTest.cpp
  16. 214
      test/solidityJSONInterfaceTest.cpp
  17. 38
      test/stPreCompiledContractsFiller.json
  18. 34
      test/state.cpp
  19. 6
      windows/LibEthereum.vcxproj
  20. 18
      windows/LibEthereum.vcxproj.filters

6
alethzero/MainWin.cpp

@ -1608,15 +1608,15 @@ void Main::on_data_textChanged()
} }
else if (src.substr(0, 8) == "contract") // improve this heuristic else if (src.substr(0, 8) == "contract") // improve this heuristic
{ {
shared_ptr<solidity::Scanner> scanner = make_shared<solidity::Scanner>(); dev::solidity::CompilerStack compiler;
try try
{ {
m_data = dev::solidity::CompilerStack::compile(src, scanner, m_enableOptimizer); m_data = compiler.compile(src, m_enableOptimizer);
} }
catch (dev::Exception const& exception) catch (dev::Exception const& exception)
{ {
ostringstream error; ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", *scanner); solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler.getScanner());
solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>"; solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>";
} }
catch (...) catch (...)

8
libdevcore/CommonData.cpp

@ -29,14 +29,20 @@ using namespace dev;
std::string dev::escaped(std::string const& _s, bool _all) std::string dev::escaped(std::string const& _s, bool _all)
{ {
static const map<char, char> prettyEscapes{{'\r', 'r'}, {'\n', 'n'}, {'\t', 't'}, {'\v', 'v'}};
std::string ret; std::string ret;
ret.reserve(_s.size()); ret.reserve(_s.size() + 2);
ret.push_back('"'); ret.push_back('"');
for (auto i: _s) for (auto i: _s)
if (i == '"' && !_all) if (i == '"' && !_all)
ret += "\\\""; ret += "\\\"";
else if (i == '\\' && !_all) else if (i == '\\' && !_all)
ret += "\\\\"; ret += "\\\\";
else if (prettyEscapes.count(i))
{
ret += '\\';
ret += prettyEscapes.find(i)->second;
}
else if (i < ' ' || _all) else if (i < ' ' || _all)
{ {
ret += "\\x"; ret += "\\x";

2
libethcore/CommonEth.cpp

@ -34,7 +34,7 @@ namespace dev
namespace eth namespace eth
{ {
const unsigned c_protocolVersion = 41; const unsigned c_protocolVersion = 42;
const unsigned c_databaseVersion = 4; const unsigned c_databaseVersion = 4;
static const vector<pair<u256, string>> g_units = static const vector<pair<u256, string>> g_units =

4
libevm/VM.h

@ -184,7 +184,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
{ {
unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0; unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
require(n + 2); require(n + 2);
runGas = c_logGas + c_logTopicGas * n + c_logDataGas * m_stack[m_stack.size() - 2]; runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]); newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
break; break;
} }
@ -192,7 +192,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::CALL: case Instruction::CALL:
case Instruction::CALLCODE: case Instruction::CALLCODE:
require(7); require(7);
runGas = c_callGas + m_stack[m_stack.size() - 1]; runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
break; break;

15
libsolidity/AST.cpp

@ -263,6 +263,21 @@ TypeError ASTNode::createTypeError(string const& _description)
return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description); return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description);
} }
vector<FunctionDefinition const*> ContractDefinition::getInterfaceFunctions() const
{
vector<FunctionDefinition const*> exportedFunctions;
for (ASTPointer<FunctionDefinition> const& f: m_definedFunctions)
if (f->isPublic() && f->getName() != getName())
exportedFunctions.push_back(f.get());
auto compareNames = [](FunctionDefinition const* _a, FunctionDefinition const* _b)
{
return _a->getName().compare(_b->getName()) < 0;
};
sort(exportedFunctions.begin(), exportedFunctions.end(), compareNames);
return exportedFunctions;
}
void Block::checkTypeRequirements() void Block::checkTypeRequirements()
{ {
for (shared_ptr<Statement> const& statement: m_statements) for (shared_ptr<Statement> const& statement: m_statements)

2
libsolidity/AST.h

@ -120,6 +120,8 @@ public:
std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; } std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; } std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
/// Returns the functions that make up the calling interface in the intended order.
std::vector<FunctionDefinition const*> getInterfaceFunctions() const;
private: private:
std::vector<ASTPointer<StructDefinition>> m_definedStructs; std::vector<ASTPointer<StructDefinition>> m_definedStructs;
std::vector<ASTPointer<VariableDeclaration>> m_stateVariables; std::vector<ASTPointer<VariableDeclaration>> m_stateVariables;

8
libsolidity/ASTPrinter.cpp

@ -30,8 +30,8 @@ namespace dev
namespace solidity namespace solidity
{ {
ASTPrinter::ASTPrinter(ASTPointer<ASTNode> const& _ast, string const& _source): ASTPrinter::ASTPrinter(ASTNode& _ast, string const& _source):
m_indentation(0), m_source(_source), m_ast(_ast) m_indentation(0), m_source(_source), m_ast(&_ast)
{ {
} }
@ -430,8 +430,8 @@ void ASTPrinter::printSourcePart(ASTNode const& _node)
if (!m_source.empty()) if (!m_source.empty())
{ {
Location const& location(_node.getLocation()); Location const& location(_node.getLocation());
*m_ostream << getIndentation() << " Source: |" *m_ostream << getIndentation() << " Source: "
<< m_source.substr(location.start, location.end - location.start) << "|" << endl; << escaped(m_source.substr(location.start, location.end - location.start), false) << endl;
} }
} }

4
libsolidity/ASTPrinter.h

@ -38,7 +38,7 @@ class ASTPrinter: public ASTVisitor
public: public:
/// Create a printer for the given abstract syntax tree. If the source is specified, /// Create a printer for the given abstract syntax tree. If the source is specified,
/// the corresponding parts of the source are printed with each node. /// the corresponding parts of the source are printed with each node.
ASTPrinter(ASTPointer<ASTNode> const& _ast, std::string const& _source = std::string()); ASTPrinter(ASTNode& _ast, std::string const& _source = std::string());
/// Output the string representation of the AST to _stream. /// Output the string representation of the AST to _stream.
void print(std::ostream& _stream); void print(std::ostream& _stream);
@ -114,7 +114,7 @@ private:
int m_indentation; int m_indentation;
std::string m_source; std::string m_source;
ASTPointer<ASTNode> m_ast; ASTNode* m_ast;
std::ostream* m_ostream; std::ostream* m_ostream;
}; };

40
libsolidity/Compiler.cpp

@ -81,36 +81,34 @@ void Compiler::appendFunctionSelector(vector<ASTPointer<FunctionDefinition>> con
if (publicFunctions.size() > 255) if (publicFunctions.size() > 255)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("More than 255 public functions for contract.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("More than 255 public functions for contract."));
//@todo check for calldatasize? // retrieve the first byte of the call data, which determines the called function
// retrieve the first byte of the call data // @todo This code had a jump table in a previous version which was more efficient but also
m_context << u256(0) << eth::Instruction::CALLDATALOAD << u256(0) << eth::Instruction::BYTE; // error prone (due to the optimizer and variable length tag addresses)
// check that it is not too large m_context << u256(1) << u256(0) // some constants
m_context << eth::Instruction::DUP1 << u256(publicFunctions.size() - 1) << eth::Instruction::LT; << eth::dupInstruction(1) << eth::Instruction::CALLDATALOAD
eth::AssemblyItem returnTag = m_context.appendConditionalJump(); << eth::dupInstruction(2) << eth::Instruction::BYTE
<< eth::dupInstruction(2);
// otherwise, jump inside jump table (each entry of the table has size 4)
m_context << u256(4) << eth::Instruction::MUL; // stack here: 1 0 <funid> 0, stack top will be counted up until it matches funid
eth::AssemblyItem jumpTableStart = m_context.pushNewTag();
m_context << eth::Instruction::ADD << eth::Instruction::JUMP;
// jump table, tell the optimizer not to remove the JUMPDESTs
m_context << eth::AssemblyItem(eth::NoOptimizeBegin) << jumpTableStart;
for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions) for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions)
m_context.appendJumpTo(f.second.second) << eth::Instruction::JUMPDEST; {
m_context << eth::AssemblyItem(eth::NoOptimizeEnd); eth::AssemblyItem const& callDataUnpackerEntry = f.second.second;
m_context << eth::dupInstruction(2) << eth::dupInstruction(2) << eth::Instruction::EQ;
m_context << returnTag << eth::Instruction::STOP; m_context.appendConditionalJumpTo(callDataUnpackerEntry);
m_context << eth::dupInstruction(4) << eth::Instruction::ADD;
//@todo avoid the last ADD (or remove it in the optimizer)
}
m_context << eth::Instruction::STOP; // function not found
for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions) for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions)
{ {
FunctionDefinition const& function = *f.second.first; FunctionDefinition const& function = *f.second.first;
m_context << f.second.second; eth::AssemblyItem const& callDataUnpackerEntry = f.second.second;
m_context << callDataUnpackerEntry;
eth::AssemblyItem returnTag = m_context.pushNewTag(); eth::AssemblyItem returnTag = m_context.pushNewTag();
appendCalldataUnpacker(function); appendCalldataUnpacker(function);
m_context.appendJumpTo(m_context.getFunctionEntryLabel(function)); m_context.appendJumpTo(m_context.getFunctionEntryLabel(function));
m_context << returnTag; m_context << returnTag;
appendReturnValuePacker(function); appendReturnValuePacker(function);
} }
} }

100
libsolidity/CompilerStack.cpp

@ -34,17 +34,101 @@ namespace dev
namespace solidity namespace solidity
{ {
bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr<Scanner> _scanner, void CompilerStack::setSource(string const& _sourceCode)
bool _optimize)
{ {
if (!_scanner) reset();
_scanner = make_shared<Scanner>(); m_scanner = make_shared<Scanner>(CharStream(_sourceCode));
_scanner->reset(CharStream(_sourceCode)); }
void CompilerStack::parse()
{
if (!m_scanner)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available."));
m_contractASTNode = Parser().parse(m_scanner);
NameAndTypeResolver().resolveNamesAndTypes(*m_contractASTNode);
m_parseSuccessful = true;
}
void CompilerStack::parse(string const& _sourceCode)
{
setSource(_sourceCode);
parse();
}
bytes const& CompilerStack::compile(bool _optimize)
{
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
m_bytecode.clear();
m_compiler = make_shared<Compiler>();
m_compiler->compileContract(*m_contractASTNode);
return m_bytecode = m_compiler->getAssembledBytecode(_optimize);
}
ASTPointer<ContractDefinition> contract = Parser().parse(_scanner); bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
NameAndTypeResolver().resolveNamesAndTypes(*contract); {
return Compiler::compile(*contract, _optimize); parse(_sourceCode);
return compile(_optimize);
} }
void CompilerStack::streamAssembly(ostream& _outStream)
{
if (!m_compiler || m_bytecode.empty())
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
m_compiler->streamAssembly(_outStream);
}
string const& CompilerStack::getInterface()
{
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
if (m_interface.empty())
{
stringstream interface;
interface << '[';
vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions();
unsigned functionsCount = exportedFunctions.size();
for (FunctionDefinition const* f: exportedFunctions)
{
auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars)
{
unsigned varCount = _vars.size();
for (ASTPointer<VariableDeclaration> const& var: _vars)
{
interface << "{"
<< "\"name\":" << escaped(var->getName(), false) << ","
<< "\"type\":" << escaped(var->getType()->toString(), false)
<< "}";
if (--varCount > 0)
interface << ",";
}
};
interface << '{'
<< "\"name\":" << escaped(f->getName(), false) << ","
<< "\"inputs\":[";
streamVariables(f->getParameters());
interface << "],"
<< "\"outputs\":[";
streamVariables(f->getReturnParameters());
interface << "]"
<< "}";
if (--functionsCount > 0)
interface << ",";
}
interface << ']';
m_interface = interface.str();
}
return m_interface;
}
bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)
{
CompilerStack stack;
return stack.compile(_sourceCode, _optimize);
}
} }
} }

41
libsolidity/CompilerStack.h

@ -22,6 +22,7 @@
#pragma once #pragma once
#include <ostream>
#include <string> #include <string>
#include <memory> #include <memory>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
@ -30,13 +31,51 @@ namespace dev {
namespace solidity { namespace solidity {
class Scanner; // forward class Scanner; // forward
class ContractDefinition; // forward
class Compiler; // forward
/**
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
* It holds state and can be used to either step through the compilation stages (and abort e.g.
* before compilation to bytecode) or run the whole compilation in one call.
*/
class CompilerStack class CompilerStack
{ {
public: public:
CompilerStack() {}
void reset() { *this = CompilerStack(); }
void setSource(std::string const& _sourceCode);
void parse();
void parse(std::string const& _sourceCode);
/// Compiles the contract that was previously parsed.
bytes const& compile(bool _optimize = false);
/// Parses and compiles the given source code.
bytes const& compile(std::string const& _sourceCode, bool _optimize = false);
bytes const& getBytecode() const { return m_bytecode; }
/// Streams a verbose version of the assembly to @a _outStream.
/// Prerequisite: Successful compilation.
void streamAssembly(std::ostream& _outStream);
/// Returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getInterface();
/// Returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& getScanner() const { return *m_scanner; }
ContractDefinition& getAST() const { return *m_contractASTNode; }
/// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for
/// scanning the source code - this is useful for printing exception information. /// scanning the source code - this is useful for printing exception information.
static bytes compile(std::string const& _sourceCode, std::shared_ptr<Scanner> _scanner = std::shared_ptr<Scanner>(), bool _optimize = false); static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false);
private:
std::shared_ptr<Scanner> m_scanner;
std::shared_ptr<ContractDefinition> m_contractASTNode;
bool m_parseSuccessful;
std::string m_interface;
std::shared_ptr<Compiler> m_compiler;
bytes m_bytecode;
}; };
} }

39
solc/main.cpp

@ -26,12 +26,13 @@
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevmcore/Instruction.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h> #include <libsolidity/Parser.h>
#include <libsolidity/ASTPrinter.h> #include <libsolidity/ASTPrinter.h>
#include <libsolidity/NameAndTypeResolver.h> #include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Exceptions.h> #include <libsolidity/Exceptions.h>
#include <libsolidity/Compiler.h> #include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h> #include <libsolidity/SourceReferenceFormatter.h>
using namespace std; using namespace std;
@ -85,48 +86,34 @@ int main(int argc, char** argv)
else else
sourceCode = asString(dev::contents(infile)); sourceCode = asString(dev::contents(infile));
ASTPointer<ContractDefinition> ast; CompilerStack compiler;
shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(sourceCode));
Parser parser;
bytes instructions;
Compiler compiler;
try try
{ {
ast = parser.parse(scanner); compiler.compile(sourceCode, optimize);
NameAndTypeResolver resolver;
resolver.resolveNamesAndTypes(*ast.get());
cout << "Syntax tree for the contract:" << endl;
dev::solidity::ASTPrinter printer(ast, sourceCode);
printer.print(cout);
compiler.compileContract(*ast);
instructions = compiler.getAssembledBytecode(optimize);
} }
catch (ParserError const& exception) catch (ParserError const& exception)
{ {
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", *scanner); SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler.getScanner());
return -1; return -1;
} }
catch (DeclarationError const& exception) catch (DeclarationError const& exception)
{ {
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", *scanner); SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler.getScanner());
return -1; return -1;
} }
catch (TypeError const& exception) catch (TypeError const& exception)
{ {
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", *scanner); SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler.getScanner());
return -1; return -1;
} }
catch (CompilerError const& exception) catch (CompilerError const& exception)
{ {
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", *scanner); SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler.getScanner());
return -1; return -1;
} }
catch (InternalCompilerError const& exception) catch (InternalCompilerError const& exception)
{ {
cerr << "Internal compiler error: " << boost::diagnostic_information(exception) << endl; SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler.getScanner());
return -1; return -1;
} }
catch (Exception const& exception) catch (Exception const& exception)
@ -140,11 +127,15 @@ int main(int argc, char** argv)
return -1; return -1;
} }
cout << "Syntax tree for the contract:" << endl;
ASTPrinter printer(compiler.getAST(), sourceCode);
printer.print(cout);
cout << "EVM assembly:" << endl; cout << "EVM assembly:" << endl;
compiler.streamAssembly(cout); compiler.streamAssembly(cout);
cout << "Opcodes:" << endl; cout << "Opcodes:" << endl;
cout << eth::disassemble(instructions) << endl; cout << eth::disassemble(compiler.getBytecode()) << endl;
cout << "Binary: " << toHex(instructions) << endl; cout << "Binary: " << toHex(compiler.getBytecode()) << endl;
cout << "Interface specification: " << compiler.getInterface() << endl;
return 0; return 0;
} }

47
test/TestHelper.cpp

@ -27,8 +27,6 @@
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
//#define FILL_TESTS
using namespace std; using namespace std;
using namespace dev::eth; using namespace dev::eth;
@ -357,28 +355,33 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
string testPath = getTestPath(); string testPath = getTestPath();
testPath += _testPathAppendix; testPath += _testPathAppendix;
#ifdef FILL_TESTS for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
try
{
cnote << "Populating tests...";
json_spirit::mValue v;
boost::filesystem::path p(__FILE__);
boost::filesystem::path dir = p.parent_path();
string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty.");
json_spirit::read_string(s, v);
doTests(v, true);
writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
}
catch (Exception const& _e)
{
BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
}
catch (std::exception const& _e)
{ {
BOOST_ERROR("Failed test with Exception: " << _e.what()); string arg = boost::unit_test::framework::master_test_suite().argv[i];
if (arg == "--filltests")
{
try
{
cnote << "Populating tests...";
json_spirit::mValue v;
boost::filesystem::path p(__FILE__);
boost::filesystem::path dir = p.parent_path();
string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty.");
json_spirit::read_string(s, v);
doTests(v, true);
writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
}
catch (Exception const& _e)
{
BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
}
catch (std::exception const& _e)
{
BOOST_ERROR("Failed test with Exception: " << _e.what());
}
}
} }
#endif
try try
{ {

14
test/solidityCompiler.cpp

@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
"}\n"; "}\n";
bytes code = compileContract(sourceCode); bytes code = compileContract(sourceCode);
unsigned boilerplateSize = 51; unsigned boilerplateSize = 42;
bytes expectation({byte(Instruction::JUMPDEST), bytes expectation({byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x0, // initialize local variable x byte(Instruction::PUSH1), 0x0, // initialize local variable x
byte(Instruction::PUSH1), 0x2, byte(Instruction::PUSH1), 0x2,
@ -100,8 +100,8 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers)
"}\n"; "}\n";
bytes code = compileContract(sourceCode); bytes code = compileContract(sourceCode);
unsigned shift = 75; unsigned shift = 70;
unsigned boilerplateSize = 88; unsigned boilerplateSize = 83;
bytes expectation({byte(Instruction::JUMPDEST), bytes expectation({byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x0, // initialize return variable d byte(Instruction::PUSH1), 0x0, // initialize return variable d
byte(Instruction::DUP3), byte(Instruction::DUP3),
@ -153,8 +153,8 @@ BOOST_AUTO_TEST_CASE(ifStatement)
"}\n"; "}\n";
bytes code = compileContract(sourceCode); bytes code = compileContract(sourceCode);
unsigned shift = 38; unsigned shift = 29;
unsigned boilerplateSize = 51; unsigned boilerplateSize = 42;
bytes expectation({byte(Instruction::JUMPDEST), bytes expectation({byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x0, byte(Instruction::PUSH1), 0x0,
byte(Instruction::DUP1), byte(Instruction::DUP1),
@ -195,8 +195,8 @@ BOOST_AUTO_TEST_CASE(loops)
"}\n"; "}\n";
bytes code = compileContract(sourceCode); bytes code = compileContract(sourceCode);
unsigned shift = 38; unsigned shift = 29;
unsigned boilerplateSize = 51; unsigned boilerplateSize = 42;
bytes expectation({byte(Instruction::JUMPDEST), bytes expectation({byte(Instruction::JUMPDEST),
byte(Instruction::JUMPDEST), byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0x1,

169
test/solidityEndToEndTest.cpp

@ -22,6 +22,7 @@
*/ */
#include <string> #include <string>
#include <tuple>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/Executive.h> #include <libethereum/Executive.h>
@ -41,36 +42,72 @@ class ExecutionFramework
public: public:
ExecutionFramework() { g_logVerbosity = 0; } ExecutionFramework() { g_logVerbosity = 0; }
bytes const& compileAndRun(std::string const& _sourceCode) bytes const& compileAndRun(string const& _sourceCode)
{ {
bytes code = dev::solidity::CompilerStack::compile(_sourceCode); bytes code = dev::solidity::CompilerStack::staticCompile(_sourceCode);
sendMessage(code, true); sendMessage(code, true);
BOOST_REQUIRE(!m_output.empty()); BOOST_REQUIRE(!m_output.empty());
return m_output; return m_output;
} }
bytes const& callFunction(byte _index, bytes const& _data) bytes const& callContractFunction(byte _index, bytes const& _data = bytes())
{ {
sendMessage(bytes(1, _index) + _data, false); sendMessage(bytes(1, _index) + _data, false);
return m_output; return m_output;
} }
bytes const& callFunction(byte _index, u256 const& _argument1) template <class... Args>
bytes const& callContractFunction(byte _index, Args const&... _arguments)
{ {
return callFunction(_index, toBigEndian(_argument1)); return callContractFunction(_index, argsToBigEndian(_arguments...));
} }
bool testSolidityAgainstCpp(byte _index, std::function<u256(u256)> const& _cppfun, u256 const& _argument1) template <class CppFunction, class... Args>
void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunction, Args const&... _arguments)
{ {
return toBigEndian(_cppfun(_argument1)) == callFunction(_index, toBigEndian(_argument1)); bytes solidityResult = callContractFunction(_index, _arguments...);
bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...);
BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match."
"\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult));
} }
bool testSolidityAgainstCpp(byte _index, std::function<u256()> const& _cppfun) template <class CppFunction, class... Args>
void testSolidityAgainstCppOnRange(byte _index, CppFunction const& _cppFunction,
u256 const& _rangeStart, u256 const& _rangeEnd)
{ {
return toBigEndian(_cppfun()) == callFunction(_index, bytes()); for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument)
{
bytes solidityResult = callContractFunction(_index, argument);
bytes cppResult = callCppAndEncodeResult(_cppFunction, argument);
BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match."
"\nSolidity: " + toHex(solidityResult) + "\nC++: " + toHex(cppResult) +
"\nArgument: " + toHex(toBigEndian(argument)));
}
} }
private: private:
template <class FirstArg, class... Args>
bytes argsToBigEndian(FirstArg const& _firstArg, Args const&... _followingArgs) const
{
return toBigEndian(_firstArg) + argsToBigEndian(_followingArgs...);
}
bytes argsToBigEndian() const { return bytes(); }
template <class CppFunction, class... Args>
auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
-> typename enable_if<is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type
{
_cppFunction(_arguments...);
return bytes();
}
template <class CppFunction, class... Args>
auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
-> typename enable_if<!is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type
{
return toBigEndian(_cppFunction(_arguments...));
}
void sendMessage(bytes const& _data, bool _isCreation) void sendMessage(bytes const& _data, bool _isCreation)
{ {
eth::Executive executive(m_state); eth::Executive executive(m_state);
@ -91,7 +128,10 @@ private:
BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
} }
else else
{
BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address())); BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address()));
}
BOOST_REQUIRE(executive.go()); BOOST_REQUIRE(executive.go());
executive.finalize(); executive.finalize();
m_output = executive.out().toVector(); m_output = executive.out().toVector();
@ -112,8 +152,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
" function f(uint a) returns(uint d) { return a * 7; }\n" " function f(uint a) returns(uint d) { return a * 7; }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
u256 a = 0x200030004; testSolidityAgainstCppOnRange(0, [](u256 const& a) -> u256 { return a * 7; }, 0, 100);
BOOST_CHECK(callFunction(0, a) == toBigEndian(a * 7));
} }
BOOST_AUTO_TEST_CASE(empty_contract) BOOST_AUTO_TEST_CASE(empty_contract)
@ -121,7 +160,7 @@ BOOST_AUTO_TEST_CASE(empty_contract)
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes()).empty()); BOOST_CHECK(callContractFunction(0, bytes()).empty());
} }
BOOST_AUTO_TEST_CASE(recursive_calls) BOOST_AUTO_TEST_CASE(recursive_calls)
@ -133,7 +172,7 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
std::function<u256(u256)> recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 function<u256(u256)> recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256
{ {
if (n <= 1) if (n <= 1)
return 1; return 1;
@ -141,11 +180,23 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
return n * recursive_calls_cpp(n - 1); return n * recursive_calls_cpp(n - 1);
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(0))); testSolidityAgainstCppOnRange(0, recursive_calls_cpp, 0, 5);
BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(1))); }
BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(2)));
BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(3))); BOOST_AUTO_TEST_CASE(multiple_functions)
BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(4))); {
char const* sourceCode = "contract test {\n"
" function a() returns(uint n) { return 0; }\n"
" function b() returns(uint n) { return 1; }\n"
" function c() returns(uint n) { return 2; }\n"
" function f() returns(uint n) { return 3; }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction(0, bytes()) == toBigEndian(u256(0)));
BOOST_CHECK(callContractFunction(1, bytes()) == toBigEndian(u256(1)));
BOOST_CHECK(callContractFunction(2, bytes()) == toBigEndian(u256(2)));
BOOST_CHECK(callContractFunction(3, bytes()) == toBigEndian(u256(3)));
BOOST_CHECK(callContractFunction(4, bytes()) == bytes());
} }
BOOST_AUTO_TEST_CASE(while_loop) BOOST_AUTO_TEST_CASE(while_loop)
@ -169,11 +220,7 @@ BOOST_AUTO_TEST_CASE(while_loop)
return nfac; return nfac;
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(0))); testSolidityAgainstCppOnRange(0, while_loop_cpp, 0, 5);
BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(1)));
BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(2)));
BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(3)));
BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(4)));
} }
BOOST_AUTO_TEST_CASE(break_outside_loop) BOOST_AUTO_TEST_CASE(break_outside_loop)
@ -184,9 +231,8 @@ BOOST_AUTO_TEST_CASE(break_outside_loop)
" break; continue; return 2;\n" " break; continue; return 2;\n"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); testSolidityAgainstCpp(0, [](u256 const&) -> u256 { return 2; }, u256(0));
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(2)));
} }
BOOST_AUTO_TEST_CASE(nested_loops) BOOST_AUTO_TEST_CASE(nested_loops)
@ -209,8 +255,7 @@ BOOST_AUTO_TEST_CASE(nested_loops)
" return x;\n" " return x;\n"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode);
auto nested_loops_cpp = [](u256 n) -> u256 auto nested_loops_cpp = [](u256 n) -> u256
{ {
@ -236,18 +281,7 @@ BOOST_AUTO_TEST_CASE(nested_loops)
return n; return n;
}; };
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(0))); testSolidityAgainstCppOnRange(0, nested_loops_cpp, 0, 12);
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(1)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(2)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(3)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(4)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(5)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(6)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(7)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(8)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(9)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(10)));
BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(11)));
} }
BOOST_AUTO_TEST_CASE(calling_other_functions) BOOST_AUTO_TEST_CASE(calling_other_functions)
@ -279,7 +313,8 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
return 3 * n + 1; return 3 * n + 1;
}; };
auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp] (u256 n) -> u256 { auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp](u256 n) -> u256
{
u256 y; u256 y;
while ((y = n) > 1) while ((y = n) > 1)
{ {
@ -291,11 +326,11 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
return y; return y;
}; };
BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(0))); testSolidityAgainstCpp(2, collatz_cpp, u256(0));
BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(1))); testSolidityAgainstCpp(2, collatz_cpp, u256(1));
BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(2))); testSolidityAgainstCpp(2, collatz_cpp, u256(2));
BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(8))); testSolidityAgainstCpp(2, collatz_cpp, u256(8));
BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(127))); testSolidityAgainstCpp(2, collatz_cpp, u256(127));
} }
BOOST_AUTO_TEST_CASE(many_local_variables) BOOST_AUTO_TEST_CASE(many_local_variables)
@ -308,8 +343,15 @@ BOOST_AUTO_TEST_CASE(many_local_variables)
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000))) auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256
== toBigEndian(u256(0x121121))); {
u256 a = 0x1;
u256 b = 0x10;
u256 c = 0x100;
u256 y = a + b + c + x1 + x2 + x3;
return y + b + x2;
};
testSolidityAgainstCpp(0, f, u256(0x1000), u256(0x10000), u256(0x100000));
} }
BOOST_AUTO_TEST_CASE(packing_unpacking_types) BOOST_AUTO_TEST_CASE(packing_unpacking_types)
@ -322,7 +364,7 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types)
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) BOOST_CHECK(callContractFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0"))
== fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f"));
} }
@ -334,7 +376,7 @@ BOOST_AUTO_TEST_CASE(multiple_return_values)
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd))) BOOST_CHECK(callContractFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
== toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0))); == toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0)));
} }
@ -354,8 +396,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
return n; return n;
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(0))); testSolidityAgainstCppOnRange(0, short_circuiting_cpp, 0, 2);
BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(1)));
} }
BOOST_AUTO_TEST_CASE(high_bits_cleaning) BOOST_AUTO_TEST_CASE(high_bits_cleaning)
@ -375,7 +416,7 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning)
return 0; return 0;
return x; return x;
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, high_bits_cleaning_cpp)); testSolidityAgainstCpp(0, high_bits_cleaning_cpp);
} }
BOOST_AUTO_TEST_CASE(sign_extension) BOOST_AUTO_TEST_CASE(sign_extension)
@ -395,7 +436,7 @@ BOOST_AUTO_TEST_CASE(sign_extension)
return 0; return 0;
return u256(x) * -1; return u256(x) * -1;
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, sign_extension_cpp)); testSolidityAgainstCpp(0, sign_extension_cpp);
} }
BOOST_AUTO_TEST_CASE(small_unsigned_types) BOOST_AUTO_TEST_CASE(small_unsigned_types)
@ -412,7 +453,7 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types)
uint32_t x = uint32_t(0xffffff) * 0xffffff; uint32_t x = uint32_t(0xffffff) * 0xffffff;
return x / 0x100; return x / 0x100;
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, small_unsigned_types_cpp)); testSolidityAgainstCpp(0, small_unsigned_types_cpp);
} }
BOOST_AUTO_TEST_CASE(small_signed_types) BOOST_AUTO_TEST_CASE(small_signed_types)
@ -427,7 +468,7 @@ BOOST_AUTO_TEST_CASE(small_signed_types)
{ {
return -int32_t(10) * -int64_t(20); return -int32_t(10) * -int64_t(20);
}; };
BOOST_CHECK(testSolidityAgainstCpp(0, small_signed_types_cpp)); testSolidityAgainstCpp(0, small_signed_types_cpp);
} }
BOOST_AUTO_TEST_CASE(state_smoke_test) BOOST_AUTO_TEST_CASE(state_smoke_test)
@ -445,14 +486,14 @@ BOOST_AUTO_TEST_CASE(state_smoke_test)
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0))); BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0)));
BOOST_CHECK(callFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0))); BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0)));
BOOST_CHECK(callFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes()); BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes());
BOOST_CHECK(callFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes()); BOOST_CHECK(callContractFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes());
BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234))); BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234)));
BOOST_CHECK(callFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765))); BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765)));
BOOST_CHECK(callFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes()); BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes());
BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3))); BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3)));
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

214
test/solidityJSONInterfaceTest.cpp

@ -0,0 +1,214 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2014
* Unit tests for the solidity compiler JSON Interface output.
*/
#include <boost/test/unit_test.hpp>
#include <libsolidity/CompilerStack.h>
#include <jsonrpc/json/json.h>
namespace dev
{
namespace solidity
{
namespace test
{
class InterfaceChecker
{
public:
bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
{
m_compilerStack.parse(_code);
std::string generatedInterfaceString = m_compilerStack.getInterface();
Json::Value generatedInterface;
m_reader.parse(generatedInterfaceString, generatedInterface);
Json::Value expectedInterface;
m_reader.parse(_expectedInterfaceString, expectedInterface);
return expectedInterface == generatedInterface;
}
private:
CompilerStack m_compilerStack;
Json::Reader m_reader;
};
BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker)
BOOST_AUTO_TEST_CASE(basic_test)
{
char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
"}\n";
char const* interface = R"([
{
"name": "f",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}
])";
BOOST_CHECK(checkInterface(sourceCode, interface));
}
BOOST_AUTO_TEST_CASE(empty_contract)
{
char const* sourceCode = "contract test {\n"
"}\n";
char const* interface = "[]";
BOOST_CHECK(checkInterface(sourceCode, interface));
}
BOOST_AUTO_TEST_CASE(multiple_methods)
{
char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
" function g(uint b) returns(uint e) { return b * 8; }\n"
"}\n";
char const* interface = R"([
{
"name": "f",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
},
{
"name": "g",
"inputs": [
{
"name": "b",
"type": "uint256"
}
],
"outputs": [
{
"name": "e",
"type": "uint256"
}
]
}
])";
BOOST_CHECK(checkInterface(sourceCode, interface));
}
BOOST_AUTO_TEST_CASE(multiple_params)
{
char const* sourceCode = "contract test {\n"
" function f(uint a, uint b) returns(uint d) { return a + b; }\n"
"}\n";
char const* interface = R"([
{
"name": "f",
"inputs": [
{
"name": "a",
"type": "uint256"
},
{
"name": "b",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}
])";
BOOST_CHECK(checkInterface(sourceCode, interface));
}
BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
// methods are expected to be in alpabetical order
char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n"
" function c(uint b) returns(uint e) { return b * 8; }\n"
"}\n";
char const* interface = R"([
{
"name": "c",
"inputs": [
{
"name": "b",
"type": "uint256"
}
],
"outputs": [
{
"name": "e",
"type": "uint256"
}
]
},
{
"name": "f",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}
])";
BOOST_CHECK(checkInterface(sourceCode, interface));
}
BOOST_AUTO_TEST_SUITE_END()
}
}
}

38
test/stPreCompiledContractsFiller.json

@ -12,7 +12,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -46,7 +46,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -80,7 +80,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -114,7 +114,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", "code": "{ [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -148,7 +148,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -182,7 +182,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -216,7 +216,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -284,7 +284,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ [[ 2 ]] (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -318,7 +318,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -352,7 +352,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -386,7 +386,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -420,7 +420,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -454,7 +454,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -522,7 +522,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ [[ 2 ]] (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -556,7 +556,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -590,7 +590,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -624,7 +624,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -658,7 +658,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@ -692,7 +692,7 @@
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "20000000", "balance" : "20000000",
"nonce" : 0, "nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}",
"storage": {} "storage": {}
}, },
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {

34
test/state.cpp

@ -122,6 +122,40 @@ BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
} }
BOOST_AUTO_TEST_CASE(stCreateTest)
{
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
{
string arg = boost::unit_test::framework::master_test_suite().argv[i];
if (arg == "--createtest")
{
if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
{
cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
return;
}
try
{
cnote << "Populating tests...";
json_spirit::mValue v;
string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
json_spirit::read_string(s, v);
dev::test::doStateTests(v, true);
writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
}
catch (Exception const& _e)
{
BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
}
catch (std::exception const& _e)
{
BOOST_ERROR("Failed state test with Exception: " << _e.what());
}
}
}
}
BOOST_AUTO_TEST_CASE(userDefinedFileState) BOOST_AUTO_TEST_CASE(userDefinedFileState)
{ {
dev::test::userDefinedTest("--statetest", dev::test::doStateTests); dev::test::userDefinedTest("--statetest", dev::test::doStateTests);

6
windows/LibEthereum.vcxproj

@ -342,6 +342,7 @@
<ClInclude Include="..\libethereum\Transaction.h" /> <ClInclude Include="..\libethereum\Transaction.h" />
<ClInclude Include="..\libethereum\TransactionQueue.h" /> <ClInclude Include="..\libethereum\TransactionQueue.h" />
<ClInclude Include="..\libethereum\Utility.h" /> <ClInclude Include="..\libethereum\Utility.h" />
<ClInclude Include="..\libevmcore\Assembly.h" />
<ClInclude Include="..\libevmcore\Exceptions.h" /> <ClInclude Include="..\libevmcore\Exceptions.h" />
<ClInclude Include="..\libevmcore\Instruction.h" /> <ClInclude Include="..\libevmcore\Instruction.h" />
<ClInclude Include="..\libevm\All.h"> <ClInclude Include="..\libevm\All.h">
@ -370,7 +371,6 @@
</ClInclude> </ClInclude>
<ClInclude Include="..\libevm\VMFace.h" /> <ClInclude Include="..\libevm\VMFace.h" />
<ClInclude Include="..\liblll\All.h" /> <ClInclude Include="..\liblll\All.h" />
<ClInclude Include="..\libevmcore\Assembly.h" />
<ClInclude Include="..\liblll\CodeFragment.h" /> <ClInclude Include="..\liblll\CodeFragment.h" />
<ClInclude Include="..\liblll\Compiler.h" /> <ClInclude Include="..\liblll\Compiler.h" />
<ClInclude Include="..\liblll\CompilerState.h" /> <ClInclude Include="..\liblll\CompilerState.h" />
@ -480,25 +480,21 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="LibEthereum.props" /> <Import Project="LibEthereum.props" />
<Import Project="LibEthereum_Debug.props" /> <Import Project="LibEthereum_Debug.props" />
<Import Project="LLVM.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="LibEthereum.props" /> <Import Project="LibEthereum.props" />
<Import Project="LibEthereum_Debug.props" /> <Import Project="LibEthereum_Debug.props" />
<Import Project="LLVM.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="LibEthereum.props" /> <Import Project="LibEthereum.props" />
<Import Project="LibEthereum_Release.props" /> <Import Project="LibEthereum_Release.props" />
<Import Project="LLVM.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="LibEthereum.props" /> <Import Project="LibEthereum.props" />
<Import Project="LibEthereum_Release.props" /> <Import Project="LibEthereum_Release.props" />
<Import Project="LLVM.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />

18
windows/LibEthereum.vcxproj.filters

@ -187,9 +187,6 @@
<ClCompile Include="..\libethcore\Exceptions.cpp"> <ClCompile Include="..\libethcore\Exceptions.cpp">
<Filter>libethcore</Filter> <Filter>libethcore</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\libevm\VMFace.cpp">
<Filter>libevm</Filter>
</ClCompile>
<ClCompile Include="..\libdevcrypto\CryptoPP.cpp"> <ClCompile Include="..\libdevcrypto\CryptoPP.cpp">
<Filter>libdevcrypto</Filter> <Filter>libdevcrypto</Filter>
</ClCompile> </ClCompile>
@ -205,6 +202,9 @@
<ClCompile Include="..\libevmcore\Assembly.cpp"> <ClCompile Include="..\libevmcore\Assembly.cpp">
<Filter>libevmcore</Filter> <Filter>libevmcore</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\libevm\VMFace.cpp">
<Filter>libevm</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
@ -252,9 +252,6 @@
<ClInclude Include="..\liblll\All.h"> <ClInclude Include="..\liblll\All.h">
<Filter>liblll</Filter> <Filter>liblll</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevmcore\Assembly.h">
<Filter>libevmcore</Filter>
</ClInclude>
<ClInclude Include="..\liblll\CodeFragment.h"> <ClInclude Include="..\liblll\CodeFragment.h">
<Filter>liblll</Filter> <Filter>liblll</Filter>
</ClInclude> </ClInclude>
@ -426,9 +423,6 @@
<ClInclude Include="..\libwebthree\webthree.h"> <ClInclude Include="..\libwebthree\webthree.h">
<Filter>libwebthree</Filter> <Filter>libwebthree</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevm\VMFace.h">
<Filter>libevm</Filter>
</ClInclude>
<ClInclude Include="..\libdevcrypto\CryptoPP.h"> <ClInclude Include="..\libdevcrypto\CryptoPP.h">
<Filter>libdevcrypto</Filter> <Filter>libdevcrypto</Filter>
</ClInclude> </ClInclude>
@ -441,9 +435,15 @@
<ClInclude Include="..\libethereum\Account.h"> <ClInclude Include="..\libethereum\Account.h">
<Filter>libethereum</Filter> <Filter>libethereum</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevmcore\Assembly.h">
<Filter>libevmcore</Filter>
</ClInclude>
<ClInclude Include="..\libevmcore\Exceptions.h"> <ClInclude Include="..\libevmcore\Exceptions.h">
<Filter>libevmcore</Filter> <Filter>libevmcore</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevm\VMFace.h">
<Filter>libevm</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Windows"> <Filter Include="Windows">

Loading…
Cancel
Save