Skip to content

Commit

Permalink
Fixing some tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
aarlt committed Feb 21, 2024
1 parent 622e24a commit fdcf92e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 113 deletions.
34 changes: 17 additions & 17 deletions libsolidity/interface/StandardCompiler.cpp
Expand Up @@ -394,7 +394,7 @@ Json collectEVMObject(

std::optional<Json> checkKeys(Json const& _input, std::set<std::string> const& _keys, std::string const& _name)
{
if (!!_input && !_input.is_object())
if (!_input.is_object())
return formatFatalError(Error::Type::JSONError, "\"" + _name + "\" must be an object");

for (auto const& [member, _]: _input.items())
Expand Down Expand Up @@ -513,7 +513,7 @@ std::optional<Json> checkMetadataKeys(Json const& _input)

std::optional<Json> checkOutputSelection(Json const& _outputSelection)
{
if (!!_outputSelection && !_outputSelection.is_object())
if (!_outputSelection.empty() && !_outputSelection.is_object())
return formatFatalError(Error::Type::JSONError, "\"settings.outputSelection\" must be an object");

for (auto const& [sourceName, _]: _outputSelection.items())
Expand Down Expand Up @@ -640,9 +640,9 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
if (auto result = checkRootKeys(_input))
return *result;

ret.language = _input["language"].get<std::string>();
ret.language = _input.value<std::string>("language", "");

Json const& sources = _input["sources"];
Json const& sources = _input.value<Json>("sources", Json());

if (!sources.is_object() && !sources.is_null())
return formatFatalError(Error::Type::JSONError, "\"sources\" is not a JSON object.");
Expand All @@ -661,10 +661,10 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
if (auto result = checkSourceKeys(sources[sourceName], sourceName))
return *result;

if (sources[sourceName]["keccak256"].is_string())
if (sources[sourceName].contains("keccak256") && sources[sourceName]["keccak256"].is_string())
hash = sources[sourceName]["keccak256"].get<std::string>();

if (sources[sourceName]["content"].is_string())
if (sources[sourceName].contains("content") && sources[sourceName]["content"].is_string())
{
std::string content = sources[sourceName]["content"].get<std::string>();
if (!hash.empty() && !hashMatchesContent(hash, content))
Expand Down Expand Up @@ -754,12 +754,12 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
"EVMAssembly import only supports exactly one input file."
);
}
Json const& auxInputs = _input["auxiliaryInput"];
Json const& auxInputs = _input.value("auxiliaryInput", Json::object());

if (auto result = checkAuxiliaryInputKeys(auxInputs))
return *result;

if (!!auxInputs)
if (!auxInputs.empty())
{
Json const& smtlib2Responses = auxInputs["smtlib2responses"];
if (!!smtlib2Responses)
Expand Down Expand Up @@ -790,7 +790,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
}
}

Json const& settings = _input["settings"];
Json const& settings = _input.value("settings", Json::object());

if (auto result = checkSettingsKeys(settings))
return *result;
Expand Down Expand Up @@ -888,7 +888,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
if (settings.contains("remappings") && !settings["remappings"].is_array())
return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings.");

for (auto const& remapping: settings["remappings"])
for (auto const& remapping: settings.value("remappings", Json::array()))
{
if (!remapping.is_string())
return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings");
Expand All @@ -907,7 +907,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
ret.optimiserSettings = std::get<OptimiserSettings>(std::move(optimiserSettings));
}

Json const& jsonLibraries = settings["libraries"];
Json const& jsonLibraries = settings.value("libraries", Json::object());
if (!jsonLibraries.is_object())
return formatFatalError(Error::Type::JSONError, "\"libraries\" is not a JSON object.");
for (auto const& [sourceName, _]: jsonLibraries.items())
Expand Down Expand Up @@ -947,7 +947,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
}
}

Json const& metadataSettings = settings["metadata"];
Json const& metadataSettings = settings.value("metadata", Json::object());

if (auto result = checkMetadataKeys(metadataSettings))
return *result;
Expand All @@ -961,7 +961,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
CompilerStack::defaultMetadataFormat() :
CompilerStack::MetadataFormat::NoMetadata;

