| // Copyright 2017-2020 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "common/util/expandable_tree_view.h" |
| |
| #include <sstream> |
| #include <vector> |
| |
| #include "absl/strings/str_join.h" |
| #include "absl/strings/string_view.h" |
| #include "common/util/vector_tree.h" |
| #include "common/util/vector_tree_test_util.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| |
| namespace verible { |
| namespace { |
| |
| using ::testing::ElementsAre; |
| using verible::testing::NamedInterval; |
| using verible::testing::VectorTreeTestType; |
| |
| using ExpandableTreeViewTestType = |
| ExpandableTreeView<VectorTree<NamedInterval>>; |
| |
| // Test that basic Tree View operations work on a singleton node. |
| TEST(ExpandableTreeViewTest, RootOnly) { |
| const VectorTreeTestType tree(verible::testing::MakeRootOnlyExampleTree()); |
| const auto &value = tree.Value(); |
| |
| // View testing. |
| const ExpandableTreeViewTestType tree_view(tree); |
| EXPECT_EQ(&tree_view.Value().Value(), &value); |
| EXPECT_TRUE(tree_view.Value().IsExpanded()); |
| |
| // Iterator testing. |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(&*iter, &value); |
| ExpandableTreeViewTestType::iterator copy(iter); |
| |
| ++iter; |
| EXPECT_NE(iter, copy); |
| EXPECT_EQ(iter, end); // There was only one node to visit, the root. |
| } |
| |
| TEST(ExpandableTreeViewTest, OneChildPolicyFullyExpanded) { |
| const auto tree = verible::testing::MakeOneChildPolicyExampleTree(); |
| const ExpandableTreeViewTestType tree_view(tree); |
| |
| // Iterator testing. |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| |
| ASSERT_NE(iter, end); |
| ExpandableTreeViewTestType::iterator copy(iter); |
| EXPECT_EQ(iter->left, 0); |
| EXPECT_EQ(iter->right, 3); |
| // Fully expanded means reaching deepest child first. |
| EXPECT_EQ(iter->name, "gen2"); |
| |
| ++iter; |
| EXPECT_NE(iter, copy); |
| // There was only one node to visit, the only grandchild. |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, OneChildPolicyUnexpanded) { |
| const auto tree = verible::testing::MakeOneChildPolicyExampleTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| tree_view.Value().Unexpand(); // Mark root node as un-expanded. |
| EXPECT_FALSE(tree_view.Value().IsExpanded()); |
| |
| // Iterator testing. |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| |
| ASSERT_NE(iter, end); |
| ExpandableTreeViewTestType::iterator copy(iter); |
| EXPECT_EQ(iter->left, 0); |
| EXPECT_EQ(iter->right, 3); |
| // Unexpanded: skip any of root's children |
| EXPECT_EQ(iter->name, "root"); |
| |
| ++iter; |
| EXPECT_NE(iter, copy); |
| // There was only one node to visit, the root. |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, OneChildPolicyPartiallyExpanded) { |
| const auto tree = verible::testing::MakeOneChildPolicyExampleTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| tree_view[0].Value().Unexpand(); // Mark root node as un-expanded. |
| EXPECT_FALSE(tree_view[0].Value().IsExpanded()); |
| |
| // Iterator testing. |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| |
| ASSERT_NE(iter, end); |
| ExpandableTreeViewTestType::iterator copy(iter); |
| EXPECT_EQ(iter->left, 0); |
| EXPECT_EQ(iter->right, 3); |
| // Partially expanded: don't expand beyond direct child |
| EXPECT_EQ(iter->name, "gen1"); |
| |
| ++iter; |
| EXPECT_NE(iter, copy); |
| // There was only one node to visit, the root's only child. |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, FamilyTreeFullyExpanded) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| const ExpandableTreeViewTestType tree_view(tree); |
| |
| // Fully-expanded, expect to visit all grandchildren, and nothing else. |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child1"); |
| |
| iter++; // post-increment |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child2"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child3"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child4"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, FamilyTreeFullyExpandedStrJoin) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| const ExpandableTreeViewTestType tree_view(tree); |
| |
| std::ostringstream stream; |
| stream << absl::StrJoin(tree_view.begin(), tree_view.end(), "\n", |
| absl::StreamFormatter()); |
| EXPECT_EQ(stream.str(), |
| "(0, 1, child1)\n(1, 2, child2)\n(2, 3, child3)\n(3, 4, child4)"); |
| } |
| |
| TEST(ExpandableTreeViewTest, FamilyTreeUnexpanded) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| tree_view.Value().Unexpand(); // expect to only visit root |
| |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "grandparent"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, FamilyTreeExpandedMixed) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| |
| // Unexpand only one of the parents. |
| tree_view[0].Value().Unexpand(); |
| |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent1"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child3"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child4"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, FamilyTreeExpandedMixed2) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| |
| // Unexpand only one of the parents. |
| tree_view[1].Value().Unexpand(); |
| |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child1"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child2"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent2"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| TEST(ExpandableTreeViewTest, FamilyTreeExpandedOneLevel) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| |
| // Expand only one level. |
| tree_view[0].Value().Unexpand(); |
| tree_view[1].Value().Unexpand(); |
| |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent1"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent2"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| // Tests that function can be applied that un-expands nodes in the tree view. |
| TEST(ExpandableTreeViewTest, FamilyTreeApplyPreOrder) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| |
| std::vector<absl::string_view> visit_order; |
| tree_view.ApplyPreOrder( |
| [=, &visit_order]( |
| VectorTree<TreeViewNodeInfo<VectorTree<NamedInterval>>> &node) { |
| const absl::string_view name = node.Value().Value().name; |
| visit_order.push_back(name); |
| if (name[0] == 'p') { |
| node.Value().Unexpand(); |
| } |
| }); |
| |
| EXPECT_THAT(visit_order, |
| ElementsAre("grandparent", "parent1", "child1", "child2", |
| "parent2", "child3", "child4")); |
| |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent1"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent2"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| // Tests that function can be applied that un-expands nodes in the tree view. |
| TEST(ExpandableTreeViewTest, FamilyTreeApplyPostOrder) { |
| const auto tree = verible::testing::MakeExampleFamilyTree(); |
| ExpandableTreeViewTestType tree_view(tree); |
| |
| std::vector<absl::string_view> visit_order; |
| tree_view.ApplyPostOrder( |
| [=, &visit_order]( |
| VectorTree<TreeViewNodeInfo<VectorTree<NamedInterval>>> &node) { |
| const absl::string_view name = node.Value().Value().name; |
| visit_order.push_back(name); |
| if (name[0] == 'p' && name.back() == '1') { |
| node.Value().Unexpand(); |
| } |
| }); |
| |
| EXPECT_THAT(visit_order, ElementsAre("child1", "child2", "parent1", "child3", |
| "child4", "parent2", "grandparent")); |
| |
| ExpandableTreeViewTestType::iterator iter(tree_view.begin()), |
| end(tree_view.end()); |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "parent1"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child3"); |
| |
| iter++; |
| ASSERT_NE(iter, end); |
| EXPECT_EQ(iter->name, "child4"); |
| |
| iter++; |
| EXPECT_EQ(iter, end); |
| } |
| |
| } // namespace |
| } // namespace verible |