/********************* */ /*! \file expr_public.h ** \verbatim ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Christopher L. Conway ** This file is part of the CVC4 project. ** Copyright (c) 2009-2019 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.\endverbatim ** ** \brief Public black-box testing of CVC4::Expr. ** ** Public black-box testing of CVC4::Expr. **/ #include #include #include #include "base/exception.h" #include "expr/expr_manager.h" #include "expr/expr.h" #include "options/options.h" using namespace CVC4; using namespace CVC4::kind; using namespace std; class ExprPublic : public CxxTest::TestSuite { private: Options opts; ExprManager* d_em; Expr* a_bool; Expr* b_bool; Expr* c_bool_and; Expr* and_op; Expr* plus_op; Type* fun_type; Expr* fun_op; Expr* d_apply_fun_bool; Expr* null; Expr* i1; Expr* i2; Expr* r1; Expr* r2; public: void setUp() override { try { char* argv[2]; argv[0] = strdup(""); argv[1] = strdup("--output-lang=ast"); Options::parseOptions(&opts, 2, argv); free(argv[0]); free(argv[1]); d_em = new ExprManager(opts); a_bool = new Expr(d_em->mkVar("a", d_em->booleanType())); b_bool = new Expr(d_em->mkVar("b", d_em->booleanType())); c_bool_and = new Expr(d_em->mkExpr(AND, *a_bool, *b_bool)); and_op = new Expr(d_em->mkConst(AND)); plus_op = new Expr(d_em->mkConst(PLUS)); fun_type = new Type( d_em->mkFunctionType(d_em->booleanType(), d_em->booleanType())); fun_op = new Expr(d_em->mkVar("f", *fun_type)); d_apply_fun_bool = new Expr(d_em->mkExpr(APPLY_UF, *fun_op, *a_bool)); null = new Expr(); i1 = new Expr(d_em->mkConst(Rational("0"))); i2 = new Expr(d_em->mkConst(Rational(23))); r1 = new Expr(d_em->mkConst(Rational(1, 5))); r2 = new Expr(d_em->mkConst(Rational("0"))); } catch (Exception& e) { cerr << "Exception during setUp():" << endl << e; throw; } } void tearDown() override { try { delete r2; delete r1; delete i2; delete i1; delete null; delete d_apply_fun_bool; delete fun_type; delete fun_op; delete plus_op; delete and_op; delete c_bool_and; delete b_bool; delete a_bool; delete d_em; } catch (Exception& e) { cerr << "Exception during tearDown():" << endl << e; throw; } } void testDefaultCtor() { /* Expr(); */ Expr e; TS_ASSERT(e.isNull()); } void testCtors() { TS_ASSERT(!a_bool->isNull()); TS_ASSERT(!b_bool->isNull()); /* Expr(); */ Expr e; TS_ASSERT(e.isNull()); /* Expr(const Expr& e) */ Expr e2(e); TS_ASSERT(e == e2); TS_ASSERT(e2 == e); TS_ASSERT(!(e2 < e)); TS_ASSERT(!(e < e2)); TS_ASSERT(e.isNull()); TS_ASSERT(e2.isNull()); Expr f = d_em->mkExpr(OR, *a_bool, *b_bool); Expr f2 = f; TS_ASSERT(!f.isNull()); TS_ASSERT(!f2.isNull()); TS_ASSERT(f == f2); TS_ASSERT(f2 == f); TS_ASSERT(!(f2 < f)); TS_ASSERT(!(f < f2)); TS_ASSERT(f == d_em->mkExpr(OR, *a_bool, *b_bool)); } void testAssignment() { /* Expr& operator=(const Expr& e); */ Expr e = d_em->mkExpr(OR, *a_bool, *b_bool); Expr f; TS_ASSERT(f.isNull()); f = e; TS_ASSERT(!f.isNull()); TS_ASSERT(e == f); TS_ASSERT(f == e); TS_ASSERT(!(f < e)); TS_ASSERT(!(e < f)); TS_ASSERT(f == d_em->mkExpr(OR, *a_bool, *b_bool)); } void testEquality() { /* bool operator==(const Expr& e) const; */ /* bool operator!=(const Expr& e) const; */ TS_ASSERT(*a_bool == *a_bool); TS_ASSERT(*b_bool == *b_bool); TS_ASSERT(!(*a_bool != *a_bool)); TS_ASSERT(!(*b_bool != *b_bool)); TS_ASSERT(*a_bool != *b_bool); TS_ASSERT(*b_bool != *a_bool); TS_ASSERT(!(*a_bool == *b_bool)); TS_ASSERT(!(*b_bool == *a_bool)); } void testComparison() { /* bool operator<(const Expr& e) const; */ TS_ASSERT(*null < *a_bool); TS_ASSERT(*null < *b_bool); TS_ASSERT(*null < *c_bool_and); TS_ASSERT(*null < *d_apply_fun_bool); TS_ASSERT(*null < *plus_op); TS_ASSERT(*null < *and_op); TS_ASSERT(*null < *i1); TS_ASSERT(*null < *i2); TS_ASSERT(*null < *r1); TS_ASSERT(*null < *r2); TS_ASSERT(*a_bool < *b_bool); TS_ASSERT(*a_bool < *c_bool_and); TS_ASSERT(*a_bool < *d_apply_fun_bool); TS_ASSERT(!(*b_bool < *a_bool)); TS_ASSERT(!(*c_bool_and < *a_bool)); TS_ASSERT(!(*d_apply_fun_bool < *a_bool)); TS_ASSERT(*b_bool < *c_bool_and); TS_ASSERT(*b_bool < *d_apply_fun_bool); TS_ASSERT(!(*c_bool_and < *b_bool)); TS_ASSERT(!(*d_apply_fun_bool < *b_bool)); TS_ASSERT(*c_bool_and < *d_apply_fun_bool); TS_ASSERT(!(*d_apply_fun_bool < *c_bool_and)); TS_ASSERT(*and_op < *c_bool_and); TS_ASSERT(*and_op < *d_apply_fun_bool); TS_ASSERT(*plus_op < *d_apply_fun_bool); TS_ASSERT(!(*c_bool_and < *and_op)); TS_ASSERT(!(*d_apply_fun_bool < *and_op)); TS_ASSERT(!(*d_apply_fun_bool < *plus_op)); TS_ASSERT(!(*null < *null)); TS_ASSERT(!(*a_bool < *a_bool)); TS_ASSERT(!(*b_bool < *b_bool)); TS_ASSERT(!(*c_bool_and < *c_bool_and)); TS_ASSERT(!(*plus_op < *plus_op)); TS_ASSERT(!(*and_op < *and_op)); TS_ASSERT(!(*d_apply_fun_bool < *d_apply_fun_bool)); } void testGetKind() { /* Kind getKind() const; */ TS_ASSERT(a_bool->getKind() == VARIABLE); TS_ASSERT(b_bool->getKind() == VARIABLE); TS_ASSERT(c_bool_and->getKind() == AND); TS_ASSERT(and_op->getKind() == BUILTIN); TS_ASSERT(plus_op->getKind() == BUILTIN); TS_ASSERT(d_apply_fun_bool->getKind() == APPLY_UF); TS_ASSERT(null->getKind() == NULL_EXPR); TS_ASSERT(i1->getKind() == CONST_RATIONAL); TS_ASSERT(i2->getKind() == CONST_RATIONAL); TS_ASSERT(r1->getKind() == CONST_RATIONAL); TS_ASSERT(r2->getKind() == CONST_RATIONAL); } void testGetNumChildren() { /* size_t getNumChildren() const; */ TS_ASSERT(a_bool->getNumChildren() == 0); TS_ASSERT(b_bool->getNumChildren() == 0); TS_ASSERT(c_bool_and->getNumChildren() == 2); TS_ASSERT(and_op->getNumChildren() == 0); TS_ASSERT(plus_op->getNumChildren() == 0); TS_ASSERT(d_apply_fun_bool->getNumChildren() == 1); TS_ASSERT(null->getNumChildren() == 0); TS_ASSERT(i1->getNumChildren() == 0); TS_ASSERT(i2->getNumChildren() == 0); TS_ASSERT(r1->getNumChildren() == 0); TS_ASSERT(r2->getNumChildren() == 0); } void testOperatorFunctions() { /* bool hasOperator() const; */ /* Expr getOperator() const; */ TS_ASSERT(!a_bool->hasOperator()); TS_ASSERT(!b_bool->hasOperator()); TS_ASSERT(c_bool_and->hasOperator()); TS_ASSERT(!and_op->hasOperator()); TS_ASSERT(!plus_op->hasOperator()); TS_ASSERT(d_apply_fun_bool->hasOperator()); TS_ASSERT(!null->hasOperator()); TS_ASSERT_THROWS(a_bool->getOperator(), IllegalArgumentException&); TS_ASSERT_THROWS(b_bool->getOperator(), IllegalArgumentException&); TS_ASSERT(c_bool_and->getOperator() == *and_op); TS_ASSERT_THROWS(plus_op->getOperator(), IllegalArgumentException&); TS_ASSERT_THROWS(and_op->getOperator(), IllegalArgumentException&); TS_ASSERT(d_apply_fun_bool->getOperator() == *fun_op); TS_ASSERT_THROWS(null->getOperator(), IllegalArgumentException&); } void testGetType() { /* Type getType(); */ TS_ASSERT(a_bool->getType(false) == d_em->booleanType()); TS_ASSERT(a_bool->getType(true) == d_em->booleanType()); TS_ASSERT(b_bool->getType(false) == d_em->booleanType()); TS_ASSERT(b_bool->getType(true) == d_em->booleanType()); TS_ASSERT_THROWS(d_em->mkExpr(MULT, *a_bool, *b_bool).getType(true), TypeCheckingException&); // These need better support for operators // TS_ASSERT(and_op->getType().isNull()); // TS_ASSERT(plus_op->getType().isNull()); TS_ASSERT(d_apply_fun_bool->getType() == d_em->booleanType()); TS_ASSERT(i1->getType().isInteger()); TS_ASSERT(i2->getType().isInteger()); TS_ASSERT(r1->getType().isReal()); TS_ASSERT(r2->getType().isReal()); } void testToString() { /* std::string toString() const; */ TS_ASSERT(a_bool->toString() == "a"); TS_ASSERT(b_bool->toString() == "b"); TS_ASSERT(c_bool_and->toString() == "(AND a b)"); TS_ASSERT(and_op->toString() == "(BUILTIN AND)"); TS_ASSERT(plus_op->toString() == "(BUILTIN PLUS)"); TS_ASSERT(d_apply_fun_bool->toString() == "(APPLY_UF f a)"); TS_ASSERT(null->toString() == "null"); TS_ASSERT(i1->toString() == "(CONST_RATIONAL 0)"); TS_ASSERT(i2->toString() == "(CONST_RATIONAL 23)"); TS_ASSERT(r1->toString() == "(CONST_RATIONAL 1/5)"); TS_ASSERT(r2->toString() == "(CONST_RATIONAL 0)"); } void testToStream() { /* void toStream(std::ostream& out) const; */ stringstream sa, sb, sc, smult, splus, sd, snull; stringstream si1, si2, sr1, sr2; a_bool->toStream(sa); b_bool->toStream(sb); c_bool_and->toStream(sc); and_op->toStream(smult); plus_op->toStream(splus); d_apply_fun_bool->toStream(sd); null->toStream(snull); i1->toStream(si1); i2->toStream(si2); r1->toStream(sr1); r2->toStream(sr2); TS_ASSERT(sa.str() == "a"); TS_ASSERT(sb.str() == "b"); TS_ASSERT(sc.str() == "(AND a b)"); TS_ASSERT(smult.str() == "(BUILTIN AND)"); TS_ASSERT(splus.str() == "(BUILTIN PLUS)"); TS_ASSERT(sd.str() == "(APPLY_UF f a)"); TS_ASSERT(snull.str() == "null"); TS_ASSERT(si1.str() == "(CONST_RATIONAL 0)"); TS_ASSERT(si2.str() == "(CONST_RATIONAL 23)"); TS_ASSERT(sr1.str() == "(CONST_RATIONAL 1/5)"); TS_ASSERT(sr2.str() == "(CONST_RATIONAL 0)"); } void testIsNull() { /* bool isNull() const; */ TS_ASSERT(!a_bool->isNull()); TS_ASSERT(!b_bool->isNull()); TS_ASSERT(!c_bool_and->isNull()); TS_ASSERT(!and_op->isNull()); TS_ASSERT(!plus_op->isNull()); TS_ASSERT(!d_apply_fun_bool->isNull()); TS_ASSERT(null->isNull()); } void testIsConst() { /* bool isConst() const; */ //Debug.on("isConst"); TS_ASSERT(!a_bool->isConst()); TS_ASSERT(!b_bool->isConst()); TS_ASSERT(!c_bool_and->isConst()); TS_ASSERT(and_op->isConst()); TS_ASSERT(plus_op->isConst()); TS_ASSERT(!d_apply_fun_bool->isConst()); TS_ASSERT(!null->isConst()); // more complicated "constants" exist in datatypes and arrays theories Datatype list(d_em, "list"); DatatypeConstructor consC("cons"); consC.addArg("car", d_em->integerType()); consC.addArg("cdr", DatatypeSelfType()); list.addConstructor(consC); list.addConstructor(DatatypeConstructor("nil")); DatatypeType listType = d_em->mkDatatypeType(list); Expr cons = listType.getDatatype().getConstructor("cons"); Expr nil = listType.getDatatype().getConstructor("nil"); Expr x = d_em->mkVar("x", d_em->integerType()); Expr cons_x_nil = d_em->mkExpr(APPLY_CONSTRUCTOR, cons, x, d_em->mkExpr(APPLY_CONSTRUCTOR, nil)); Expr cons_1_nil = d_em->mkExpr(APPLY_CONSTRUCTOR, cons, d_em->mkConst(Rational(1)), d_em->mkExpr(APPLY_CONSTRUCTOR, nil)); Expr cons_1_cons_2_nil = d_em->mkExpr(APPLY_CONSTRUCTOR, cons, d_em->mkConst(Rational(1)), d_em->mkExpr(APPLY_CONSTRUCTOR, cons, d_em->mkConst(Rational(2)), d_em->mkExpr(APPLY_CONSTRUCTOR, nil))); TS_ASSERT(d_em->mkExpr(APPLY_CONSTRUCTOR, nil).isConst()); TS_ASSERT(!cons_x_nil.isConst()); TS_ASSERT(cons_1_nil.isConst()); TS_ASSERT(cons_1_cons_2_nil.isConst()); ArrayType arrType = d_em->mkArrayType(d_em->integerType(), d_em->integerType()); Expr zero = d_em->mkConst(Rational(0)); Expr one = d_em->mkConst(Rational(1)); Expr storeAll = d_em->mkConst(ArrayStoreAll(arrType, zero)); TS_ASSERT(storeAll.isConst()); Expr arr = d_em->mkExpr(STORE, storeAll, zero, zero); TS_ASSERT(!arr.isConst()); arr = d_em->mkExpr(STORE, storeAll, zero, one); TS_ASSERT(arr.isConst()); Expr arr2 = d_em->mkExpr(STORE, arr, one, zero); TS_ASSERT(!arr2.isConst()); arr2 = d_em->mkExpr(STORE, arr, one, one); TS_ASSERT(arr2.isConst()); arr2 = d_em->mkExpr(STORE, arr, zero, one); TS_ASSERT(!arr2.isConst()); arrType = d_em->mkArrayType(d_em->mkBitVectorType(1), d_em->mkBitVectorType(1)); zero = d_em->mkConst(BitVector(1,unsigned(0))); one = d_em->mkConst(BitVector(1,unsigned(1))); storeAll = d_em->mkConst(ArrayStoreAll(arrType, zero)); TS_ASSERT(storeAll.isConst()); arr = d_em->mkExpr(STORE, storeAll, zero, zero); TS_ASSERT(!arr.isConst()); arr = d_em->mkExpr(STORE, storeAll, zero, one); TS_ASSERT(arr.isConst()); arr2 = d_em->mkExpr(STORE, arr, one, zero); TS_ASSERT(!arr2.isConst()); arr2 = d_em->mkExpr(STORE, arr, one, one); TS_ASSERT(!arr2.isConst()); arr2 = d_em->mkExpr(STORE, arr, zero, one); TS_ASSERT(!arr2.isConst()); } void testGetConst() { /* template const T& getConst() const; */ TS_ASSERT_THROWS(a_bool->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(b_bool->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(c_bool_and->getConst(), IllegalArgumentException&); TS_ASSERT(and_op->getConst() == AND); TS_ASSERT_THROWS(and_op->getConst(), IllegalArgumentException&); TS_ASSERT(plus_op->getConst() == PLUS); TS_ASSERT_THROWS(plus_op->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(d_apply_fun_bool->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(null->getConst(), IllegalArgumentException&); TS_ASSERT(i1->getConst() == 0); TS_ASSERT(i2->getConst() == 23); TS_ASSERT(r1->getConst() == Rational(1, 5)); TS_ASSERT(r2->getConst() == Rational("0")); TS_ASSERT_THROWS(i1->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(i2->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(r1->getConst(), IllegalArgumentException&); TS_ASSERT_THROWS(r2->getConst(), IllegalArgumentException&); } void testGetExprManager() { /* ExprManager* getExprManager() const; */ TS_ASSERT(a_bool->getExprManager() == d_em); TS_ASSERT(b_bool->getExprManager() == d_em); TS_ASSERT(c_bool_and->getExprManager() == d_em); TS_ASSERT(and_op->getExprManager() == d_em); TS_ASSERT(plus_op->getExprManager() == d_em); TS_ASSERT(d_apply_fun_bool->getExprManager() == d_em); TS_ASSERT(null->getExprManager() == NULL); TS_ASSERT(i1->getExprManager() == d_em); TS_ASSERT(i2->getExprManager() == d_em); TS_ASSERT(r1->getExprManager() == d_em); TS_ASSERT(r2->getExprManager() == d_em); } };