/* 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 . */ #include #include using namespace std; using namespace solidity::smtutil; namespace solidity::smtutil::test { BOOST_AUTO_TEST_SUITE(DLSolverTest) BOOST_AUTO_TEST_CASE(test_empty_sat) { DLSolver solver; auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_CASE(test_basic_sat) { DLSolver solver; Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression k2{"2", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.addAssertion(a - b <= k2); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_sat) { DLSolver solver; // a <= b -> a - b <= 0 // b <= c -> b - c <= 0 // c <= a -> c - a <= 0 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k0{"0", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k0); solver.addAssertion(b - c <= k0); solver.addAssertion(c - a <= k0); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_CASE(test_basic_unsat) { DLSolver solver; // a <= b -> a - b <= 0 // b < a -> b - a < 0 -> b - a <= -1 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression k0{"0", {}, SortProvider::sintSort}; Expression kMinus1{"-1", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.addAssertion(a - b <= k0); solver.addAssertion(b - a <= kMinus1); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::UNSATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_unsat) { DLSolver solver; // a <= b -> a - b <= 0 // b <= c -> b - c <= 0 // c < a -> c - a < 0 -> c - a <= -1 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k0{"0", {}, SortProvider::sintSort}; Expression kMinus1{"-1", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k0); solver.addAssertion(b - c <= k0); solver.addAssertion(c - a <= kMinus1); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::UNSATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_unsat_reset_sat) { DLSolver solver; // a <= b -> a - b <= 0 // b <= c -> b - c <= 0 // c < a -> c - a < 0 -> c - a <= -1 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k0{"0", {}, SortProvider::sintSort}; Expression kMinus1{"-1", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k0); solver.addAssertion(b - c <= k0); solver.addAssertion(c - a <= kMinus1); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::UNSATISFIABLE); solver.reset(); auto [res2, model2] = solver.check({}); BOOST_CHECK(res2 == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_incremental) { DLSolver solver; // a <= b -> a - b <= 0 // b <= c -> b - c <= 0 // c < a -> c - a < 0 -> c - a <= -1 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k0{"0", {}, SortProvider::sintSort}; Expression kMinus1{"-1", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k0); solver.addAssertion(b - c <= k0); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::SATISFIABLE); solver.push(); solver.addAssertion(c - a <= kMinus1); auto [res2, model2] = solver.check({}); BOOST_CHECK(res2 == CheckResult::UNSATISFIABLE); solver.pop(); auto [res3, model3] = solver.check({}); BOOST_CHECK(res3 == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_complex) { DLSolver solver; // a−b ≤ 2, b−c ≤ 3, c−a ≤ −7 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k2{"2", {}, SortProvider::sintSort}; Expression k3{"3", {}, SortProvider::sintSort}; Expression kMinus7{"-7", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k2); solver.addAssertion(b - c <= k3); solver.addAssertion(c - a <= kMinus7); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::UNSATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_complex2) { DLSolver solver; // a−b ≤ 2, b−c ≤ 10, c−a ≤ −7 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k2{"2", {}, SortProvider::sintSort}; Expression k10{"10", {}, SortProvider::sintSort}; Expression kMinus7{"-7", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k2); solver.addAssertion(b - c <= k10); solver.addAssertion(c - a <= kMinus7); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_CASE(test_triangle_complex2_incremental) { DLSolver solver; // a−b ≤ 2, b−c ≤ 10, c−a ≤ −7 Expression a{"a", {}, SortProvider::sintSort}; Expression b{"b", {}, SortProvider::sintSort}; Expression c{"c", {}, SortProvider::sintSort}; Expression k2{"2", {}, SortProvider::sintSort}; Expression k3{"3", {}, SortProvider::sintSort}; Expression k10{"10", {}, SortProvider::sintSort}; Expression kMinus7{"-7", {}, SortProvider::sintSort}; solver.declareVariable(a.name, a.sort); solver.declareVariable(b.name, b.sort); solver.declareVariable(c.name, c.sort); solver.addAssertion(a - b <= k2); solver.addAssertion(c - a <= kMinus7); auto [res, model] = solver.check({}); BOOST_CHECK(res == CheckResult::SATISFIABLE); solver.push(); solver.addAssertion(b - c <= k3); auto [res2, model2] = solver.check({}); BOOST_CHECK(res2 == CheckResult::UNSATISFIABLE); solver.pop(); solver.addAssertion(b - c <= k10); auto [res3, model3] = solver.check({}); BOOST_CHECK(res3 == CheckResult::SATISFIABLE); } BOOST_AUTO_TEST_SUITE_END() } // end namespaces