/****************************************************************************** * Top contributors (to current version): * Aina Niemetz, Alex Ozdemir, Andres Noetzli * * 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 node traversal iterators. */ #include #include #include #include #include #include #include "expr/node.h" #include "expr/node_builder.h" #include "expr/node_manager.h" #include "expr/node_traversal.h" #include "expr/node_value.h" #include "test_node.h" namespace cvc5::internal { namespace test { class TestNodeBlackNodeTraversalPostorder : public TestNode { }; class TestNodeBlackNodeTraversalPreorder : public TestNode { }; TEST_F(TestNodeBlackNodeTraversalPostorder, preincrement_iteration) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); auto traversal = NodeDfsIterable(cnd, VisitOrder::POSTORDER); NodeDfsIterator i = traversal.begin(); NodeDfsIterator end = traversal.end(); ASSERT_EQ(*i, tb); ASSERT_FALSE(i == end); ++i; ASSERT_EQ(*i, eb); ASSERT_FALSE(i == end); ++i; ASSERT_EQ(*i, cnd); ASSERT_FALSE(i == end); ++i; ASSERT_TRUE(i == end); } TEST_F(TestNodeBlackNodeTraversalPostorder, postincrement_iteration) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); auto traversal = NodeDfsIterable(cnd, VisitOrder::POSTORDER); NodeDfsIterator i = traversal.begin(); NodeDfsIterator end = traversal.end(); ASSERT_EQ(*(i++), tb); ASSERT_EQ(*(i++), eb); ASSERT_EQ(*(i++), cnd); ASSERT_TRUE(i == end); } TEST_F(TestNodeBlackNodeTraversalPostorder, postorder_is_default) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); auto traversal = NodeDfsIterable(cnd); NodeDfsIterator i = traversal.begin(); NodeDfsIterator end = traversal.end(); ASSERT_EQ(*i, tb); ASSERT_FALSE(i == end); } TEST_F(TestNodeBlackNodeTraversalPostorder, range_for_loop) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); size_t count = 0; for (auto i : NodeDfsIterable(cnd, VisitOrder::POSTORDER)) { ++count; } ASSERT_EQ(count, 3); } TEST_F(TestNodeBlackNodeTraversalPostorder, count_if_with_loop) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); size_t count = 0; for (auto i : NodeDfsIterable(cnd, VisitOrder::POSTORDER)) { if (i.isConst()) { ++count; } } ASSERT_EQ(count, 2); } TEST_F(TestNodeBlackNodeTraversalPostorder, stl_count_if) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); auto traversal = NodeDfsIterable(top, VisitOrder::POSTORDER); size_t count = std::count_if( traversal.begin(), traversal.end(), [](TNode n) { return n.isConst(); }); ASSERT_EQ(count, 2); } TEST_F(TestNodeBlackNodeTraversalPostorder, stl_copy) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); std::vector expected = {tb, eb, cnd, top}; auto traversal = NodeDfsIterable(top, VisitOrder::POSTORDER); std::vector actual; std::copy(traversal.begin(), traversal.end(), std::back_inserter(actual)); ASSERT_EQ(actual, expected); } TEST_F(TestNodeBlackNodeTraversalPostorder, skip_if) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); std::vector expected = {top}; auto traversal = NodeDfsIterable( top, VisitOrder::POSTORDER, [&cnd](TNode n) { return n == cnd; }); std::vector actual; std::copy(traversal.begin(), traversal.end(), std::back_inserter(actual)); ASSERT_EQ(actual, expected); } TEST_F(TestNodeBlackNodeTraversalPostorder, skip_all) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); std::vector expected = {}; auto traversal = NodeDfsIterable(top, VisitOrder::POSTORDER, [](TNode n) { return true; }); std::vector actual; std::copy(traversal.begin(), traversal.end(), std::back_inserter(actual)); ASSERT_EQ(actual, expected); } TEST_F(TestNodeBlackNodeTraversalPreorder, preincrement_iteration) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); auto traversal = NodeDfsIterable(cnd, VisitOrder::PREORDER); NodeDfsIterator i = traversal.begin(); NodeDfsIterator end = traversal.end(); ASSERT_EQ(*i, cnd); ASSERT_FALSE(i == end); ++i; ASSERT_EQ(*i, tb); ASSERT_FALSE(i == end); ++i; ASSERT_EQ(*i, eb); ASSERT_FALSE(i == end); ++i; ASSERT_TRUE(i == end); } TEST_F(TestNodeBlackNodeTraversalPreorder, postincrement_iteration) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); auto traversal = NodeDfsIterable(cnd, VisitOrder::PREORDER); NodeDfsIterator i = traversal.begin(); NodeDfsIterator end = traversal.end(); ASSERT_EQ(*(i++), cnd); ASSERT_EQ(*(i++), tb); ASSERT_EQ(*(i++), eb); ASSERT_TRUE(i == end); } TEST_F(TestNodeBlackNodeTraversalPreorder, range_for_loop) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); size_t count = 0; for (auto i : NodeDfsIterable(cnd, VisitOrder::PREORDER)) { ++count; } ASSERT_EQ(count, 3); } TEST_F(TestNodeBlackNodeTraversalPreorder, count_if_with_loop) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); size_t count = 0; for (auto i : NodeDfsIterable(cnd, VisitOrder::PREORDER)) { if (i.isConst()) { ++count; } } ASSERT_EQ(count, 2); } TEST_F(TestNodeBlackNodeTraversalPreorder, stl_count_if) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); auto traversal = NodeDfsIterable(top, VisitOrder::PREORDER); size_t count = std::count_if( traversal.begin(), traversal.end(), [](TNode n) { return n.isConst(); }); ASSERT_EQ(count, 2); } TEST_F(TestNodeBlackNodeTraversalPreorder, stl_copy) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); std::vector expected = {top, cnd, tb, eb}; auto traversal = NodeDfsIterable(top, VisitOrder::PREORDER); std::vector actual; std::copy(traversal.begin(), traversal.end(), std::back_inserter(actual)); ASSERT_EQ(actual, expected); } TEST_F(TestNodeBlackNodeTraversalPreorder, skip_if) { const Node tb = d_nodeManager->mkConst(true); const Node eb = d_nodeManager->mkConst(false); const Node cnd = d_nodeManager->mkNode(Kind::XOR, tb, eb); const Node top = d_nodeManager->mkNode(Kind::XOR, cnd, cnd); std::vector expected = {top, cnd, eb}; auto traversal = NodeDfsIterable( top, VisitOrder::PREORDER, [&tb](TNode n) { return n == tb; }); std::vector actual; std::copy(traversal.begin(), traversal.end(), std::back_inserter(actual)); ASSERT_EQ(actual, expected); } } // namespace test } // namespace cvc5::internal