ret.metadataLiteralSources = metadataSettings["useLiteralContent"].get<bool>();
ret.metadataLiteralSources = metadataSettings.value("useLiteralContent", false);
if (metadataSettings.contains("bytecodeHash"))
{
auto metadataHash = metadataSettings["bytecodeHash"].get<std::string>();
Expand All @@ -980,7 +980,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
);
}

Json const& outputSelection = settings["outputSelection"];
Json const& outputSelection = settings.value("outputSelection", Json::object());

if (auto jsonError = checkOutputSelection(outputSelection))
return *jsonError;
Expand All @@ -993,7 +993,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json> StandardCompiler::parseI
"Requested output selection conflicts with \"settings.stopAfter\"."
);

Json const& modelCheckerSettings = settings["modelChecker"];
Json const& modelCheckerSettings = settings.value("modelChecker", Json::object());

if (auto result = checkModelCheckerSettingsKeys(modelCheckerSettings))
return *result;
Expand Down Expand Up @@ -1793,9 +1793,9 @@ std::string StandardCompiler::compile(std::string const& _input) noexcept
return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON.\"}]}";
}

// cout << "Input: " << input.toStyledString() << endl;
std::cout << "Input: " << solidity::util::jsonPrettyPrint(input) << std::endl;
Json output = compile(input);
// cout << "Output: " << output.toStyledString() << endl;
std::cout << "Output: " << solidity::util::jsonPrettyPrint(output) << std::endl;

