mirror of
https://github.com/AdaCore/cvc5.git
synced 2026-02-12 12:32:16 -08:00
171 lines
5.9 KiB
C++
171 lines
5.9 KiB
C++
/******************************************************************************
|
|
* Top contributors (to current version):
|
|
* Aina Niemetz, Andrew Reynolds
|
|
*
|
|
* This file is part of the cvc5 project.
|
|
*
|
|
* Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
|
|
* in the top-level source directory and their institutional affiliations.
|
|
* All rights reserved. See the file COPYING in the top-level source
|
|
* directory for licensing information.
|
|
* ****************************************************************************
|
|
*
|
|
* Black box testing of result functions of the C API.
|
|
*/
|
|
|
|
extern "C" {
|
|
#include <cvc5/c/cvc5.h>
|
|
}
|
|
|
|
#include "base/check.h"
|
|
#include "base/output.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace cvc5::internal::test {
|
|
|
|
class TestCApiBlackResult : public ::testing::Test
|
|
{
|
|
protected:
|
|
void SetUp() override
|
|
{
|
|
d_tm = cvc5_term_manager_new();
|
|
d_solver = cvc5_new(d_tm);
|
|
d_bool = cvc5_get_boolean_sort(d_tm);
|
|
d_real = cvc5_get_real_sort(d_tm);
|
|
d_uninterpreted = cvc5_mk_uninterpreted_sort(d_tm, "u");
|
|
}
|
|
void TearDown() override
|
|
{
|
|
cvc5_delete(d_solver);
|
|
cvc5_term_manager_delete(d_tm);
|
|
}
|
|
Cvc5TermManager* d_tm;
|
|
Cvc5* d_solver;
|
|
Cvc5Sort d_bool;
|
|
Cvc5Sort d_real;
|
|
Cvc5Sort d_uninterpreted;
|
|
};
|
|
|
|
TEST_F(TestCApiBlackResult, is_null)
|
|
{
|
|
ASSERT_DEATH(cvc5_result_is_null(nullptr), "invalid result");
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_uninterpreted, "x");
|
|
std::vector<Cvc5Term> args = {x, x};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_EQUAL, args.size(), args.data()));
|
|
Cvc5Result res = cvc5_check_sat(d_solver);
|
|
ASSERT_FALSE(cvc5_result_is_null(res));
|
|
}
|
|
|
|
TEST_F(TestCApiBlackResult, is_equal_disequal)
|
|
{
|
|
cvc5_set_option(d_solver, "incremental", "true");
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_uninterpreted, "x");
|
|
std::vector<Cvc5Term> args = {x, x};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_EQUAL, args.size(), args.data()));
|
|
Cvc5Result res1 = cvc5_check_sat(d_solver);
|
|
cvc5_assert_formula(
|
|
d_solver,
|
|
cvc5_mk_term(d_tm, CVC5_KIND_DISTINCT, args.size(), args.data()));
|
|
Cvc5Result res2 = cvc5_check_sat(d_solver);
|
|
ASSERT_TRUE(cvc5_result_is_equal(res1, res1));
|
|
ASSERT_FALSE(cvc5_result_is_equal(res1, res2));
|
|
ASSERT_FALSE(cvc5_result_is_equal(res1, nullptr));
|
|
ASSERT_FALSE(cvc5_result_is_equal(nullptr, res1));
|
|
ASSERT_FALSE(cvc5_result_is_disequal(res1, res1));
|
|
ASSERT_TRUE(cvc5_result_is_disequal(res1, res2));
|
|
ASSERT_TRUE(cvc5_result_is_disequal(res1, nullptr));
|
|
ASSERT_TRUE(cvc5_result_is_disequal(nullptr, res1));
|
|
}
|
|
|
|
TEST_F(TestCApiBlackResult, is_sat)
|
|
{
|
|
ASSERT_DEATH(cvc5_result_is_sat(nullptr), "invalid result");
|
|
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_uninterpreted, "x");
|
|
std::vector<Cvc5Term> args = {x, x};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_EQUAL, args.size(), args.data()));
|
|
Cvc5Result res = cvc5_check_sat(d_solver);
|
|
ASSERT_TRUE(cvc5_result_is_sat(res));
|
|
ASSERT_FALSE(cvc5_result_is_unsat(res));
|
|
ASSERT_FALSE(cvc5_result_is_unknown(res));
|
|
}
|
|
|
|
TEST_F(TestCApiBlackResult, is_unsat)
|
|
{
|
|
ASSERT_DEATH(cvc5_result_is_unsat(nullptr), "invalid result");
|
|
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_uninterpreted, "x");
|
|
std::vector<Cvc5Term> args = {x, x};
|
|
cvc5_assert_formula(
|
|
d_solver,
|
|
cvc5_mk_term(d_tm, CVC5_KIND_DISTINCT, args.size(), args.data()));
|
|
Cvc5Result res = cvc5_check_sat(d_solver);
|
|
ASSERT_FALSE(cvc5_result_is_sat(res));
|
|
ASSERT_TRUE(cvc5_result_is_unsat(res));
|
|
ASSERT_FALSE(cvc5_result_is_unknown(res));
|
|
}
|
|
|
|
TEST_F(TestCApiBlackResult, is_unknown)
|
|
{
|
|
ASSERT_DEATH(cvc5_result_is_unknown(nullptr), "invalid result");
|
|
|
|
cvc5_set_logic(d_solver, "QF_NIA");
|
|
cvc5_set_option(d_solver, "incremental", "false");
|
|
cvc5_set_option(d_solver, "solve-real-as-int", "true");
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_real, "x");
|
|
std::vector<Cvc5Term> args = {cvc5_mk_real(d_tm, "0.0"), x};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_LT, args.size(), args.data()));
|
|
args = {x, cvc5_mk_real(d_tm, "1.0")};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_LT, args.size(), args.data()));
|
|
Cvc5Result res = cvc5_check_sat(d_solver);
|
|
ASSERT_FALSE(cvc5_result_is_sat(res));
|
|
ASSERT_FALSE(cvc5_result_is_unsat(res));
|
|
ASSERT_TRUE(cvc5_result_is_unknown(res));
|
|
Cvc5UnknownExplanation ue = cvc5_result_get_unknown_explanation(res);
|
|
ASSERT_EQ(ue, CVC5_UNKNOWN_EXPLANATION_INCOMPLETE);
|
|
ASSERT_EQ(cvc5_unknown_explanation_to_string(ue),
|
|
std::string("INCOMPLETE"));
|
|
}
|
|
|
|
TEST_F(TestCApiBlackResult, hash)
|
|
{
|
|
cvc5_set_option(d_solver, "incremental", "true");
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_uninterpreted, "x");
|
|
std::vector<Cvc5Term> args = {x, x};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_EQUAL, args.size(), args.data()));
|
|
Cvc5Result res1 = cvc5_check_sat(d_solver);
|
|
cvc5_assert_formula(
|
|
d_solver,
|
|
cvc5_mk_term(d_tm, CVC5_KIND_DISTINCT, args.size(), args.data()));
|
|
Cvc5Result res2 = cvc5_check_sat(d_solver);
|
|
ASSERT_EQ(cvc5_result_hash(res1), cvc5_result_hash(res1));
|
|
ASSERT_NE(cvc5_result_hash(res1), cvc5_result_hash(res2));
|
|
ASSERT_DEATH(cvc5_result_hash(nullptr), "invalid result");
|
|
}
|
|
|
|
TEST_F(TestCApiBlackResult, copy_release)
|
|
{
|
|
ASSERT_DEATH(cvc5_result_copy(nullptr), "invalid result");
|
|
ASSERT_DEATH(cvc5_result_release(nullptr), "invalid result");
|
|
Cvc5Term x = cvc5_mk_const(d_tm, d_uninterpreted, "x");
|
|
std::vector<Cvc5Term> args = {x, x};
|
|
cvc5_assert_formula(
|
|
d_solver, cvc5_mk_term(d_tm, CVC5_KIND_EQUAL, args.size(), args.data()));
|
|
Cvc5Result res1 = cvc5_check_sat(d_solver);
|
|
Cvc5Result res2 = cvc5_result_copy(res1);
|
|
ASSERT_EQ(cvc5_result_hash(res1), cvc5_result_hash(res2));
|
|
cvc5_result_release(res1);
|
|
ASSERT_EQ(cvc5_result_hash(res1), cvc5_result_hash(res2));
|
|
cvc5_result_release(res1);
|
|
// we cannot reliably check that querying on the (now freed) result fails
|
|
// unless ASAN is enabled
|
|
}
|
|
|
|
} // namespace cvc5::internal::test
|