From a4ef435c07f2dc96864fec116a1dabf355ea2ebb Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 2 Jul 2019 17:30:54 +0200 Subject: [PATCH] Automated ABI Json tests. --- test/InteractiveTests.h | 2 + test/libsolidity/ABIJson/basic_test.sol | 28 + test/libsolidity/ABIJson/constructor_abi.sol | 27 + test/libsolidity/ABIJson/empty_contract.sol | 4 + ...ty_name_input_parameter_with_named_one.sol | 40 + .../ABIJson/empty_name_return_parameters.sol | 30 + test/libsolidity/ABIJson/event_structs.sol | 57 + test/libsolidity/ABIJson/events.sol | 75 ++ test/libsolidity/ABIJson/events_anonymous.sol | 13 + test/libsolidity/ABIJson/function_type.sol | 22 + .../ABIJson/include_fallback_function.sol | 12 + test/libsolidity/ABIJson/inherited.sol | 119 ++ test/libsolidity/ABIJson/library_function.sol | 34 + test/libsolidity/ABIJson/multiple_methods.sol | 50 + .../ABIJson/multiple_methods_order.sol | 51 + test/libsolidity/ABIJson/multiple_params.sol | 32 + .../ABIJson/payabl_fallback_function.sol | 12 + .../ABIJson/payable_constructor_abi.sol | 27 + test/libsolidity/ABIJson/payable_function.sol | 26 + test/libsolidity/ABIJson/pure_function.sol | 54 + .../ABIJson/return_param_in_abi.sol | 40 + test/libsolidity/ABIJson/return_structs.sol | 48 + .../ABIJson/return_structs_with_contracts.sol | 40 + .../ABIJson/structs_and_arrays.sol | 31 + .../ABIJson/structs_in_libraries.sol | 48 + test/libsolidity/ABIJson/view_function.sol | 54 + test/libsolidity/ABIJsonTest.cpp | 103 ++ test/libsolidity/ABIJsonTest.h | 57 + test/libsolidity/SolidityABIJSON.cpp | 1088 ----------------- test/tools/CMakeLists.txt | 1 + 30 files changed, 1137 insertions(+), 1088 deletions(-) create mode 100644 test/libsolidity/ABIJson/basic_test.sol create mode 100644 test/libsolidity/ABIJson/constructor_abi.sol create mode 100644 test/libsolidity/ABIJson/empty_contract.sol create mode 100644 test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol create mode 100644 test/libsolidity/ABIJson/empty_name_return_parameters.sol create mode 100644 test/libsolidity/ABIJson/event_structs.sol create mode 100644 test/libsolidity/ABIJson/events.sol create mode 100644 test/libsolidity/ABIJson/events_anonymous.sol create mode 100644 test/libsolidity/ABIJson/function_type.sol create mode 100644 test/libsolidity/ABIJson/include_fallback_function.sol create mode 100644 test/libsolidity/ABIJson/inherited.sol create mode 100644 test/libsolidity/ABIJson/library_function.sol create mode 100644 test/libsolidity/ABIJson/multiple_methods.sol create mode 100644 test/libsolidity/ABIJson/multiple_methods_order.sol create mode 100644 test/libsolidity/ABIJson/multiple_params.sol create mode 100644 test/libsolidity/ABIJson/payabl_fallback_function.sol create mode 100644 test/libsolidity/ABIJson/payable_constructor_abi.sol create mode 100644 test/libsolidity/ABIJson/payable_function.sol create mode 100644 test/libsolidity/ABIJson/pure_function.sol create mode 100644 test/libsolidity/ABIJson/return_param_in_abi.sol create mode 100644 test/libsolidity/ABIJson/return_structs.sol create mode 100644 test/libsolidity/ABIJson/return_structs_with_contracts.sol create mode 100644 test/libsolidity/ABIJson/structs_and_arrays.sol create mode 100644 test/libsolidity/ABIJson/structs_in_libraries.sol create mode 100644 test/libsolidity/ABIJson/view_function.sol create mode 100644 test/libsolidity/ABIJsonTest.cpp create mode 100644 test/libsolidity/ABIJsonTest.h delete mode 100644 test/libsolidity/SolidityABIJSON.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 3f46558d4..ba0324c47 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include #include @@ -59,6 +60,7 @@ Testsuite const g_interactiveTestsuites[] = { {"Error Recovery", "libsolidity", "errorRecoveryTests", false, false, &SyntaxTest::createErrorRecovery}, {"Semantic", "libsolidity", "semanticTests", false, true, &SemanticTest::create}, {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create}, + {"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create}, {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SyntaxTest::create}, {"SMT Checker JSON", "libsolidity", "smtCheckerTestsJSON", true, false, &SMTCheckerTest::create}, {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create} diff --git a/test/libsolidity/ABIJson/basic_test.sol b/test/libsolidity/ABIJson/basic_test.sol new file mode 100644 index 000000000..8753ef45a --- /dev/null +++ b/test/libsolidity/ABIJson/basic_test.sol @@ -0,0 +1,28 @@ +contract test { + function f(uint a) public returns (uint d) { return a * 7; } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/constructor_abi.sol b/test/libsolidity/ABIJson/constructor_abi.sol new file mode 100644 index 000000000..a311cfcf9 --- /dev/null +++ b/test/libsolidity/ABIJson/constructor_abi.sol @@ -0,0 +1,27 @@ +contract test { + constructor(uint param1, test param2, bool param3) public {} +} +// ---- +// :test +// [ +// { +// "inputs": +// [ +// { +// "name": "param1", +// "type": "uint256" +// }, +// { +// "name": "param2", +// "type": "address" +// }, +// { +// "name": "param3", +// "type": "bool" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "constructor" +// } +// ] diff --git a/test/libsolidity/ABIJson/empty_contract.sol b/test/libsolidity/ABIJson/empty_contract.sol new file mode 100644 index 000000000..4e3951f68 --- /dev/null +++ b/test/libsolidity/ABIJson/empty_contract.sol @@ -0,0 +1,4 @@ +contract test { } +// ---- +// :test +// [] diff --git a/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol b/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol new file mode 100644 index 000000000..530d04a41 --- /dev/null +++ b/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol @@ -0,0 +1,40 @@ +contract test { + function f(uint, uint k) public returns (uint ret_k, uint ret_g) { + uint g = 8; + ret_k = k; + ret_g = g; + } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "", +// "type": "uint256" +// }, +// { +// "name": "k", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "ret_k", +// "type": "uint256" +// }, +// { +// "name": "ret_g", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/empty_name_return_parameters.sol b/test/libsolidity/ABIJson/empty_name_return_parameters.sol new file mode 100644 index 000000000..132c9a629 --- /dev/null +++ b/test/libsolidity/ABIJson/empty_name_return_parameters.sol @@ -0,0 +1,30 @@ +contract test { + function f(uint k) public returns (uint) { + return k; + } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "k", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/event_structs.sol b/test/libsolidity/ABIJson/event_structs.sol new file mode 100644 index 000000000..134b99fce --- /dev/null +++ b/test/libsolidity/ABIJson/event_structs.sol @@ -0,0 +1,57 @@ +pragma experimental ABIEncoderV2; +contract C { + struct S { uint a; T[] sub; bytes b; } + struct T { uint[2] x; } + event E(T t, S s); +} +// ---- +// :C +// [ +// { +// "anonymous": false, +// "inputs": +// [ +// { +// "components": +// [ +// { +// "name": "x", +// "type": "uint256[2]" +// } +// ], +// "indexed": false, +// "name": "t", +// "type": "tuple" +// }, +// { +// "components": +// [ +// { +// "name": "a", +// "type": "uint256" +// }, +// { +// "components": +// [ +// { +// "name": "x", +// "type": "uint256[2]" +// } +// ], +// "name": "sub", +// "type": "tuple[]" +// }, +// { +// "name": "b", +// "type": "bytes" +// } +// ], +// "indexed": false, +// "name": "s", +// "type": "tuple" +// } +// ], +// "name": "E", +// "type": "event" +// } +// ] diff --git a/test/libsolidity/ABIJson/events.sol b/test/libsolidity/ABIJson/events.sol new file mode 100644 index 000000000..822f52f1e --- /dev/null +++ b/test/libsolidity/ABIJson/events.sol @@ -0,0 +1,75 @@ +contract test { + function f(uint a) public returns (uint d) { return a * 7; } + event e1(uint b, address indexed c); + event e2(); + event e2(uint a); + event e3() anonymous; +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "anonymous": false, +// "inputs": +// [ +// { +// "indexed": false, +// "name": "b", +// "type": "uint256" +// }, +// { +// "indexed": true, +// "name": "c", +// "type": "address" +// } +// ], +// "name": "e1", +// "type": "event" +// }, +// { +// "anonymous": false, +// "inputs": [], +// "name": "e2", +// "type": "event" +// }, +// { +// "anonymous": false, +// "inputs": +// [ +// { +// "indexed": false, +// "name": "a", +// "type": "uint256" +// } +// ], +// "name": "e2", +// "type": "event" +// }, +// { +// "anonymous": true, +// "inputs": [], +// "name": "e3", +// "type": "event" +// } +// ] diff --git a/test/libsolidity/ABIJson/events_anonymous.sol b/test/libsolidity/ABIJson/events_anonymous.sol new file mode 100644 index 000000000..0941a8809 --- /dev/null +++ b/test/libsolidity/ABIJson/events_anonymous.sol @@ -0,0 +1,13 @@ +contract test { + event e() anonymous; +} +// ---- +// :test +// [ +// { +// "anonymous": true, +// "inputs": [], +// "name": "e", +// "type": "event" +// } +// ] diff --git a/test/libsolidity/ABIJson/function_type.sol b/test/libsolidity/ABIJson/function_type.sol new file mode 100644 index 000000000..1a18782b6 --- /dev/null +++ b/test/libsolidity/ABIJson/function_type.sol @@ -0,0 +1,22 @@ +contract test { + function g(function(uint) external returns (uint) x) public {} +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "x", +// "type": "function" +// } +// ], +// "name": "g", +// "outputs": [], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/include_fallback_function.sol b/test/libsolidity/ABIJson/include_fallback_function.sol new file mode 100644 index 000000000..f4877ff8b --- /dev/null +++ b/test/libsolidity/ABIJson/include_fallback_function.sol @@ -0,0 +1,12 @@ +contract test { + function() external {} +} +// ---- +// :test +// [ +// { +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "fallback" +// } +// ] diff --git a/test/libsolidity/ABIJson/inherited.sol b/test/libsolidity/ABIJson/inherited.sol new file mode 100644 index 000000000..800475610 --- /dev/null +++ b/test/libsolidity/ABIJson/inherited.sol @@ -0,0 +1,119 @@ +contract Base { + function baseFunction(uint p) public returns (uint i) { return p; } + event baseEvent(bytes32 indexed evtArgBase); +} +contract Derived is Base { + function derivedFunction(bytes32 p) public returns (bytes32 i) { return p; } + event derivedEvent(uint indexed evtArgDerived); +} +// ---- +// :Base +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "p", +// "type": "uint256" +// } +// ], +// "name": "baseFunction", +// "outputs": +// [ +// { +// "name": "i", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "anonymous": false, +// "inputs": +// [ +// { +// "indexed": true, +// "name": "evtArgBase", +// "type": "bytes32" +// } +// ], +// "name": "baseEvent", +// "type": "event" +// } +// ] +// +// +// :Derived +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "p", +// "type": "uint256" +// } +// ], +// "name": "baseFunction", +// "outputs": +// [ +// { +// "name": "i", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "p", +// "type": "bytes32" +// } +// ], +// "name": "derivedFunction", +// "outputs": +// [ +// { +// "name": "i", +// "type": "bytes32" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "anonymous": false, +// "inputs": +// [ +// { +// "indexed": true, +// "name": "evtArgDerived", +// "type": "uint256" +// } +// ], +// "name": "derivedEvent", +// "type": "event" +// }, +// { +// "anonymous": false, +// "inputs": +// [ +// { +// "indexed": true, +// "name": "evtArgBase", +// "type": "bytes32" +// } +// ], +// "name": "baseEvent", +// "type": "event" +// } +// ] diff --git a/test/libsolidity/ABIJson/library_function.sol b/test/libsolidity/ABIJson/library_function.sol new file mode 100644 index 000000000..83df014e9 --- /dev/null +++ b/test/libsolidity/ABIJson/library_function.sol @@ -0,0 +1,34 @@ +library test { + struct StructType { uint a; } + function f(StructType storage b, uint[] storage c, test d) public returns (uint[] memory e, StructType storage f) { f = f; } + function f1(uint[] memory c, test d) public pure returns (uint[] memory e) { } +} +// ---- +// :test +// [ +// { +// "constant": true, +// "inputs": +// [ +// { +// "name": "c", +// "type": "uint256[]" +// }, +// { +// "name": "d", +// "type": "test" +// } +// ], +// "name": "f1", +// "outputs": +// [ +// { +// "name": "e", +// "type": "uint256[]" +// } +// ], +// "payable": false, +// "stateMutability": "pure", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/multiple_methods.sol b/test/libsolidity/ABIJson/multiple_methods.sol new file mode 100644 index 000000000..da664c44c --- /dev/null +++ b/test/libsolidity/ABIJson/multiple_methods.sol @@ -0,0 +1,50 @@ +contract test { + function f(uint a) public returns (uint d) { return a * 7; } + function g(uint b) public returns (uint e) { return b * 8; } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "name": "g", +// "outputs": +// [ +// { +// "name": "e", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/multiple_methods_order.sol b/test/libsolidity/ABIJson/multiple_methods_order.sol new file mode 100644 index 000000000..b4ec583b7 --- /dev/null +++ b/test/libsolidity/ABIJson/multiple_methods_order.sol @@ -0,0 +1,51 @@ +// methods are expected to be in alphabetical order +contract test { + function f(uint a) public returns (uint d) { return a * 7; } + function c(uint b) public returns (uint e) { return b * 8; } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "name": "c", +// "outputs": +// [ +// { +// "name": "e", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/multiple_params.sol b/test/libsolidity/ABIJson/multiple_params.sol new file mode 100644 index 000000000..cd567fba5 --- /dev/null +++ b/test/libsolidity/ABIJson/multiple_params.sol @@ -0,0 +1,32 @@ +contract test { + function f(uint a, uint b) public returns (uint d) { return a + b; } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// }, +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "name": "f", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/payabl_fallback_function.sol b/test/libsolidity/ABIJson/payabl_fallback_function.sol new file mode 100644 index 000000000..a92646a2f --- /dev/null +++ b/test/libsolidity/ABIJson/payabl_fallback_function.sol @@ -0,0 +1,12 @@ +contract test { + function () external payable {} +} +// ---- +// :test +// [ +// { +// "payable": true, +// "stateMutability": "payable", +// "type": "fallback" +// } +// ] diff --git a/test/libsolidity/ABIJson/payable_constructor_abi.sol b/test/libsolidity/ABIJson/payable_constructor_abi.sol new file mode 100644 index 000000000..2b127bc82 --- /dev/null +++ b/test/libsolidity/ABIJson/payable_constructor_abi.sol @@ -0,0 +1,27 @@ +contract test { + constructor(uint param1, test param2, bool param3) public payable {} +} +// ---- +// :test +// [ +// { +// "inputs": +// [ +// { +// "name": "param1", +// "type": "uint256" +// }, +// { +// "name": "param2", +// "type": "address" +// }, +// { +// "name": "param3", +// "type": "bool" +// } +// ], +// "payable": true, +// "stateMutability": "payable", +// "type": "constructor" +// } +// ] diff --git a/test/libsolidity/ABIJson/payable_function.sol b/test/libsolidity/ABIJson/payable_function.sol new file mode 100644 index 000000000..4ed1e02b3 --- /dev/null +++ b/test/libsolidity/ABIJson/payable_function.sol @@ -0,0 +1,26 @@ +contract test { + function f() public {} + function g() public payable {} +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": [], +// "name": "f", +// "outputs": [], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "constant": false, +// "inputs": [], +// "name": "g", +// "outputs": [], +// "payable": true, +// "stateMutability": "payable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/pure_function.sol b/test/libsolidity/ABIJson/pure_function.sol new file mode 100644 index 000000000..21db31727 --- /dev/null +++ b/test/libsolidity/ABIJson/pure_function.sol @@ -0,0 +1,54 @@ +contract test { + function foo(uint a, uint b) public returns (uint d) { return a + b; } + function boo(uint32 a) public pure returns (uint b) { return a * 4; } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// }, +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "name": "foo", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "constant": true, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint32" +// } +// ], +// "name": "boo", +// "outputs": +// [ +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "pure", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/return_param_in_abi.sol b/test/libsolidity/ABIJson/return_param_in_abi.sol new file mode 100644 index 000000000..3c617dfc3 --- /dev/null +++ b/test/libsolidity/ABIJson/return_param_in_abi.sol @@ -0,0 +1,40 @@ +// bug #1801 +contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + constructor(ActionChoices param) public {} + function ret() public returns (ActionChoices) { + ActionChoices action = ActionChoices.GoLeft; + return action; + } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": [], +// "name": "ret", +// "outputs": +// [ +// { +// "name": "", +// "type": "uint8" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "inputs": +// [ +// { +// "name": "param", +// "type": "uint8" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "constructor" +// } +// ] diff --git a/test/libsolidity/ABIJson/return_structs.sol b/test/libsolidity/ABIJson/return_structs.sol new file mode 100644 index 000000000..bb9a0c1d0 --- /dev/null +++ b/test/libsolidity/ABIJson/return_structs.sol @@ -0,0 +1,48 @@ +pragma experimental ABIEncoderV2; +contract C { + struct S { uint a; T[] sub; } + struct T { uint[2] x; } + function f() public returns (uint x, S memory s) { + } +} +// ---- +// :C +// [ +// { +// "constant": false, +// "inputs": [], +// "name": "f", +// "outputs": +// [ +// { +// "name": "x", +// "type": "uint256" +// }, +// { +// "components": +// [ +// { +// "name": "a", +// "type": "uint256" +// }, +// { +// "components": +// [ +// { +// "name": "x", +// "type": "uint256[2]" +// } +// ], +// "name": "sub", +// "type": "tuple[]" +// } +// ], +// "name": "s", +// "type": "tuple" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/return_structs_with_contracts.sol b/test/libsolidity/ABIJson/return_structs_with_contracts.sol new file mode 100644 index 000000000..ce957f1c3 --- /dev/null +++ b/test/libsolidity/ABIJson/return_structs_with_contracts.sol @@ -0,0 +1,40 @@ +pragma experimental ABIEncoderV2; +contract C { + struct S { C[] x; C y; } + function f() public returns (S memory s, C c) { + } +} +// ---- +// :C +// [ +// { +// "constant": false, +// "inputs": [], +// "name": "f", +// "outputs": +// [ +// { +// "components": +// [ +// { +// "name": "x", +// "type": "address[]" +// }, +// { +// "name": "y", +// "type": "address" +// } +// ], +// "name": "s", +// "type": "tuple" +// }, +// { +// "name": "c", +// "type": "address" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/structs_and_arrays.sol b/test/libsolidity/ABIJson/structs_and_arrays.sol new file mode 100644 index 000000000..4474b98f7 --- /dev/null +++ b/test/libsolidity/ABIJson/structs_and_arrays.sol @@ -0,0 +1,31 @@ +// bug #1801 +contract test { + function f(string calldata a, bytes calldata b, uint[] calldata c) external {} +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "string" +// }, +// { +// "name": "b", +// "type": "bytes" +// }, +// { +// "name": "c", +// "type": "uint256[]" +// } +// ], +// "name": "f", +// "outputs": [], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/structs_in_libraries.sol b/test/libsolidity/ABIJson/structs_in_libraries.sol new file mode 100644 index 000000000..29a709f81 --- /dev/null +++ b/test/libsolidity/ABIJson/structs_in_libraries.sol @@ -0,0 +1,48 @@ +pragma experimental ABIEncoderV2; +library L { + struct S { uint a; T[] sub; bytes b; } + struct T { uint[2] x; } + function f(L.S storage s) public view {} + function g(L.S memory s) public view {} +} +// ---- +// :L +// [ +// { +// "constant": true, +// "inputs": +// [ +// { +// "components": +// [ +// { +// "name": "a", +// "type": "uint256" +// }, +// { +// "components": +// [ +// { +// "name": "x", +// "type": "uint256[2]" +// } +// ], +// "name": "sub", +// "type": "tuple[]" +// }, +// { +// "name": "b", +// "type": "bytes" +// } +// ], +// "name": "s", +// "type": "tuple" +// } +// ], +// "name": "g", +// "outputs": [], +// "payable": false, +// "stateMutability": "view", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJson/view_function.sol b/test/libsolidity/ABIJson/view_function.sol new file mode 100644 index 000000000..6f731a09c --- /dev/null +++ b/test/libsolidity/ABIJson/view_function.sol @@ -0,0 +1,54 @@ +contract test { + function foo(uint a, uint b) public returns (uint d) { return a + b; } + function boo(uint32 a) public view returns(uint b) { return a * 4; } +} +// ---- +// :test +// [ +// { +// "constant": false, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint256" +// }, +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "name": "foo", +// "outputs": +// [ +// { +// "name": "d", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "nonpayable", +// "type": "function" +// }, +// { +// "constant": true, +// "inputs": +// [ +// { +// "name": "a", +// "type": "uint32" +// } +// ], +// "name": "boo", +// "outputs": +// [ +// { +// "name": "b", +// "type": "uint256" +// } +// ], +// "payable": false, +// "stateMutability": "view", +// "type": "function" +// } +// ] diff --git a/test/libsolidity/ABIJsonTest.cpp b/test/libsolidity/ABIJsonTest.cpp new file mode 100644 index 000000000..a5b9d7ba8 --- /dev/null +++ b/test/libsolidity/ABIJsonTest.cpp @@ -0,0 +1,103 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see . + */ +/** + * Unit tests for the solidity compiler ABI JSON Interface output. + */ + +#include + +#include + +#include +#include +#include + +#include + +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; +using namespace dev::solidity::test; + +ABIJsonTest::ABIJsonTest(string const& _filename) +{ + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test contract: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + m_source = parseSourceAndSettings(file); + m_expectation = parseSimpleExpectations(file); +} + +TestCase::TestResult ABIJsonTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) +{ + CompilerStack compiler; + + compiler.setSources({{"", "pragma solidity >=0.0;\n" + m_source}}); + compiler.setEVMVersion(dev::test::Options::get().evmVersion()); + compiler.setOptimiserSettings(dev::test::Options::get().optimize); + if (!compiler.parseAndAnalyze()) + BOOST_THROW_EXCEPTION(runtime_error("Parsing contract failed")); + + m_obtainedResult.clear(); + bool first = true; + for (string const& contractName: compiler.contractNames()) + { + if (!first) + m_obtainedResult += "\n\n"; + m_obtainedResult += " " + contractName + "\n"; + m_obtainedResult += jsonPrettyPrint(compiler.contractABI(contractName)) + "\n"; + first = false; + } + if (m_expectation != m_obtainedResult) + { + string nextIndentLevel = _linePrefix + " "; + AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Expected result:" << endl; + printIndented(_stream, m_expectation, nextIndentLevel); + AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Obtained result:" << endl; + printIndented(_stream, m_obtainedResult, nextIndentLevel); + return TestResult::Failure; + } + return TestResult::Success; +} + + +void ABIJsonTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + printIndented(_stream, m_source, _linePrefix); +} + +void ABIJsonTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +{ + printIndented(_stream, m_obtainedResult, _linePrefix); +} + +void ABIJsonTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const +{ + stringstream output(_output); + string line; + while (getline(output, line)) + if (line.empty()) + // Avoid trailing spaces. + _stream << boost::trim_right_copy(_linePrefix) << endl; + else + _stream << _linePrefix << line << endl; +} + diff --git a/test/libsolidity/ABIJsonTest.h b/test/libsolidity/ABIJsonTest.h new file mode 100644 index 000000000..e7be7947f --- /dev/null +++ b/test/libsolidity/ABIJsonTest.h @@ -0,0 +1,57 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see . +*/ +/** + * Unit tests for the solidity compiler ABI JSON Interface output. + */ + +#pragma once + +#include + +#include + +namespace dev +{ +namespace solidity +{ +namespace test +{ + + +class ABIJsonTest: public TestCase +{ +public: + static std::unique_ptr create(Config const& _config) + { return std::unique_ptr(new ABIJsonTest(_config.filename)); } + ABIJsonTest(std::string const& _filename); + + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + + void printSource(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) const override; + void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; + +private: + void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const; + + std::string m_source; + std::string m_expectation; + std::string m_obtainedResult; +}; + +} +} +} diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp deleted file mode 100644 index 7905d0b37..000000000 --- a/test/libsolidity/SolidityABIJSON.cpp +++ /dev/null @@ -1,1088 +0,0 @@ -/* - This file is part of solidity. - - solidity 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. - - solidity 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 solidity. If not, see . - */ -/** - * @author Marek Kotewicz - * @date 2014 - * Unit tests for the solidity compiler JSON Interface output. - */ - -#include -#include - -#include -#include - -#include - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -class JSONInterfaceChecker -{ -public: - void checkInterface(std::string const& _code, std::string const& _contractName, std::string const& _expectedInterfaceString) - { - m_compilerStack.reset(); - m_compilerStack.setSources({{"", "pragma solidity >=0.0;\n" + _code}}); - m_compilerStack.setEVMVersion(dev::test::Options::get().evmVersion()); - m_compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); - BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); - - Json::Value generatedInterface = m_compilerStack.contractABI(_contractName); - Json::Value expectedInterface; - BOOST_REQUIRE(jsonParseStrict(_expectedInterfaceString, expectedInterface)); - BOOST_CHECK_MESSAGE( - expectedInterface == generatedInterface, - "Expected:\n" << expectedInterface.toStyledString() << - "\n but got:\n" << generatedInterface.toStyledString() - ); - } - -protected: - CompilerStack m_compilerStack; -}; - -BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, JSONInterfaceChecker) - -BOOST_AUTO_TEST_CASE(basic_test) -{ - char const* sourceCode = R"( - contract test { - function f(uint a) public returns (uint d) { return a * 7; } - } - )"; - - char const* interface = R"([ - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(empty_contract) -{ - char const* sourceCode = R"( - contract test { } - )"; - char const* interface = "[]"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(multiple_methods) -{ - char const* sourceCode = R"( - contract test { - function f(uint a) public returns (uint d) { return a * 7; } - function g(uint b) public returns (uint e) { return b * 8; } - } - )"; - - char const* interface = R"([ - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - }, - { - "name": "g", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "b", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "e", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(multiple_params) -{ - char const* sourceCode = R"( - contract test { - function f(uint a, uint b) public returns (uint d) { return a + b; } - } - )"; - - char const* interface = R"([ - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(multiple_methods_order) -{ - // methods are expected to be in alphabetical order - char const* sourceCode = R"( - contract test { - function f(uint a) public returns (uint d) { return a * 7; } - function c(uint b) public returns (uint e) { return b * 8; } - } - )"; - - char const* interface = R"([ - { - "name": "c", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "b", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "e", - "type": "uint256" - } - ] - }, - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(view_function) -{ - char const* sourceCode = R"( - contract test { - function foo(uint a, uint b) public returns (uint d) { return a + b; } - function boo(uint32 a) public view returns(uint b) { return a * 4; } - } - )"; - - char const* interface = R"([ - { - "name": "foo", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - }, - { - "name": "boo", - "constant": true, - "payable" : false, - "stateMutability": "view", - "type": "function", - "inputs": [{ - "name": "a", - "type": "uint32" - }], - "outputs": [ - { - "name": "b", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(pure_function) -{ - char const* sourceCode = R"( - contract test { - function foo(uint a, uint b) public returns (uint d) { return a + b; } - function boo(uint32 a) public pure returns (uint b) { return a * 4; } - } - )"; - - char const* interface = R"([ - { - "name": "foo", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - }, - { - "name": "boo", - "constant": true, - "payable" : false, - "stateMutability": "pure", - "type": "function", - "inputs": [{ - "name": "a", - "type": "uint32" - }], - "outputs": [ - { - "name": "b", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(events) -{ - char const* sourceCode = R"( - contract test { - function f(uint a) public returns (uint d) { return a * 7; } - event e1(uint b, address indexed c); - event e2(); - event e2(uint a); - event e3() anonymous; - } - )"; - char const* interface = R"([ - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] - }, - { - "name": "e1", - "type": "event", - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "b", - "type": "uint256" - }, - { - "indexed": true, - "name": "c", - "type": "address" - } - ] - }, - { - "name": "e2", - "type": "event", - "anonymous": false, - "inputs": [] - }, - { - "name": "e2", - "type": "event", - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "a", - "type": "uint256" - } - ] - }, - { - "name": "e3", - "type": "event", - "anonymous": true, - "inputs": [] - } - - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(events_anonymous) -{ - char const* sourceCode = R"( - contract test { - event e() anonymous; - } - )"; - char const* interface = R"([ - { - "name": "e", - "type": "event", - "anonymous": true, - "inputs": [] - } - - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(inherited) -{ - char const* sourceCode = R"( - contract Base { - function baseFunction(uint p) public returns (uint i) { return p; } - event baseEvent(bytes32 indexed evtArgBase); - } - contract Derived is Base { - function derivedFunction(bytes32 p) public returns (bytes32 i) { return p; } - event derivedEvent(uint indexed evtArgDerived); - } - )"; - - char const* interface = R"([ - { - "name": "baseFunction", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": - [{ - "name": "p", - "type": "uint256" - }], - "outputs": - [{ - "name": "i", - "type": "uint256" - }] - }, - { - "name": "derivedFunction", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": - [{ - "name": "p", - "type": "bytes32" - }], - "outputs": - [{ - "name": "i", - "type": "bytes32" - }] - }, - { - "name": "derivedEvent", - "type": "event", - "anonymous": false, - "inputs": - [{ - "indexed": true, - "name": "evtArgDerived", - "type": "uint256" - }] - }, - { - "name": "baseEvent", - "type": "event", - "anonymous": false, - "inputs": - [{ - "indexed": true, - "name": "evtArgBase", - "type": "bytes32" - }] - }])"; - - - checkInterface(sourceCode, "Derived", interface); -} -BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) -{ - char const* sourceCode = R"( - contract test { - function f(uint, uint k) public returns (uint ret_k, uint ret_g) { - uint g = 8; - ret_k = k; - ret_g = g; - } - } - )"; - - char const* interface = R"([ - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "k", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "ret_k", - "type": "uint256" - }, - { - "name": "ret_g", - "type": "uint256" - } - ] - } - ])"; - - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(empty_name_return_parameter) -{ - char const* sourceCode = R"( - contract test { - function f(uint k) public returns (uint) { - return k; - } - } - )"; - - char const* interface = R"([ - { - "name": "f", - "constant": false, - "payable" : false, - "stateMutability": "nonpayable", - "type": "function", - "inputs": [ - { - "name": "k", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256" - } - ] - } - ])"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(constructor_abi) -{ - char const* sourceCode = R"( - contract test { - constructor(uint param1, test param2, bool param3) public {} - } - )"; - - char const* interface = R"([ - { - "inputs": [ - { - "name": "param1", - "type": "uint256" - }, - { - "name": "param2", - "type": "address" - }, - { - "name": "param3", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - } - ])"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(payable_constructor_abi) -{ - char const* sourceCode = R"( - contract test { - constructor(uint param1, test param2, bool param3) public payable {} - } - )"; - - char const* interface = R"([ - { - "inputs": [ - { - "name": "param1", - "type": "uint256" - }, - { - "name": "param2", - "type": "address" - }, - { - "name": "param3", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "constructor" - } - ])"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(return_param_in_abi) -{ - // bug #1801 - char const* sourceCode = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - constructor(ActionChoices param) public {} - function ret() public returns (ActionChoices) { - ActionChoices action = ActionChoices.GoLeft; - return action; - } - } - )"; - - char const* interface = R"( - [ - { - "constant" : false, - "payable" : false, - "stateMutability": "nonpayable", - "inputs" : [], - "name" : "ret", - "outputs" : [ - { - "name" : "", - "type" : "uint8" - } - ], - "type" : "function" - }, - { - "inputs": [ - { - "name": "param", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(strings_and_arrays) -{ - // bug #1801 - char const* sourceCode = R"( - contract test { - function f(string calldata a, bytes calldata b, uint[] calldata c) external {} - } - )"; - - char const* interface = R"( - [ - { - "constant" : false, - "payable" : false, - "stateMutability": "nonpayable", - "name": "f", - "inputs": [ - { "name": "a", "type": "string" }, - { "name": "b", "type": "bytes" }, - { "name": "c", "type": "uint256[]" } - ], - "outputs": [], - "type" : "function" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(library_function) -{ - char const* sourceCode = R"( - library test { - struct StructType { uint a; } - function f(StructType storage b, uint[] storage c, test d) public returns (uint[] memory e, StructType storage f) { f = f; } - function f1(uint[] memory c, test d) public pure returns (uint[] memory e) { } - } - )"; - - char const* interface = R"( - [ - { - "constant" : true, - "payable" : false, - "stateMutability": "pure", - "name": "f1", - "inputs": [ - { "name": "c", "type": "uint256[]" }, - { "name": "d", "type": "test" } - ], - "outputs": [ - { "name": "e", "type": "uint256[]" } - ], - "type" : "function" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(include_fallback_function) -{ - char const* sourceCode = R"( - contract test { - function() external {} - } - )"; - - char const* interface = R"( - [ - { - "payable": false, - "stateMutability": "nonpayable", - "type" : "fallback" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(payable_function) -{ - char const* sourceCode = R"( - contract test { - function f() public {} - function g() public payable {} - } - )"; - - char const* interface = R"( - [ - { - "constant" : false, - "payable": false, - "stateMutability": "nonpayable", - "inputs": [], - "name": "f", - "outputs": [], - "type" : "function" - }, - { - "constant" : false, - "payable": true, - "stateMutability": "payable", - "inputs": [], - "name": "g", - "outputs": [], - "type" : "function" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(payable_fallback_function) -{ - char const* sourceCode = R"( - contract test { - function () external payable {} - } - )"; - - char const* interface = R"( - [ - { - "payable": true, - "stateMutability": "payable", - "type" : "fallback" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(function_type) -{ - char const* sourceCode = R"( - contract test { - function g(function(uint) external returns (uint) x) public {} - } - )"; - - char const* interface = R"( - [ - { - "constant" : false, - "payable": false, - "stateMutability": "nonpayable", - "inputs": [{ - "name": "x", - "type": "function" - }], - "name": "g", - "outputs": [], - "type" : "function" - } - ] - )"; - checkInterface(sourceCode, "test", interface); -} - -BOOST_AUTO_TEST_CASE(return_structs) -{ - char const* sourceCode = R"( - pragma experimental ABIEncoderV2; - contract C { - struct S { uint a; T[] sub; } - struct T { uint[2] x; } - function f() public returns (uint x, S memory s) { - } - } - )"; - char const* interface = R"( - [{ - "constant" : false, - "inputs" : [], - "name" : "f", - "outputs" : [ - { - "name" : "x", - "type" : "uint256" - }, - { - "components" : [ - { - "name" : "a", - "type" : "uint256" - }, - { - "components" : [ - { - "name" : "x", - "type" : "uint256[2]" - } - ], - "name" : "sub", - "type" : "tuple[]" - } - ], - "name" : "s", - "type" : "tuple" - } - ], - "payable" : false, - "stateMutability" : "nonpayable", - "type" : "function" - }] - )"; - checkInterface(sourceCode, "C", interface); -} - -BOOST_AUTO_TEST_CASE(return_structs_with_contracts) -{ - char const* sourceCode = R"( - pragma experimental ABIEncoderV2; - contract C { - struct S { C[] x; C y; } - function f() public returns (S memory s, C c) { - } - } - )"; - char const* interface = R"( - [{ - "constant": false, - "inputs": [], - "name": "f", - "outputs": [ - { - "components": [ - { - "name": "x", - "type": "address[]" - }, - { - "name": "y", - "type": "address" - } - ], - "name": "s", - "type": "tuple" - }, - { - "name": "c", - "type": "address" - } - ], - "payable": false, - "stateMutability" : "nonpayable", - "type": "function" - }] - )"; - checkInterface(sourceCode, "C", interface); -} - -BOOST_AUTO_TEST_CASE(event_structs) -{ - char const* sourceCode = R"( - pragma experimental ABIEncoderV2; - contract C { - struct S { uint a; T[] sub; bytes b; } - struct T { uint[2] x; } - event E(T t, S s); - } - )"; - char const *interface = R"( - [{ - "anonymous": false, - "inputs": [ - { - "components": [ - { - "name": "x", - "type": "uint256[2]" - } - ], - "indexed": false, - "name": "t", - "type": "tuple" - }, - { - "components": [ - { - "name": "a", - "type": "uint256" - }, - { - "components": [ - { - "name": "x", - "type": "uint256[2]" - } - ], - "name": "sub", - "type": "tuple[]" - }, - { - "name": "b", - "type": "bytes" - } - ], - "indexed": false, - "name": "s", - "type": "tuple" - } - ], - "name": "E", - "type": "event" - }] - )"; - checkInterface(sourceCode, "C", interface); -} - -BOOST_AUTO_TEST_CASE(structs_in_libraries) -{ - char const* sourceCode = R"( - pragma experimental ABIEncoderV2; - library L { - struct S { uint a; T[] sub; bytes b; } - struct T { uint[2] x; } - function f(L.S storage s) public view {} - function g(L.S memory s) public view {} - } - )"; - char const* interface = R"( - [{ - "constant": true, - "inputs": [ - { - "components": [ - { - "name": "a", - "type": "uint256" - }, - { - "components": [ - { - "name": "x", - "type": "uint256[2]" - } - ], - "name": "sub", - "type": "tuple[]" - }, - { - "name": "b", - "type": "bytes" - } - ], - "name": "s", - "type": "tuple" - } - ], - "name": "g", - "outputs": [], - "payable": false, - "stateMutability": "view", - "type": "function" - }])"; - checkInterface(sourceCode, "L", interface); -} - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index b9e72d27b..df8d2f10c 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(isoltest ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp ../RPCSession.cpp + ../libsolidity/ABIJsonTest.cpp ../libsolidity/ASTJSONTest.cpp ../libsolidity/SMTCheckerJSONTest.cpp ../libyul/ObjectCompilerTest.cpp