try
{
Expand Down
5 changes: 0 additions & 5 deletions libsolutil/JSON.cpp
Expand Up @@ -22,12 +22,7 @@

#include <libsolutil/JSON.h>

#include <libsolutil/CommonIO.h>

#include <boost/algorithm/string/replace.hpp>

#include <map>
#include <memory>
#include <sstream>

static_assert(
Expand Down
96 changes: 52 additions & 44 deletions test/libsolidity/StandardCompiler.cpp
Expand Up @@ -22,6 +22,7 @@

#include <string>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <libsolidity/interface/OptimiserSettings.h>
#include <libsolidity/interface/StandardCompiler.h>
#include <libsolidity/interface/Version.h>
Expand Down Expand Up @@ -90,7 +91,7 @@ bool containsAtMostWarnings(Json const& _compilerResult)

Json getContractResult(Json const& _compilerResult, std::string const& _file, std::string const& _name)
{
if (
if (!_compilerResult.contains("contracts") ||
!_compilerResult["contracts"].is_object() ||
!_compilerResult["contracts"][_file].is_object() ||
!_compilerResult["contracts"][_file][_name].is_object()
Expand Down Expand Up @@ -167,14 +168,15 @@ BOOST_AUTO_TEST_CASE(assume_object_input)

/// Use the string interface of StandardCompiler to trigger these
result = compile("");
BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 1\n A valid JSON document must be either an array or an object value.\n"));
BOOST_CHECK(containsError(result, "JSONError", "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON"));
result = compile("invalid");
BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 2\n Extra non-whitespace after JSON value.\n"));
std::cout << solidity::util::jsonPrettyPrint(result) << std::endl;

BOOST_CHECK(containsError(result, "JSONError", "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'i'"));
result = compile("\"invalid\"");
BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n A valid JSON document must be either an array or an object value.\n"));
BOOST_CHECK(!containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n"));
BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object."));
result = compile("{}");
BOOST_CHECK(!containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n"));
BOOST_CHECK(containsError(result, "JSONError", "No input sources specified."));
BOOST_CHECK(!containsAtMostWarnings(result));
}

Expand Down Expand Up @@ -263,7 +265,7 @@ BOOST_AUTO_TEST_CASE(unexpected_trailing_test)
}
)";
Json result = compile(input);
BOOST_CHECK(containsError(result, "JSONError", "* Line 10, Column 2\n Extra non-whitespace after JSON value.\n"));
BOOST_CHECK(containsError(result, "JSONError", "[json.exception.parse_error.101] parse error at line 10, column 2: syntax error while parsing value - unexpected '}'; expected end of input"));
}

BOOST_AUTO_TEST_CASE(smoke_test)
Expand Down Expand Up @@ -1227,7 +1229,15 @@ BOOST_AUTO_TEST_CASE(metadata_without_compilation)
{
// NOTE: the contract code here should fail to compile due to "out of stack"
// If the metadata is successfully returned, that means no compilation was attempted.
char const* input = R"(
std::string contractCode = R"(
contract A {
function x(uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h, uint i, uint j, uint k, uint l, uint m, uint n, uint o, uint p) pure public {}
function y() pure public {
uint a; uint b; uint c; uint d; uint e; uint f; uint g; uint h; uint i; uint j; uint k; uint l; uint m; uint n; uint o; uint p;
x(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
}
})";
std::string input = R"(
{
"language": "Solidity",
"settings": {
Expand All @@ -1237,13 +1247,7 @@ BOOST_AUTO_TEST_CASE(metadata_without_compilation)
},
"sources": {
"fileA": {
"content": "contract A {
function x(uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h, uint i, uint j, uint k, uint l, uint m, uint n, uint o, uint p) pure public {}
function y() pure public {
uint a; uint b; uint c; uint d; uint e; uint f; uint g; uint h; uint i; uint j; uint k; uint l; uint m; uint n; uint o; uint p;
x(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
}
}"
"content": )" + Json(contractCode).dump() + R"(
}
}
}
Expand Down Expand Up @@ -1329,7 +1333,36 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization)
{
// NOTE: the contract code here should fail to compile due to "out of stack"
// If we enable stack optimization, though, it will compile.
char const* input = R"(
std::string contractCode = R"(
contract A {
function y() public {
assembly {
function fun() -> a3, b3, c3, d3, e3, f3, g3, h3, i3, j3, k3, l3, m3, n3, o3, p3
{
let a := 1
let b := 1
let z3 := 1
sstore(a, b)
sstore(add(a, 1), b)
sstore(add(a, 2), b)
sstore(add(a, 3), b)
sstore(add(a, 4), b)
sstore(add(a, 5), b)
sstore(add(a, 6), b)
sstore(add(a, 7), b)
sstore(add(a, 8), b)
sstore(add(a, 9), b)
sstore(add(a, 10), b)
sstore(add(a, 11), b)
sstore(add(a, 12), b)
}
let a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1 := fun()
let a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2 := fun()
sstore(a1, a2)
}
}
})";
std::string input = R"(
{
"language": "Solidity",
"settings": {
Expand All @@ -1340,38 +1373,12 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization)
},
"sources": {
"fileA": {
"content": "contract A {
function y() public {
assembly {
function fun() -> a3, b3, c3, d3, e3, f3, g3, h3, i3, j3, k3, l3, m3, n3, o3, p3
{
let a := 1
let b := 1
let z3 := 1
sstore(a, b)
sstore(add(a, 1), b)
sstore(add(a, 2), b)
sstore(add(a, 3), b)
sstore(add(a, 4), b)
sstore(add(a, 5), b)
sstore(add(a, 6), b)
sstore(add(a, 7), b)
sstore(add(a, 8), b)
sstore(add(a, 9), b)
sstore(add(a, 10), b)
sstore(add(a, 11), b)
sstore(add(a, 12), b)
}
let a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1 := fun()
let a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2 := fun()
sstore(a1, a2)
}
}
}"
"content": )" + Json(contractCode).dump() + R"(
}
}
}
)";
std::cout << input << std::endl;

Json parsedInput;
BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput));
Expand Down Expand Up @@ -1682,6 +1689,7 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract)

solidity::frontend::StandardCompiler compiler;
Json result = compiler.compile(parsedInput);
std::cout << util::jsonPrettyPrint(result) << std::endl;

BOOST_REQUIRE(result["contracts"].is_object());
BOOST_REQUIRE(result["contracts"].size() == 1);
Expand Down

0 comments on commit fdcf92e

Please sign in to comment.