aboutsummaryrefslogtreecommitdiffstats
path: root/test/libsolidity/SMTChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/libsolidity/SMTChecker.cpp')
-rw-r--r--test/libsolidity/SMTChecker.cpp154
1 files changed, 141 insertions, 13 deletions
diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp
index 667d666b..8c955292 100644
--- a/test/libsolidity/SMTChecker.cpp
+++ b/test/libsolidity/SMTChecker.cpp
@@ -42,7 +42,7 @@ public:
}
protected:
- virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>>
+ virtual std::pair<SourceUnit const*, ErrorList>
parseAnalyseAndReturnError(
std::string const& _source,
bool _reportWarnings = false,
@@ -94,6 +94,7 @@ BOOST_AUTO_TEST_CASE(warn_on_typecast)
BOOST_AUTO_TEST_CASE(warn_on_struct)
{
string text = R"(
+ pragma experimental ABIEncoderV2;
contract C {
struct A { uint a; uint b; }
function f() public pure returns (A) {
@@ -101,8 +102,10 @@ BOOST_AUTO_TEST_CASE(warn_on_struct)
}
}
)";
- /// Multiple warnings, should check for: Assertion checker does not yet implement this expression.
- CHECK_WARNING_ALLOW_MULTI(text, "");
+ CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{
+ "Assertion checker does not yet implement this expression.",
+ "Assertion checker does not yet support the type of this variable."
+ }));
}
BOOST_AUTO_TEST_CASE(simple_assert)
@@ -167,9 +170,9 @@ BOOST_AUTO_TEST_CASE(function_call_does_not_clear_local_vars)
CHECK_SUCCESS_NO_WARNINGS(text);
}
-BOOST_AUTO_TEST_CASE(branches_clear_variables)
+BOOST_AUTO_TEST_CASE(branches_merge_variables)
{
- // Only clears accessed variables
+ // Branch does not touch variable a
string text = R"(
contract C {
function f(uint x) public pure {
@@ -181,7 +184,7 @@ BOOST_AUTO_TEST_CASE(branches_clear_variables)
}
)";
CHECK_SUCCESS_NO_WARNINGS(text);
- // It is just a plain clear and will not combine branches.
+ // Positive branch touches variable a, but assertion should still hold.
text = R"(
contract C {
function f(uint x) public pure {
@@ -193,8 +196,8 @@ BOOST_AUTO_TEST_CASE(branches_clear_variables)
}
}
)";
- CHECK_WARNING(text, "Assertion violation happens here");
- // Clear also works on the else branch
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ // Negative branch touches variable a, but assertion should still hold.
text = R"(
contract C {
function f(uint x) public pure {
@@ -207,8 +210,8 @@ BOOST_AUTO_TEST_CASE(branches_clear_variables)
}
}
)";
- CHECK_WARNING(text, "Assertion violation happens here");
- // Variable is not cleared, if it is only read.
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ // Variable is not merged, if it is only read.
text = R"(
contract C {
function f(uint x) public pure {
@@ -223,6 +226,36 @@ BOOST_AUTO_TEST_CASE(branches_clear_variables)
}
)";
CHECK_SUCCESS_NO_WARNINGS(text);
+ // Variable is reset in both branches
+ text = R"(
+ contract C {
+ function f(uint x) public pure {
+ uint a = 2;
+ if (x > 10) {
+ a = 3;
+ } else {
+ a = 3;
+ }
+ assert(a == 3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ // Variable is reset in both branches
+ text = R"(
+ contract C {
+ function f(uint x) public pure {
+ uint a = 2;
+ if (x > 10) {
+ a = 3;
+ } else {
+ a = 4;
+ }
+ assert(a >= 3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
}
BOOST_AUTO_TEST_CASE(branches_assert_condition)
@@ -261,7 +294,7 @@ BOOST_AUTO_TEST_CASE(branches_assert_condition)
CHECK_SUCCESS_NO_WARNINGS(text);
}
-BOOST_AUTO_TEST_CASE(ways_to_clear_variables)
+BOOST_AUTO_TEST_CASE(ways_to_merge_variables)
{
string text = R"(
contract C {
@@ -274,6 +307,7 @@ BOOST_AUTO_TEST_CASE(ways_to_clear_variables)
}
}
)";
+ CHECK_WARNING(text, "Assertion violation happens here");
text = R"(
contract C {
function f(uint x) public pure {
@@ -351,9 +385,9 @@ BOOST_AUTO_TEST_CASE(while_loop_simple)
// Check that side-effects of condition are taken into account
text = R"(
contract C {
- function f(uint x) public pure {
+ function f(uint x, uint y) public pure {
x = 7;
- while ((x = 5) > 0) {
+ while ((x = y) > 0) {
}
assert(x == 7);
}
@@ -458,6 +492,100 @@ BOOST_AUTO_TEST_CASE(for_loop)
CHECK_WARNING(text, "Assertion violation");
}
+BOOST_AUTO_TEST_CASE(division)
+{
+ string text = R"(
+ contract C {
+ function f(uint x, uint y) public pure returns (uint) {
+ return x / y;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Division by zero");
+ text = R"(
+ contract C {
+ function f(uint x, uint y) public pure returns (uint) {
+ require(y != 0);
+ return x / y;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(int x, int y) public pure returns (int) {
+ require(y != 0);
+ return x / y;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Overflow");
+ text = R"(
+ contract C {
+ function f(int x, int y) public pure returns (int) {
+ require(y != 0);
+ require(y != -1);
+ return x / y;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(division_truncates_correctly)
+{
+ string text = R"(
+ contract C {
+ function f(uint x, uint y) public pure {
+ x = 7;
+ y = 2;
+ assert(x / y == 3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(int x, int y) public pure {
+ x = 7;
+ y = 2;
+ assert(x / y == 3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(int x, int y) public pure {
+ x = -7;
+ y = 2;
+ assert(x / y == -3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(int x, int y) public pure {
+ x = 7;
+ y = -2;
+ assert(x / y == -3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+ text = R"(
+ contract C {
+ function f(int x, int y) public pure {
+ x = -7;
+ y = -2;
+ assert(x / y == 3);
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}