/****************************************************************************** * Top contributors (to current version): * Aina Niemetz, Gereon Kremer, 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 the Term class. */ #include "test_api.h" namespace cvc5::internal { namespace test { class TestApiBlackTerm : public TestApi { }; TEST_F(TestApiBlackTerm, equalHash) { Sort uSort = d_tm.mkUninterpretedSort("u"); Term x = d_tm.mkVar(uSort, "x"); Term y = d_tm.mkVar(uSort, "y"); Term z; ASSERT_TRUE(x == x); ASSERT_FALSE(x != x); ASSERT_FALSE(x == y); ASSERT_TRUE(x != y); ASSERT_FALSE((x == z)); ASSERT_TRUE(x != z); ASSERT_EQ(std::hash{}(x), std::hash{}(x)); ASSERT_NE(std::hash{}(x), std::hash{}(y)); (void)std::hash{}(Term()); } TEST_F(TestApiBlackTerm, getId) { Term n; ASSERT_THROW(n.getId(), CVC5ApiException); Term x = d_tm.mkVar(d_tm.getIntegerSort(), "x"); ASSERT_NO_THROW(x.getId()); Term y = x; ASSERT_EQ(x.getId(), y.getId()); Term z = d_tm.mkVar(d_tm.getIntegerSort(), "z"); ASSERT_NE(x.getId(), z.getId()); } TEST_F(TestApiBlackTerm, getKind) { Sort uSort = d_tm.mkUninterpretedSort("u"); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({uSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term n; ASSERT_THROW(n.getKind(), CVC5ApiException); Term x = d_tm.mkVar(uSort, "x"); ASSERT_NO_THROW(x.getKind()); Term y = d_tm.mkVar(uSort, "y"); ASSERT_NO_THROW(y.getKind()); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_NO_THROW(f.getKind()); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_NO_THROW(p.getKind()); Term zero = d_tm.mkInteger(0); ASSERT_NO_THROW(zero.getKind()); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_NO_THROW(f_x.getKind()); Term f_y = d_tm.mkTerm(Kind::APPLY_UF, {f, y}); ASSERT_NO_THROW(f_y.getKind()); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_y}); ASSERT_NO_THROW(sum.getKind()); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.getKind()); Term p_f_y = d_tm.mkTerm(Kind::APPLY_UF, {p, f_y}); ASSERT_NO_THROW(p_f_y.getKind()); // Sequence kinds do not exist internally, test that the API properly // converts them back. Sort seqSort = d_tm.mkSequenceSort(intSort); Term s = d_tm.mkConst(seqSort, "s"); Term ss = d_tm.mkTerm(Kind::SEQ_CONCAT, {s, s}); ASSERT_EQ(ss.getKind(), Kind::SEQ_CONCAT); } TEST_F(TestApiBlackTerm, getSort) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term n; ASSERT_THROW(n.getSort(), CVC5ApiException); Term x = d_tm.mkVar(bvSort, "x"); ASSERT_NO_THROW(x.getSort()); ASSERT_EQ(x.getSort(), bvSort); Term y = d_tm.mkVar(bvSort, "y"); ASSERT_NO_THROW(y.getSort()); ASSERT_EQ(y.getSort(), bvSort); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_NO_THROW(f.getSort()); ASSERT_EQ(f.getSort(), funSort1); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_NO_THROW(p.getSort()); ASSERT_EQ(p.getSort(), funSort2); Term zero = d_tm.mkInteger(0); ASSERT_NO_THROW(zero.getSort()); ASSERT_EQ(zero.getSort(), intSort); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_NO_THROW(f_x.getSort()); ASSERT_EQ(f_x.getSort(), intSort); Term f_y = d_tm.mkTerm(Kind::APPLY_UF, {f, y}); ASSERT_NO_THROW(f_y.getSort()); ASSERT_EQ(f_y.getSort(), intSort); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_y}); ASSERT_NO_THROW(sum.getSort()); ASSERT_EQ(sum.getSort(), intSort); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.getSort()); ASSERT_EQ(p_0.getSort(), boolSort); Term p_f_y = d_tm.mkTerm(Kind::APPLY_UF, {p, f_y}); ASSERT_NO_THROW(p_f_y.getSort()); ASSERT_EQ(p_f_y.getSort(), boolSort); } TEST_F(TestApiBlackTerm, getOp) { Sort intsort = d_tm.getIntegerSort(); Sort bvsort = d_tm.mkBitVectorSort(8); Sort arrsort = d_tm.mkArraySort(bvsort, intsort); Sort funsort = d_tm.mkFunctionSort({intsort}, bvsort); Term x = d_tm.mkConst(intsort, "x"); Term a = d_tm.mkConst(arrsort, "a"); Term b = d_tm.mkConst(bvsort, "b"); ASSERT_FALSE(x.hasOp()); ASSERT_THROW(x.getOp(), CVC5ApiException); Term ab = d_tm.mkTerm(Kind::SELECT, {a, b}); Op ext = d_tm.mkOp(Kind::BITVECTOR_EXTRACT, {4, 0}); Term extb = d_tm.mkTerm(ext, {b}); ASSERT_TRUE(ab.hasOp()); ASSERT_FALSE(ab.getOp().isIndexed()); // can compare directly to a Kind (will invoke Op constructor) ASSERT_TRUE(extb.hasOp()); ASSERT_TRUE(extb.getOp().isIndexed()); ASSERT_EQ(extb.getOp(), ext); Op bit = d_tm.mkOp(Kind::BITVECTOR_BIT, {4}); Term bitb = d_tm.mkTerm(bit, {b}); ASSERT_EQ(bitb.getKind(), Kind::BITVECTOR_BIT); ASSERT_TRUE(bitb.hasOp()); ASSERT_EQ(bitb.getOp(), bit); ASSERT_TRUE(bitb.getOp().isIndexed()); ASSERT_EQ(bit.getNumIndices(), 1); ASSERT_EQ(bit[0], d_tm.mkInteger(4)); Term f = d_tm.mkConst(funsort, "f"); Term fx = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_FALSE(f.hasOp()); ASSERT_THROW(f.getOp(), CVC5ApiException); ASSERT_TRUE(fx.hasOp()); std::vector children(fx.begin(), fx.end()); // testing rebuild from op and children ASSERT_EQ(fx, d_tm.mkTerm(fx.getOp(), children)); // Test Datatypes Ops Sort sort = d_tm.mkParamSort("T"); DatatypeDecl listDecl = d_tm.mkDatatypeDecl("paramlist", {sort}); DatatypeConstructorDecl cons = d_tm.mkDatatypeConstructorDecl("cons"); DatatypeConstructorDecl nil = d_tm.mkDatatypeConstructorDecl("nil"); cons.addSelector("head", sort); cons.addSelectorSelf("tail"); listDecl.addConstructor(cons); listDecl.addConstructor(nil); Sort listSort = d_tm.mkDatatypeSort(listDecl); Sort intListSort = listSort.instantiate(std::vector{d_tm.getIntegerSort()}); Term c = d_tm.mkConst(intListSort, "c"); Datatype list = listSort.getDatatype(); // list datatype constructor and selector operator terms Term consOpTerm = list.getConstructor("cons").getTerm(); Term nilOpTerm = list.getConstructor("nil").getTerm(); Term headOpTerm = list["cons"].getSelector("head").getTerm(); Term tailOpTerm = list["cons"].getSelector("tail").getTerm(); Term nilTerm = d_tm.mkTerm(Kind::APPLY_CONSTRUCTOR, {nilOpTerm}); Term consTerm = d_tm.mkTerm(Kind::APPLY_CONSTRUCTOR, {consOpTerm, d_tm.mkInteger(0), nilTerm}); Term headTerm = d_tm.mkTerm(Kind::APPLY_SELECTOR, {headOpTerm, consTerm}); Term tailTerm = d_tm.mkTerm(Kind::APPLY_SELECTOR, {tailOpTerm, consTerm}); ASSERT_FALSE(c.hasOp()); ASSERT_TRUE(nilTerm.hasOp()); ASSERT_TRUE(consTerm.hasOp()); ASSERT_TRUE(headTerm.hasOp()); ASSERT_TRUE(tailTerm.hasOp()); // Test rebuilding children.clear(); children.insert(children.begin(), headTerm.begin(), headTerm.end()); ASSERT_EQ(headTerm, d_tm.mkTerm(headTerm.getOp(), children)); } TEST_F(TestApiBlackTerm, hasGetSymbol) { Term n; Term t = d_tm.mkBoolean(true); Term c = d_tm.mkConst(d_tm.getBooleanSort(), "|\\|"); ASSERT_THROW(n.hasSymbol(), CVC5ApiException); ASSERT_FALSE(t.hasSymbol()); ASSERT_TRUE(c.hasSymbol()); ASSERT_THROW(n.getSymbol(), CVC5ApiException); ASSERT_THROW(t.getSymbol(), CVC5ApiException); ASSERT_EQ(c.getSymbol(), "|\\|"); } TEST_F(TestApiBlackTerm, isNull) { Term x; ASSERT_TRUE(x.isNull()); x = d_tm.mkVar(d_tm.mkBitVectorSort(4), "x"); ASSERT_FALSE(x.isNull()); } TEST_F(TestApiBlackTerm, notTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); ASSERT_THROW(Term().notTerm(), CVC5ApiException); Term b = d_tm.mkTrue(); ASSERT_NO_THROW(b.notTerm()); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_THROW(x.notTerm(), CVC5ApiException); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.notTerm(), CVC5ApiException); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.notTerm(), CVC5ApiException); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.notTerm(), CVC5ApiException); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.notTerm(), CVC5ApiException); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.notTerm(), CVC5ApiException); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.notTerm()); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.notTerm()); } TEST_F(TestApiBlackTerm, andTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term b = d_tm.mkTrue(); ASSERT_THROW(Term().andTerm(b), CVC5ApiException); ASSERT_THROW(b.andTerm(Term()), CVC5ApiException); ASSERT_NO_THROW(b.andTerm(b)); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_THROW(x.andTerm(b), CVC5ApiException); ASSERT_THROW(x.andTerm(x), CVC5ApiException); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.andTerm(b), CVC5ApiException); ASSERT_THROW(f.andTerm(x), CVC5ApiException); ASSERT_THROW(f.andTerm(f), CVC5ApiException); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.andTerm(b), CVC5ApiException); ASSERT_THROW(p.andTerm(x), CVC5ApiException); ASSERT_THROW(p.andTerm(f), CVC5ApiException); ASSERT_THROW(p.andTerm(p), CVC5ApiException); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.andTerm(b), CVC5ApiException); ASSERT_THROW(zero.andTerm(x), CVC5ApiException); ASSERT_THROW(zero.andTerm(f), CVC5ApiException); ASSERT_THROW(zero.andTerm(p), CVC5ApiException); ASSERT_THROW(zero.andTerm(zero), CVC5ApiException); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.andTerm(b), CVC5ApiException); ASSERT_THROW(f_x.andTerm(x), CVC5ApiException); ASSERT_THROW(f_x.andTerm(f), CVC5ApiException); ASSERT_THROW(f_x.andTerm(p), CVC5ApiException); ASSERT_THROW(f_x.andTerm(zero), CVC5ApiException); ASSERT_THROW(f_x.andTerm(f_x), CVC5ApiException); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.andTerm(b), CVC5ApiException); ASSERT_THROW(sum.andTerm(x), CVC5ApiException); ASSERT_THROW(sum.andTerm(f), CVC5ApiException); ASSERT_THROW(sum.andTerm(p), CVC5ApiException); ASSERT_THROW(sum.andTerm(zero), CVC5ApiException); ASSERT_THROW(sum.andTerm(f_x), CVC5ApiException); ASSERT_THROW(sum.andTerm(sum), CVC5ApiException); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.andTerm(b)); ASSERT_THROW(p_0.andTerm(x), CVC5ApiException); ASSERT_THROW(p_0.andTerm(f), CVC5ApiException); ASSERT_THROW(p_0.andTerm(p), CVC5ApiException); ASSERT_THROW(p_0.andTerm(zero), CVC5ApiException); ASSERT_THROW(p_0.andTerm(f_x), CVC5ApiException); ASSERT_THROW(p_0.andTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_0.andTerm(p_0)); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.andTerm(b)); ASSERT_THROW(p_f_x.andTerm(x), CVC5ApiException); ASSERT_THROW(p_f_x.andTerm(f), CVC5ApiException); ASSERT_THROW(p_f_x.andTerm(p), CVC5ApiException); ASSERT_THROW(p_f_x.andTerm(zero), CVC5ApiException); ASSERT_THROW(p_f_x.andTerm(f_x), CVC5ApiException); ASSERT_THROW(p_f_x.andTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_f_x.andTerm(p_0)); ASSERT_NO_THROW(p_f_x.andTerm(p_f_x)); } TEST_F(TestApiBlackTerm, orTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term b = d_tm.mkTrue(); ASSERT_THROW(Term().orTerm(b), CVC5ApiException); ASSERT_THROW(b.orTerm(Term()), CVC5ApiException); ASSERT_NO_THROW(b.orTerm(b)); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_THROW(x.orTerm(b), CVC5ApiException); ASSERT_THROW(x.orTerm(x), CVC5ApiException); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.orTerm(b), CVC5ApiException); ASSERT_THROW(f.orTerm(x), CVC5ApiException); ASSERT_THROW(f.orTerm(f), CVC5ApiException); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.orTerm(b), CVC5ApiException); ASSERT_THROW(p.orTerm(x), CVC5ApiException); ASSERT_THROW(p.orTerm(f), CVC5ApiException); ASSERT_THROW(p.orTerm(p), CVC5ApiException); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.orTerm(b), CVC5ApiException); ASSERT_THROW(zero.orTerm(x), CVC5ApiException); ASSERT_THROW(zero.orTerm(f), CVC5ApiException); ASSERT_THROW(zero.orTerm(p), CVC5ApiException); ASSERT_THROW(zero.orTerm(zero), CVC5ApiException); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.orTerm(b), CVC5ApiException); ASSERT_THROW(f_x.orTerm(x), CVC5ApiException); ASSERT_THROW(f_x.orTerm(f), CVC5ApiException); ASSERT_THROW(f_x.orTerm(p), CVC5ApiException); ASSERT_THROW(f_x.orTerm(zero), CVC5ApiException); ASSERT_THROW(f_x.orTerm(f_x), CVC5ApiException); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.orTerm(b), CVC5ApiException); ASSERT_THROW(sum.orTerm(x), CVC5ApiException); ASSERT_THROW(sum.orTerm(f), CVC5ApiException); ASSERT_THROW(sum.orTerm(p), CVC5ApiException); ASSERT_THROW(sum.orTerm(zero), CVC5ApiException); ASSERT_THROW(sum.orTerm(f_x), CVC5ApiException); ASSERT_THROW(sum.orTerm(sum), CVC5ApiException); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.orTerm(b)); ASSERT_THROW(p_0.orTerm(x), CVC5ApiException); ASSERT_THROW(p_0.orTerm(f), CVC5ApiException); ASSERT_THROW(p_0.orTerm(p), CVC5ApiException); ASSERT_THROW(p_0.orTerm(zero), CVC5ApiException); ASSERT_THROW(p_0.orTerm(f_x), CVC5ApiException); ASSERT_THROW(p_0.orTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_0.orTerm(p_0)); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.orTerm(b)); ASSERT_THROW(p_f_x.orTerm(x), CVC5ApiException); ASSERT_THROW(p_f_x.orTerm(f), CVC5ApiException); ASSERT_THROW(p_f_x.orTerm(p), CVC5ApiException); ASSERT_THROW(p_f_x.orTerm(zero), CVC5ApiException); ASSERT_THROW(p_f_x.orTerm(f_x), CVC5ApiException); ASSERT_THROW(p_f_x.orTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_f_x.orTerm(p_0)); ASSERT_NO_THROW(p_f_x.orTerm(p_f_x)); } TEST_F(TestApiBlackTerm, xorTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term b = d_tm.mkTrue(); ASSERT_THROW(Term().xorTerm(b), CVC5ApiException); ASSERT_THROW(b.xorTerm(Term()), CVC5ApiException); ASSERT_NO_THROW(b.xorTerm(b)); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_THROW(x.xorTerm(b), CVC5ApiException); ASSERT_THROW(x.xorTerm(x), CVC5ApiException); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.xorTerm(b), CVC5ApiException); ASSERT_THROW(f.xorTerm(x), CVC5ApiException); ASSERT_THROW(f.xorTerm(f), CVC5ApiException); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.xorTerm(b), CVC5ApiException); ASSERT_THROW(p.xorTerm(x), CVC5ApiException); ASSERT_THROW(p.xorTerm(f), CVC5ApiException); ASSERT_THROW(p.xorTerm(p), CVC5ApiException); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.xorTerm(b), CVC5ApiException); ASSERT_THROW(zero.xorTerm(x), CVC5ApiException); ASSERT_THROW(zero.xorTerm(f), CVC5ApiException); ASSERT_THROW(zero.xorTerm(p), CVC5ApiException); ASSERT_THROW(zero.xorTerm(zero), CVC5ApiException); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.xorTerm(b), CVC5ApiException); ASSERT_THROW(f_x.xorTerm(x), CVC5ApiException); ASSERT_THROW(f_x.xorTerm(f), CVC5ApiException); ASSERT_THROW(f_x.xorTerm(p), CVC5ApiException); ASSERT_THROW(f_x.xorTerm(zero), CVC5ApiException); ASSERT_THROW(f_x.xorTerm(f_x), CVC5ApiException); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.xorTerm(b), CVC5ApiException); ASSERT_THROW(sum.xorTerm(x), CVC5ApiException); ASSERT_THROW(sum.xorTerm(f), CVC5ApiException); ASSERT_THROW(sum.xorTerm(p), CVC5ApiException); ASSERT_THROW(sum.xorTerm(zero), CVC5ApiException); ASSERT_THROW(sum.xorTerm(f_x), CVC5ApiException); ASSERT_THROW(sum.xorTerm(sum), CVC5ApiException); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.xorTerm(b)); ASSERT_THROW(p_0.xorTerm(x), CVC5ApiException); ASSERT_THROW(p_0.xorTerm(f), CVC5ApiException); ASSERT_THROW(p_0.xorTerm(p), CVC5ApiException); ASSERT_THROW(p_0.xorTerm(zero), CVC5ApiException); ASSERT_THROW(p_0.xorTerm(f_x), CVC5ApiException); ASSERT_THROW(p_0.xorTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_0.xorTerm(p_0)); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.xorTerm(b)); ASSERT_THROW(p_f_x.xorTerm(x), CVC5ApiException); ASSERT_THROW(p_f_x.xorTerm(f), CVC5ApiException); ASSERT_THROW(p_f_x.xorTerm(p), CVC5ApiException); ASSERT_THROW(p_f_x.xorTerm(zero), CVC5ApiException); ASSERT_THROW(p_f_x.xorTerm(f_x), CVC5ApiException); ASSERT_THROW(p_f_x.xorTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_f_x.xorTerm(p_0)); ASSERT_NO_THROW(p_f_x.xorTerm(p_f_x)); } TEST_F(TestApiBlackTerm, eqTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term b = d_tm.mkTrue(); ASSERT_THROW(Term().eqTerm(b), CVC5ApiException); ASSERT_THROW(b.eqTerm(Term()), CVC5ApiException); ASSERT_NO_THROW(b.eqTerm(b)); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_THROW(x.eqTerm(b), CVC5ApiException); ASSERT_NO_THROW(x.eqTerm(x)); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.eqTerm(b), CVC5ApiException); ASSERT_THROW(f.eqTerm(x), CVC5ApiException); ASSERT_NO_THROW(f.eqTerm(f)); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.eqTerm(b), CVC5ApiException); ASSERT_THROW(p.eqTerm(x), CVC5ApiException); ASSERT_THROW(p.eqTerm(f), CVC5ApiException); ASSERT_NO_THROW(p.eqTerm(p)); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.eqTerm(b), CVC5ApiException); ASSERT_THROW(zero.eqTerm(x), CVC5ApiException); ASSERT_THROW(zero.eqTerm(f), CVC5ApiException); ASSERT_THROW(zero.eqTerm(p), CVC5ApiException); ASSERT_NO_THROW(zero.eqTerm(zero)); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.eqTerm(b), CVC5ApiException); ASSERT_THROW(f_x.eqTerm(x), CVC5ApiException); ASSERT_THROW(f_x.eqTerm(f), CVC5ApiException); ASSERT_THROW(f_x.eqTerm(p), CVC5ApiException); ASSERT_NO_THROW(f_x.eqTerm(zero)); ASSERT_NO_THROW(f_x.eqTerm(f_x)); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.eqTerm(b), CVC5ApiException); ASSERT_THROW(sum.eqTerm(x), CVC5ApiException); ASSERT_THROW(sum.eqTerm(f), CVC5ApiException); ASSERT_THROW(sum.eqTerm(p), CVC5ApiException); ASSERT_NO_THROW(sum.eqTerm(zero)); ASSERT_NO_THROW(sum.eqTerm(f_x)); ASSERT_NO_THROW(sum.eqTerm(sum)); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.eqTerm(b)); ASSERT_THROW(p_0.eqTerm(x), CVC5ApiException); ASSERT_THROW(p_0.eqTerm(f), CVC5ApiException); ASSERT_THROW(p_0.eqTerm(p), CVC5ApiException); ASSERT_THROW(p_0.eqTerm(zero), CVC5ApiException); ASSERT_THROW(p_0.eqTerm(f_x), CVC5ApiException); ASSERT_THROW(p_0.eqTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_0.eqTerm(p_0)); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.eqTerm(b)); ASSERT_THROW(p_f_x.eqTerm(x), CVC5ApiException); ASSERT_THROW(p_f_x.eqTerm(f), CVC5ApiException); ASSERT_THROW(p_f_x.eqTerm(p), CVC5ApiException); ASSERT_THROW(p_f_x.eqTerm(zero), CVC5ApiException); ASSERT_THROW(p_f_x.eqTerm(f_x), CVC5ApiException); ASSERT_THROW(p_f_x.eqTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_f_x.eqTerm(p_0)); ASSERT_NO_THROW(p_f_x.eqTerm(p_f_x)); } TEST_F(TestApiBlackTerm, impTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term b = d_tm.mkTrue(); ASSERT_THROW(Term().impTerm(b), CVC5ApiException); ASSERT_THROW(b.impTerm(Term()), CVC5ApiException); ASSERT_NO_THROW(b.impTerm(b)); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_THROW(x.impTerm(b), CVC5ApiException); ASSERT_THROW(x.impTerm(x), CVC5ApiException); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.impTerm(b), CVC5ApiException); ASSERT_THROW(f.impTerm(x), CVC5ApiException); ASSERT_THROW(f.impTerm(f), CVC5ApiException); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.impTerm(b), CVC5ApiException); ASSERT_THROW(p.impTerm(x), CVC5ApiException); ASSERT_THROW(p.impTerm(f), CVC5ApiException); ASSERT_THROW(p.impTerm(p), CVC5ApiException); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.impTerm(b), CVC5ApiException); ASSERT_THROW(zero.impTerm(x), CVC5ApiException); ASSERT_THROW(zero.impTerm(f), CVC5ApiException); ASSERT_THROW(zero.impTerm(p), CVC5ApiException); ASSERT_THROW(zero.impTerm(zero), CVC5ApiException); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.impTerm(b), CVC5ApiException); ASSERT_THROW(f_x.impTerm(x), CVC5ApiException); ASSERT_THROW(f_x.impTerm(f), CVC5ApiException); ASSERT_THROW(f_x.impTerm(p), CVC5ApiException); ASSERT_THROW(f_x.impTerm(zero), CVC5ApiException); ASSERT_THROW(f_x.impTerm(f_x), CVC5ApiException); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.impTerm(b), CVC5ApiException); ASSERT_THROW(sum.impTerm(x), CVC5ApiException); ASSERT_THROW(sum.impTerm(f), CVC5ApiException); ASSERT_THROW(sum.impTerm(p), CVC5ApiException); ASSERT_THROW(sum.impTerm(zero), CVC5ApiException); ASSERT_THROW(sum.impTerm(f_x), CVC5ApiException); ASSERT_THROW(sum.impTerm(sum), CVC5ApiException); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.impTerm(b)); ASSERT_THROW(p_0.impTerm(x), CVC5ApiException); ASSERT_THROW(p_0.impTerm(f), CVC5ApiException); ASSERT_THROW(p_0.impTerm(p), CVC5ApiException); ASSERT_THROW(p_0.impTerm(zero), CVC5ApiException); ASSERT_THROW(p_0.impTerm(f_x), CVC5ApiException); ASSERT_THROW(p_0.impTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_0.impTerm(p_0)); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.impTerm(b)); ASSERT_THROW(p_f_x.impTerm(x), CVC5ApiException); ASSERT_THROW(p_f_x.impTerm(f), CVC5ApiException); ASSERT_THROW(p_f_x.impTerm(p), CVC5ApiException); ASSERT_THROW(p_f_x.impTerm(zero), CVC5ApiException); ASSERT_THROW(p_f_x.impTerm(f_x), CVC5ApiException); ASSERT_THROW(p_f_x.impTerm(sum), CVC5ApiException); ASSERT_NO_THROW(p_f_x.impTerm(p_0)); ASSERT_NO_THROW(p_f_x.impTerm(p_f_x)); } TEST_F(TestApiBlackTerm, iteTerm) { Sort bvSort = d_tm.mkBitVectorSort(8); Sort intSort = d_tm.getIntegerSort(); Sort boolSort = d_tm.getBooleanSort(); Sort funSort1 = d_tm.mkFunctionSort({bvSort}, intSort); Sort funSort2 = d_tm.mkFunctionSort({intSort}, boolSort); Term b = d_tm.mkTrue(); ASSERT_THROW(Term().iteTerm(b, b), CVC5ApiException); ASSERT_THROW(b.iteTerm(Term(), b), CVC5ApiException); ASSERT_THROW(b.iteTerm(b, Term()), CVC5ApiException); ASSERT_NO_THROW(b.iteTerm(b, b)); Term x = d_tm.mkVar(d_tm.mkBitVectorSort(8), "x"); ASSERT_NO_THROW(b.iteTerm(x, x)); ASSERT_NO_THROW(b.iteTerm(b, b)); ASSERT_THROW(b.iteTerm(x, b), CVC5ApiException); ASSERT_THROW(x.iteTerm(x, x), CVC5ApiException); ASSERT_THROW(x.iteTerm(x, b), CVC5ApiException); Term f = d_tm.mkVar(funSort1, "f"); ASSERT_THROW(f.iteTerm(b, b), CVC5ApiException); ASSERT_THROW(x.iteTerm(b, x), CVC5ApiException); Term p = d_tm.mkVar(funSort2, "p"); ASSERT_THROW(p.iteTerm(b, b), CVC5ApiException); ASSERT_THROW(p.iteTerm(x, b), CVC5ApiException); Term zero = d_tm.mkInteger(0); ASSERT_THROW(zero.iteTerm(x, x), CVC5ApiException); ASSERT_THROW(zero.iteTerm(x, b), CVC5ApiException); Term f_x = d_tm.mkTerm(Kind::APPLY_UF, {f, x}); ASSERT_THROW(f_x.iteTerm(b, b), CVC5ApiException); ASSERT_THROW(f_x.iteTerm(b, x), CVC5ApiException); Term sum = d_tm.mkTerm(Kind::ADD, {f_x, f_x}); ASSERT_THROW(sum.iteTerm(x, x), CVC5ApiException); ASSERT_THROW(sum.iteTerm(b, x), CVC5ApiException); Term p_0 = d_tm.mkTerm(Kind::APPLY_UF, {p, zero}); ASSERT_NO_THROW(p_0.iteTerm(b, b)); ASSERT_NO_THROW(p_0.iteTerm(x, x)); ASSERT_THROW(p_0.iteTerm(x, b), CVC5ApiException); Term p_f_x = d_tm.mkTerm(Kind::APPLY_UF, {p, f_x}); ASSERT_NO_THROW(p_f_x.iteTerm(b, b)); ASSERT_NO_THROW(p_f_x.iteTerm(x, x)); ASSERT_THROW(p_f_x.iteTerm(x, b), CVC5ApiException); } TEST_F(TestApiBlackTerm, termAssignment) { Term t1 = d_tm.mkInteger(1); Term t2 = t1; t2 = d_tm.mkInteger(2); ASSERT_EQ(t1, d_tm.mkInteger(1)); } TEST_F(TestApiBlackTerm, termCompare) { Term t1 = d_tm.mkInteger(1); Term t2 = d_tm.mkTerm(Kind::ADD, {d_tm.mkInteger(2), d_tm.mkInteger(2)}); Term t3 = d_tm.mkTerm(Kind::ADD, {d_tm.mkInteger(2), d_tm.mkInteger(2)}); ASSERT_TRUE(t2 >= t3); ASSERT_TRUE(t2 <= t3); ASSERT_TRUE((t1 > t2) != (t1 < t2)); ASSERT_TRUE((t1 > t2 || t1 == t2) == (t1 >= t2)); } TEST_F(TestApiBlackTerm, termChildren) { // simple term 2+3 Term two = d_tm.mkInteger(2); Term t1 = d_tm.mkTerm(Kind::ADD, {two, d_tm.mkInteger(3)}); ASSERT_EQ(t1[0], two); ASSERT_EQ(t1.getNumChildren(), 2); Term tnull; ASSERT_THROW(tnull.getNumChildren(), CVC5ApiException); Term::const_iterator it; it = t1.begin(); ASSERT_TRUE((*it).isIntegerValue()); it++; ASSERT_TRUE((*it).isIntegerValue()); ++it; ASSERT_EQ(it, t1.end()); // apply term f(2) Sort intSort = d_tm.getIntegerSort(); Sort fsort = d_tm.mkFunctionSort({intSort}, intSort); Term f = d_tm.mkConst(fsort, "f"); Term t2 = d_tm.mkTerm(Kind::APPLY_UF, {f, two}); // due to our higher-order view of terms, we treat f as a child of APPLY_UF ASSERT_EQ(t2.getNumChildren(), 2); ASSERT_EQ(t2[0], f); ASSERT_EQ(t2[1], two); ASSERT_THROW(tnull[0], CVC5ApiException); } TEST_F(TestApiBlackTerm, getInteger) { Term int1 = d_tm.mkInteger("-18446744073709551616"); Term int2 = d_tm.mkInteger("-18446744073709551615"); Term int3 = d_tm.mkInteger("-4294967296"); Term int4 = d_tm.mkInteger("-4294967295"); Term int5 = d_tm.mkInteger("-10"); Term int6 = d_tm.mkInteger("0"); Term int7 = d_tm.mkInteger("10"); Term int8 = d_tm.mkInteger("4294967295"); Term int9 = d_tm.mkInteger("4294967296"); Term int10 = d_tm.mkInteger("18446744073709551615"); Term int11 = d_tm.mkInteger("18446744073709551616"); Term int12 = d_tm.mkInteger("-0"); ASSERT_THROW(d_tm.mkInteger(""), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("-"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("-1-"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("0.0"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("-0.1"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("012"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("0000"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("-01"), CVC5ApiException); ASSERT_THROW(d_tm.mkInteger("-00"), CVC5ApiException); ASSERT_TRUE(!int1.isInt32Value() && !int1.isUInt32Value() && !int1.isInt64Value() && !int1.isUInt64Value() && int1.isIntegerValue()); ASSERT_EQ(int1.getIntegerValue(), "-18446744073709551616"); ASSERT_TRUE(int1.getRealOrIntegerValueSign() == -1); ASSERT_TRUE(!int2.isInt32Value() && !int2.isUInt32Value() && !int2.isInt64Value() && !int2.isUInt64Value() && int2.isIntegerValue()); ASSERT_EQ(int2.getIntegerValue(), "-18446744073709551615"); ASSERT_TRUE(!int3.isInt32Value() && !int3.isUInt32Value() && int3.isInt64Value() && !int3.isUInt64Value() && int3.isIntegerValue()); ASSERT_EQ(int3.getInt64Value(), -4294967296); ASSERT_EQ(int3.getIntegerValue(), "-4294967296"); ASSERT_TRUE(!int4.isInt32Value() && !int4.isUInt32Value() && int4.isInt64Value() && !int4.isUInt64Value() && int4.isIntegerValue()); ASSERT_EQ(int4.getInt64Value(), -4294967295); ASSERT_EQ(int4.getIntegerValue(), "-4294967295"); ASSERT_TRUE(int5.isInt32Value() && !int5.isUInt32Value() && int5.isInt64Value() && !int5.isUInt64Value() && int5.isIntegerValue()); ASSERT_EQ(int5.getInt32Value(), -10); ASSERT_EQ(int5.getInt64Value(), -10); ASSERT_EQ(int5.getIntegerValue(), "-10"); ASSERT_TRUE(int6.isInt32Value() && int6.isUInt32Value() && int6.isInt64Value() && int6.isUInt64Value() && int6.isIntegerValue()); ASSERT_EQ(int6.getInt32Value(), 0); ASSERT_EQ(int6.getUInt32Value(), 0); ASSERT_EQ(int6.getInt64Value(), 0); ASSERT_EQ(int6.getUInt64Value(), 0); ASSERT_EQ(int6.getIntegerValue(), "0"); ASSERT_TRUE(int6.getRealOrIntegerValueSign() == 0); ASSERT_TRUE(int7.isInt32Value() && int7.isUInt32Value() && int7.isInt64Value() && int7.isUInt64Value() && int7.isIntegerValue()); ASSERT_EQ(int7.getInt32Value(), 10); ASSERT_EQ(int7.getUInt32Value(), 10); ASSERT_EQ(int7.getInt64Value(), 10); ASSERT_EQ(int7.getUInt64Value(), 10); ASSERT_EQ(int7.getIntegerValue(), "10"); ASSERT_TRUE(int7.getRealOrIntegerValueSign() == 1); ASSERT_TRUE(!int8.isInt32Value() && int8.isUInt32Value() && int8.isInt64Value() && int8.isUInt64Value() && int8.isIntegerValue()); ASSERT_EQ(int8.getUInt32Value(), 4294967295); ASSERT_EQ(int8.getInt64Value(), 4294967295); ASSERT_EQ(int8.getUInt64Value(), 4294967295); ASSERT_EQ(int8.getIntegerValue(), "4294967295"); ASSERT_TRUE(!int9.isInt32Value() && !int9.isUInt32Value() && int9.isInt64Value() && int9.isUInt64Value() && int9.isIntegerValue()); ASSERT_EQ(int9.getInt64Value(), 4294967296); ASSERT_EQ(int9.getUInt64Value(), 4294967296); ASSERT_EQ(int9.getIntegerValue(), "4294967296"); ASSERT_TRUE(!int10.isInt32Value() && !int10.isUInt32Value() && !int10.isInt64Value() && int10.isUInt64Value() && int10.isIntegerValue()); ASSERT_EQ(int10.getUInt64Value(), 18446744073709551615ull); ASSERT_EQ(int10.getIntegerValue(), "18446744073709551615"); ASSERT_TRUE(!int11.isInt32Value() && !int11.isUInt32Value() && !int11.isInt64Value() && !int11.isUInt64Value() && int11.isIntegerValue()); ASSERT_EQ(int11.getIntegerValue(), "18446744073709551616"); } TEST_F(TestApiBlackTerm, getString) { Term s1 = d_tm.mkString("abcde"); ASSERT_TRUE(s1.isStringValue()); ASSERT_EQ(s1.getU32StringValue(), U"abcde"); } TEST_F(TestApiBlackTerm, getReal) { Term real1 = d_tm.mkReal("0"); Term real2 = d_tm.mkReal(".0"); Term real3 = d_tm.mkReal("-17"); Term real4 = d_tm.mkReal("-3/5"); Term real5 = d_tm.mkReal("12.7"); Term real6 = d_tm.mkReal("1/4294967297"); Term real7 = d_tm.mkReal("4294967297"); Term real8 = d_tm.mkReal("1/18446744073709551617"); Term real9 = d_tm.mkReal("18446744073709551617"); Term real10 = d_tm.mkReal("2343.2343"); ASSERT_TRUE(real1.isRealValue() && real1.isReal64Value() && real1.isReal32Value()); ASSERT_TRUE(real2.isRealValue() && real2.isReal64Value() && real2.isReal32Value()); ASSERT_TRUE(real3.isRealValue() && real3.isReal64Value() && real3.isReal32Value()); ASSERT_TRUE(real4.isRealValue() && real4.isReal64Value() && real4.isReal32Value()); ASSERT_TRUE(real5.isRealValue() && real5.isReal64Value() && real5.isReal32Value()); ASSERT_TRUE(real6.isRealValue() && real6.isReal64Value()); ASSERT_TRUE(real7.isRealValue() && real7.isReal64Value()); ASSERT_TRUE(real8.isRealValue()); ASSERT_TRUE(real9.isRealValue()); ASSERT_TRUE(real10.isRealValue()); ASSERT_EQ((std::pair(0, 1)), real1.getReal32Value()); ASSERT_EQ((std::pair(0, 1)), real1.getReal64Value()); ASSERT_EQ("0/1", real1.getRealValue()); ASSERT_EQ((std::pair(0, 1)), real2.getReal32Value()); ASSERT_EQ((std::pair(0, 1)), real2.getReal64Value()); ASSERT_EQ("0/1", real2.getRealValue()); ASSERT_EQ((std::pair(-17, 1)), real3.getReal32Value()); ASSERT_EQ((std::pair(-17, 1)), real3.getReal64Value()); ASSERT_EQ("-17/1", real3.getRealValue()); ASSERT_EQ((std::pair(-3, 5)), real4.getReal32Value()); ASSERT_EQ((std::pair(-3, 5)), real4.getReal64Value()); ASSERT_EQ("-3/5", real4.getRealValue()); ASSERT_EQ((std::pair(127, 10)), real5.getReal32Value()); ASSERT_EQ((std::pair(127, 10)), real5.getReal64Value()); ASSERT_EQ("127/10", real5.getRealValue()); ASSERT_EQ((std::pair(1, 4294967297)), real6.getReal64Value()); ASSERT_EQ("1/4294967297", real6.getRealValue()); ASSERT_EQ((std::pair(4294967297, 1)), real7.getReal64Value()); ASSERT_EQ("4294967297/1", real7.getRealValue()); ASSERT_EQ("1/18446744073709551617", real8.getRealValue()); ASSERT_EQ("18446744073709551617/1", real9.getRealValue()); ASSERT_EQ("23432343/10000", real10.getRealValue()); ASSERT_THROW(d_tm.mkReal("1/0"), CVC5ApiException); ASSERT_THROW(d_tm.mkReal("2/0000"), CVC5ApiException); } TEST_F(TestApiBlackTerm, getConstArrayBase) { Sort intsort = d_tm.getIntegerSort(); Sort arrsort = d_tm.mkArraySort(intsort, intsort); Term one = d_tm.mkInteger(1); Term constarr = d_tm.mkConstArray(arrsort, one); ASSERT_TRUE(constarr.isConstArray()); ASSERT_EQ(one, constarr.getConstArrayBase()); Term a = d_tm.mkConst(arrsort, "a"); ASSERT_THROW(a.getConstArrayBase(), CVC5ApiException); ASSERT_THROW(one.getConstArrayBase(), CVC5ApiException); } TEST_F(TestApiBlackTerm, getBoolean) { Term b1 = d_tm.mkBoolean(true); Term b2 = d_tm.mkBoolean(false); ASSERT_TRUE(b1.isBooleanValue()); ASSERT_TRUE(b2.isBooleanValue()); ASSERT_TRUE(b1.getBooleanValue()); ASSERT_FALSE(b2.getBooleanValue()); } TEST_F(TestApiBlackTerm, getBitVector) { Term b1 = d_tm.mkBitVector(8, 15); Term b2 = d_tm.mkBitVector(8, "00001111", 2); Term b3 = d_tm.mkBitVector(8, "15", 10); Term b4 = d_tm.mkBitVector(8, "0f", 16); Term b5 = d_tm.mkBitVector(9, "00001111", 2); Term b6 = d_tm.mkBitVector(9, "15", 10); Term b7 = d_tm.mkBitVector(9, "0f", 16); ASSERT_TRUE(b1.isBitVectorValue()); ASSERT_TRUE(b2.isBitVectorValue()); ASSERT_TRUE(b3.isBitVectorValue()); ASSERT_TRUE(b4.isBitVectorValue()); ASSERT_TRUE(b5.isBitVectorValue()); ASSERT_TRUE(b6.isBitVectorValue()); ASSERT_TRUE(b7.isBitVectorValue()); ASSERT_EQ("00001111", b1.getBitVectorValue(2)); ASSERT_EQ("15", b1.getBitVectorValue(10)); ASSERT_EQ("f", b1.getBitVectorValue(16)); ASSERT_EQ("00001111", b2.getBitVectorValue(2)); ASSERT_EQ("15", b2.getBitVectorValue(10)); ASSERT_EQ("f", b2.getBitVectorValue(16)); ASSERT_EQ("00001111", b3.getBitVectorValue(2)); ASSERT_EQ("15", b3.getBitVectorValue(10)); ASSERT_EQ("f", b3.getBitVectorValue(16)); ASSERT_EQ("00001111", b4.getBitVectorValue(2)); ASSERT_EQ("15", b4.getBitVectorValue(10)); ASSERT_EQ("f", b4.getBitVectorValue(16)); ASSERT_EQ("000001111", b5.getBitVectorValue(2)); ASSERT_EQ("15", b5.getBitVectorValue(10)); ASSERT_EQ("f", b5.getBitVectorValue(16)); ASSERT_EQ("000001111", b6.getBitVectorValue(2)); ASSERT_EQ("15", b6.getBitVectorValue(10)); ASSERT_EQ("f", b6.getBitVectorValue(16)); ASSERT_EQ("000001111", b7.getBitVectorValue(2)); ASSERT_EQ("15", b7.getBitVectorValue(10)); ASSERT_EQ("f", b7.getBitVectorValue(16)); } TEST_F(TestApiBlackTerm, isFiniteFieldValue) { Sort fS = d_tm.mkFiniteFieldSort("7"); Term fV = d_tm.mkFiniteFieldElem("1", fS); ASSERT_TRUE(fV.isFiniteFieldValue()); Term b1 = d_tm.mkBitVector(8, 15); ASSERT_FALSE(b1.isFiniteFieldValue()); } TEST_F(TestApiBlackTerm, getFiniteFieldValue) { Sort fS = d_tm.mkFiniteFieldSort("7"); Term fV = d_tm.mkFiniteFieldElem("1", fS); ASSERT_EQ("1", fV.getFiniteFieldValue()); ASSERT_THROW(Term().getFiniteFieldValue(), CVC5ApiException); Term b1 = d_tm.mkBitVector(8, 15); ASSERT_THROW(b1.getFiniteFieldValue(), CVC5ApiException); } TEST_F(TestApiBlackTerm, getUninterpretedSortValue) { d_solver->setOption("produce-models", "true"); Sort uSort = d_tm.mkUninterpretedSort("u"); Term x = d_tm.mkConst(uSort, "x"); Term y = d_tm.mkConst(uSort, "y"); d_solver->assertFormula(d_tm.mkTerm(Kind::EQUAL, {x, y})); ASSERT_TRUE(d_solver->checkSat().isSat()); Term vx = d_solver->getValue(x); Term vy = d_solver->getValue(y); ASSERT_TRUE(vx.isUninterpretedSortValue()); ASSERT_TRUE(vy.isUninterpretedSortValue()); ASSERT_EQ(vx.getUninterpretedSortValue(), vy.getUninterpretedSortValue()); } TEST_F(TestApiBlackTerm, isRoundingModeValue) { ASSERT_FALSE(d_tm.mkInteger(15).isRoundingModeValue()); ASSERT_TRUE(d_tm.mkRoundingMode(RoundingMode::ROUND_NEAREST_TIES_TO_EVEN) .isRoundingModeValue()); ASSERT_FALSE(d_tm.mkConst(d_tm.getRoundingModeSort()).isRoundingModeValue()); } TEST_F(TestApiBlackTerm, getRoundingModeValue) { ASSERT_THROW(d_tm.mkInteger(15).getRoundingModeValue(), CVC5ApiException); ASSERT_EQ(d_tm.mkRoundingMode(RoundingMode::ROUND_NEAREST_TIES_TO_EVEN) .getRoundingModeValue(), RoundingMode::ROUND_NEAREST_TIES_TO_EVEN); ASSERT_EQ(d_tm.mkRoundingMode(RoundingMode::ROUND_TOWARD_POSITIVE) .getRoundingModeValue(), RoundingMode::ROUND_TOWARD_POSITIVE); ASSERT_EQ(d_tm.mkRoundingMode(RoundingMode::ROUND_TOWARD_NEGATIVE) .getRoundingModeValue(), RoundingMode::ROUND_TOWARD_NEGATIVE); ASSERT_EQ(d_tm.mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO) .getRoundingModeValue(), RoundingMode::ROUND_TOWARD_ZERO); ASSERT_EQ(d_tm.mkRoundingMode(RoundingMode::ROUND_NEAREST_TIES_TO_AWAY) .getRoundingModeValue(), RoundingMode::ROUND_NEAREST_TIES_TO_AWAY); } TEST_F(TestApiBlackTerm, getTuple) { Term t1 = d_tm.mkInteger(15); Term t2 = d_tm.mkReal(17, 25); Term t3 = d_tm.mkString("abc"); Term tup = d_tm.mkTuple({t1, t2, t3}); ASSERT_TRUE(tup.isTupleValue()); ASSERT_EQ(std::vector({t1, t2, t3}), tup.getTupleValue()); } TEST_F(TestApiBlackTerm, getFloatingPoint) { Term bvval = d_tm.mkBitVector(16, "0000110000000011", 2); Term fp = d_tm.mkFloatingPoint(5, 11, bvval); ASSERT_TRUE(fp.isFloatingPointValue()); ASSERT_FALSE(fp.isFloatingPointPosZero()); ASSERT_FALSE(fp.isFloatingPointNegZero()); ASSERT_FALSE(fp.isFloatingPointPosInf()); ASSERT_FALSE(fp.isFloatingPointNegInf()); ASSERT_FALSE(fp.isFloatingPointNaN()); ASSERT_EQ(std::make_tuple(5u, 11u, bvval), fp.getFloatingPointValue()); ASSERT_TRUE(d_tm.mkFloatingPointPosZero(5, 11).isFloatingPointPosZero()); ASSERT_TRUE(d_tm.mkFloatingPointNegZero(5, 11).isFloatingPointNegZero()); ASSERT_TRUE(d_tm.mkFloatingPointPosInf(5, 11).isFloatingPointPosInf()); ASSERT_TRUE(d_tm.mkFloatingPointNegInf(5, 11).isFloatingPointNegInf()); ASSERT_TRUE(d_tm.mkFloatingPointNaN(5, 11).isFloatingPointNaN()); } TEST_F(TestApiBlackTerm, getSet) { Sort s = d_tm.mkSetSort(d_tm.getIntegerSort()); Term i1 = d_tm.mkInteger(5); Term i2 = d_tm.mkInteger(7); Term s1 = d_tm.mkEmptySet(s); Term s2 = d_tm.mkTerm(Kind::SET_SINGLETON, {i1}); Term s3 = d_tm.mkTerm(Kind::SET_SINGLETON, {i1}); Term s4 = d_tm.mkTerm(Kind::SET_SINGLETON, {i2}); Term s5 = d_tm.mkTerm(Kind::SET_UNION, {s2, d_tm.mkTerm(Kind::SET_UNION, {s3, s4})}); ASSERT_TRUE(s1.isSetValue()); ASSERT_TRUE(s2.isSetValue()); ASSERT_TRUE(s3.isSetValue()); ASSERT_TRUE(s4.isSetValue()); ASSERT_FALSE(s5.isSetValue()); s5 = d_solver->simplify(s5); ASSERT_TRUE(s5.isSetValue()); ASSERT_EQ(std::set({}), s1.getSetValue()); ASSERT_EQ(std::set({i1}), s2.getSetValue()); ASSERT_EQ(std::set({i1}), s3.getSetValue()); ASSERT_EQ(std::set({i2}), s4.getSetValue()); ASSERT_EQ(std::set({i1, i2}), s5.getSetValue()); } TEST_F(TestApiBlackTerm, getSequence) { Sort s = d_tm.mkSequenceSort(d_tm.getIntegerSort()); Term i1 = d_tm.mkInteger(5); Term i2 = d_tm.mkInteger(7); Term s1 = d_tm.mkEmptySequence(s); Term s2 = d_tm.mkTerm(Kind::SEQ_UNIT, {i1}); Term s3 = d_tm.mkTerm(Kind::SEQ_UNIT, {i1}); Term s4 = d_tm.mkTerm(Kind::SEQ_UNIT, {i2}); Term s5 = d_tm.mkTerm(Kind::SEQ_CONCAT, {s2, d_tm.mkTerm(Kind::SEQ_CONCAT, {s3, s4})}); ASSERT_TRUE(s1.isSequenceValue()); ASSERT_TRUE(!s2.isSequenceValue()); ASSERT_TRUE(!s3.isSequenceValue()); ASSERT_TRUE(!s4.isSequenceValue()); ASSERT_TRUE(!s5.isSequenceValue()); s2 = d_solver->simplify(s2); s3 = d_solver->simplify(s3); s4 = d_solver->simplify(s4); s5 = d_solver->simplify(s5); ASSERT_EQ(std::vector({}), s1.getSequenceValue()); ASSERT_EQ(std::vector({i1}), s2.getSequenceValue()); ASSERT_EQ(std::vector({i1}), s3.getSequenceValue()); ASSERT_EQ(std::vector({i2}), s4.getSequenceValue()); ASSERT_EQ(std::vector({i1, i1, i2}), s5.getSequenceValue()); } TEST_F(TestApiBlackTerm, substitute) { Term x = d_tm.mkConst(d_tm.getIntegerSort(), "x"); Term one = d_tm.mkInteger(1); Term ttrue = d_tm.mkTrue(); Term xpx = d_tm.mkTerm(Kind::ADD, {x, x}); Term onepone = d_tm.mkTerm(Kind::ADD, {one, one}); ASSERT_EQ(xpx.substitute(x, one), onepone); ASSERT_EQ(onepone.substitute(one, x), xpx); // incorrect due to type ASSERT_THROW(xpx.substitute(one, ttrue), CVC5ApiException); // simultaneous substitution Term y = d_tm.mkConst(d_tm.getIntegerSort(), "y"); Term xpy = d_tm.mkTerm(Kind::ADD, {x, y}); Term xpone = d_tm.mkTerm(Kind::ADD, {y, one}); std::vector es = {x, y}; std::vector rs = {y, one}; ASSERT_EQ(xpy.substitute(es, rs), xpone); // incorrect substitution due to arity rs.pop_back(); ASSERT_THROW(xpy.substitute(es, rs), CVC5ApiException); // incorrect substitution due to types rs.push_back(ttrue); ASSERT_THROW(xpy.substitute(es, rs), CVC5ApiException); // null cannot substitute Term tnull; ASSERT_THROW(tnull.substitute(one, x), CVC5ApiException); ASSERT_THROW(xpx.substitute(tnull, x), CVC5ApiException); ASSERT_THROW(xpx.substitute(x, tnull), CVC5ApiException); rs.pop_back(); rs.push_back(tnull); ASSERT_THROW(xpy.substitute(es, rs), CVC5ApiException); es.clear(); rs.clear(); es.push_back(x); rs.push_back(y); ASSERT_THROW(tnull.substitute(es, rs), CVC5ApiException); es.push_back(tnull); rs.push_back(one); ASSERT_THROW(xpx.substitute(es, rs), CVC5ApiException); } TEST_F(TestApiBlackTerm, constArray) { Sort intsort = d_tm.getIntegerSort(); Sort arrsort = d_tm.mkArraySort(intsort, intsort); Term a = d_tm.mkConst(arrsort, "a"); Term one = d_tm.mkInteger(1); Term two = d_tm.mkBitVector(2, 2); Term iconst = d_tm.mkConst(intsort); Term constarr = d_tm.mkConstArray(arrsort, one); ASSERT_THROW(d_tm.mkConstArray(arrsort, two), CVC5ApiException); ASSERT_THROW(d_tm.mkConstArray(arrsort, iconst), CVC5ApiException); ASSERT_EQ(constarr.getKind(), Kind::CONST_ARRAY); ASSERT_EQ(constarr.getConstArrayBase(), one); ASSERT_THROW(a.getConstArrayBase(), CVC5ApiException); arrsort = d_tm.mkArraySort(d_tm.getRealSort(), d_tm.getRealSort()); Term zero_array = d_tm.mkConstArray(arrsort, d_tm.mkReal(0)); Term stores = d_tm.mkTerm(Kind::STORE, {zero_array, d_tm.mkReal(1), d_tm.mkReal(2)}); stores = d_tm.mkTerm(Kind::STORE, {stores, d_tm.mkReal(2), d_tm.mkReal(3)}); stores = d_tm.mkTerm(Kind::STORE, {stores, d_tm.mkReal(4), d_tm.mkReal(5)}); } TEST_F(TestApiBlackTerm, getSequenceValue) { Sort realsort = d_tm.getRealSort(); Sort seqsort = d_tm.mkSequenceSort(realsort); Term s = d_tm.mkEmptySequence(seqsort); ASSERT_EQ(s.getKind(), Kind::CONST_SEQUENCE); // empty sequence has zero elements std::vector cs = s.getSequenceValue(); ASSERT_TRUE(cs.empty()); // A seq.unit app is not a constant sequence (regardless of whether it is // applied to a constant). Term su = d_tm.mkTerm(Kind::SEQ_UNIT, {d_tm.mkReal(1)}); ASSERT_THROW(su.getSequenceValue(), CVC5ApiException); } TEST_F(TestApiBlackTerm, getCardinalityConstraint) { Sort su = d_tm.mkUninterpretedSort("u"); Term t = d_tm.mkCardinalityConstraint(su, 3); ASSERT_TRUE(t.isCardinalityConstraint()); std::pair cc = t.getCardinalityConstraint(); ASSERT_EQ(cc.first, su); ASSERT_EQ(cc.second, 3); Term x = d_tm.mkConst(d_tm.getIntegerSort(), "x"); ASSERT_FALSE(x.isCardinalityConstraint()); ASSERT_THROW(x.getCardinalityConstraint(), CVC5ApiException); Term nullt; ASSERT_THROW(nullt.isCardinalityConstraint(), CVC5ApiException); } TEST_F(TestApiBlackTerm, getRealAlgebraicNumber) { d_solver->setOption("produce-models", "true"); d_solver->setLogic("QF_NRA"); Sort realsort = d_tm.getRealSort(); Term x = d_tm.mkConst(realsort, "x"); Term x2 = d_tm.mkTerm(Kind::MULT, {x, x}); Term two = d_tm.mkReal(2, 1); Term eq = d_tm.mkTerm(Kind::EQUAL, {x2, two}); d_solver->assertFormula(eq); // Note that check-sat should only return "sat" if libpoly is enabled. // Otherwise, we do not test the following functionality. if (d_solver->checkSat().isSat()) { // We find a model for (x*x = 2), where x should be a real algebraic number. // We assert that its defining polynomial is non-null and its lower and // upper bounds are real. Term vx = d_solver->getValue(x); ASSERT_TRUE(vx.isRealAlgebraicNumber()); Term y = d_tm.mkVar(realsort, "y"); Term poly = vx.getRealAlgebraicNumberDefiningPolynomial(y); ASSERT_TRUE(!poly.isNull()); Term lb = vx.getRealAlgebraicNumberLowerBound(); ASSERT_TRUE(lb.isRealValue()); Term ub = vx.getRealAlgebraicNumberUpperBound(); ASSERT_TRUE(ub.isRealValue()); // cannot call with non-variable Term yc = d_tm.mkConst(realsort, "y"); ASSERT_THROW(vx.getRealAlgebraicNumberDefiningPolynomial(yc), CVC5ApiException); } } TEST_F(TestApiBlackTerm, getSkolem) { // ordinary variables are not skolems Term x = d_tm.mkConst(d_tm.getIntegerSort(), "x"); ASSERT_FALSE(x.isSkolem()); ASSERT_THROW(x.getSkolemId(), CVC5ApiException); ASSERT_THROW(x.getSkolemIndices(), CVC5ApiException); } TEST_F(TestApiBlackTerm, termScopedToString) { Sort intsort = d_tm.getIntegerSort(); Term x = d_tm.mkConst(intsort, "x"); ASSERT_EQ(x.toString(), "x"); ASSERT_EQ(x.toString(), "x"); } TEST_F(TestApiBlackTerm, toString) { ASSERT_NO_THROW(Term().toString()); Sort intsort = d_tm.getIntegerSort(); Term x = d_tm.mkConst(intsort, "x"); std::stringstream ss; ss << std::vector{x, x}; ss << std::set{x, x}; ss << std::unordered_set{x, x}; } } // namespace test } // namespace cvc5::internal