From 981f9583aecb53fc50d75b0eaa689d1b1b1839fc Mon Sep 17 00:00:00 2001 From: mkamonMdt Date: Wed, 9 Dec 2020 16:05:46 +0100 Subject: [PATCH] [EGD-4828] Add GUI tests for DOM flow * `DepthFirstItemTree` tests - basic traverse functionalities * `GuiVisitor` tests - basic double dispatch calls * DOM serializer tests - basic serialization functionalities --- module-gui/test/test-google/CMakeLists.txt | 5 + .../test-gui-depthfirst-itemtree.cpp | 171 ++++++++++++++++++ .../test/test-google/test-gui-dom-dump.cpp | 60 ++++++ .../test-google/test-gui-visitor-call.cpp | 77 ++++++++ 4 files changed, 313 insertions(+) create mode 100644 module-gui/test/test-google/test-gui-depthfirst-itemtree.cpp create mode 100644 module-gui/test/test-google/test-gui-dom-dump.cpp create mode 100644 module-gui/test/test-google/test-gui-visitor-call.cpp diff --git a/module-gui/test/test-google/CMakeLists.txt b/module-gui/test/test-google/CMakeLists.txt index 622387689448cdbafe4fe161406f2c079c2aaf6b..fd63258a6019021bc4e6eae8c05f57564ccae796 100644 --- a/module-gui/test/test-google/CMakeLists.txt +++ b/module-gui/test/test-google/CMakeLists.txt @@ -1,10 +1,14 @@ project(googletest-gui) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) +include_directories(${gmock_SOURCE_DIR}/include ${gmock_SOURCE_DIR}) add_executable(${PROJECT_NAME} EXCLUDE_FROM_ALL test-gui-listview.cpp test-gui-boxlayout.cpp + test-gui-depthfirst-itemtree.cpp + test-gui-visitor-call.cpp + test-gui-dom-dump.cpp ../mock/TestListViewProvider.cpp ) @@ -20,6 +24,7 @@ target_link_directories(${PROJECT_NAME} PUBLIC "${PROJECT_LIB_DIRECTORY}") target_link_libraries(${PROJECT_NAME} PUBLIC module-utils module-gui) target_link_libraries(${PROJECT_NAME} PUBLIC gtest gtest_main) +target_link_libraries(${PROJECT_NAME} PUBLIC gmock gmock_main) add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} diff --git a/module-gui/test/test-google/test-gui-depthfirst-itemtree.cpp b/module-gui/test/test-google/test-gui-depthfirst-itemtree.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a70be22ce80f74f2f20190fae284fc921644c342 --- /dev/null +++ b/module-gui/test/test-google/test-gui-depthfirst-itemtree.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "gtest/gtest.h" + +#include "visitor/DepthFirstItemTree.hpp" +#include "Item.hpp" + +#include +#include + +class DepthFirstTreeTesting : public ::testing::Test +{ + + gui::Item root; + std::vector firstLevelChildren; + std::vector secondLevelChildren; + + void addItem(gui::Item *parent, std::vector &childrenList) + { + auto item = new gui::Item(); + parent->addWidget(item); + childrenList.push_back(item); + } + + protected: + DepthFirstTreeTesting(gui::DepthFirstItemTree::TraverseMode mode) + { + // adding 1st-level children to root + addItem(&root, firstLevelChildren); + addItem(&root, firstLevelChildren); + addItem(&root, firstLevelChildren); + + // adding 2nd-level children + auto child = firstLevelChildren.back(); + addItem(child, secondLevelChildren); + addItem(child, secondLevelChildren); + addItem(child, secondLevelChildren); + child = firstLevelChildren.front(); + addItem(child, secondLevelChildren); + addItem(child, secondLevelChildren); + addItem(child, secondLevelChildren); + + tree = std::make_unique(root, mode); + } + + public: + static constexpr auto rootLevel = 0; + static constexpr auto firstLevel = 1; + static constexpr auto secondLevel = 2; + + std::unique_ptr tree; + + gui::Item *getRoot() + { + return &root; + } + const std::vector &get1stLevelChildren() const + { + return firstLevelChildren; + } + const std::vector &get2ndtLevelChildren() const + { + return secondLevelChildren; + } +}; + +class DFTPreOrderTesting : public DepthFirstTreeTesting +{ + protected: + DFTPreOrderTesting() : DepthFirstTreeTesting(gui::DepthFirstItemTree::TraverseMode::PreOrder) + {} +}; + +class DFTPostOrderTesting : public DepthFirstTreeTesting +{ + + protected: + DFTPostOrderTesting() : DepthFirstTreeTesting(gui::DepthFirstItemTree::TraverseMode::PostOrder) + {} +}; + +TEST_F(DFTPreOrderTesting, RootAtFrontTest) +{ + ASSERT_TRUE(tree->hasNext()); + auto node = tree->getNext(); + ASSERT_EQ(node.getLevel(), rootLevel); + ASSERT_EQ(&node.getItem(), getRoot()); +} + +TEST_F(DFTPreOrderTesting, SecondLevelChildAtEndTest) +{ + ASSERT_TRUE(tree->hasNext()); + while (tree->hasNext()) { + auto node = tree->getNext(); + if (!tree->hasNext()) { + ASSERT_EQ(node.getLevel(), secondLevel); + } + } +} + +TEST_F(DFTPreOrderTesting, ExpectedNodesCountTest) +{ + const int expectedCount = 1 + get1stLevelChildren().size() + get2ndtLevelChildren().size(); + int currentCount = 0; + while (tree->hasNext()) { + auto node = tree->getNext(); + EXPECT_GT(node.getLevel(), -1); + currentCount++; + } + ASSERT_EQ(expectedCount, currentCount); +} + +TEST_F(DFTPreOrderTesting, ExpectedLevelOrderTest) +{ + ASSERT_TRUE(tree->hasNext()); + std::list expectedLevelOrder = {0, 1, 2, 2, 2, 1, 1, 2, 2, 2}; + + while (tree->hasNext()) { + ASSERT_GT(expectedLevelOrder.size(), 0); + auto node = tree->getNext(); + EXPECT_EQ(node.getLevel(), expectedLevelOrder.front()); + expectedLevelOrder.pop_front(); + } + ASSERT_EQ(expectedLevelOrder.size(), 0); +} + +TEST_F(DFTPostOrderTesting, RootAtEndTest) +{ + ASSERT_TRUE(tree->hasNext()); + while (tree->hasNext()) { + auto node = tree->getNext(); + if (!tree->hasNext()) { + ASSERT_EQ(node.getLevel(), rootLevel); + ASSERT_EQ(&node.getItem(), getRoot()); + } + } +} + +TEST_F(DFTPostOrderTesting, SecondLevelChildAtFrontTest) +{ + ASSERT_TRUE(tree->hasNext()); + auto node = tree->getNext(); + ASSERT_EQ(node.getLevel(), secondLevel); +} + +TEST_F(DFTPostOrderTesting, ExpectedNodesCountTest) +{ + const int expectedCount = 1 + get1stLevelChildren().size() + get2ndtLevelChildren().size(); + int currentCount = 0; + while (tree->hasNext()) { + auto node = tree->getNext(); + EXPECT_GT(node.getLevel(), -1); + currentCount++; + } + ASSERT_EQ(expectedCount, currentCount); +} + +TEST_F(DFTPostOrderTesting, ExpectedLevelOrderTest) +{ + ASSERT_TRUE(tree->hasNext()); + std::list expectedLevelOrder = {2, 2, 2, 1, 1, 2, 2, 2, 1, 0}; + + while (tree->hasNext()) { + ASSERT_GT(expectedLevelOrder.size(), 0); + auto node = tree->getNext(); + EXPECT_EQ(node.getLevel(), expectedLevelOrder.front()); + expectedLevelOrder.pop_front(); + } + ASSERT_EQ(expectedLevelOrder.size(), 0); +} diff --git a/module-gui/test/test-google/test-gui-dom-dump.cpp b/module-gui/test/test-google/test-gui-dom-dump.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7df74af69b27f6ab32cbae1ff64c165f35fc18a7 --- /dev/null +++ b/module-gui/test/test-google/test-gui-dom-dump.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "gtest/gtest.h" +#include + +#include "gui/dom/Item2JsonSerializer.hpp" + +#include "Item.hpp" +#include "Rect.hpp" +#include "Label.hpp" +#include "Text.hpp" +#include "FontManager.hpp" +#include + +class Item2JsonSerializerTester : public ::testing::Test +{ + protected: + static constexpr auto testTextValue1 = "Some text 1"; + static constexpr auto testTextValue2 = "Some text 2"; + Item2JsonSerializerTester() + { + auto &fm = gui::FontManager::getInstance(); + fm.init("assets"); + + root.addWidget(new gui::Text(nullptr, 0, 0, 0, 0, testTextValue1)); + root.addWidget(new gui::Label(nullptr, 0, 0, 0, 0, testTextValue2)); + + serializer.traverse(root); + std::stringstream ss; + serializer.dump(ss); + serializedItem = ss.str(); + } + gui::Item2JsonSerializer serializer; + + public: + gui::Item root; + std::string serializedItem; +}; + +TEST_F(Item2JsonSerializerTester, ChildrenCountTest) +{ + constexpr auto expectedRootChildrenCountPhrase = "\"ChildrenCount\": 2"; + constexpr auto expectedChildChildrenCountPhrase = "\"ChildrenCount\": 0"; + + const auto rootPhrasePos = serializedItem.find(expectedRootChildrenCountPhrase); + ASSERT_NE(rootPhrasePos, std::string::npos); + + const auto firstChildPhrasePos = serializedItem.find(expectedChildChildrenCountPhrase); + ASSERT_NE(rootPhrasePos, std::string::npos); + + const auto secondChildPhrasePos = serializedItem.find(expectedChildChildrenCountPhrase, firstChildPhrasePos); + ASSERT_NE(secondChildPhrasePos, std::string::npos); +} + +TEST_F(Item2JsonSerializerTester, TextValueTest) +{ + ASSERT_NE(serializedItem.find(testTextValue1), std::string::npos); + ASSERT_NE(serializedItem.find(testTextValue2), std::string::npos); +} diff --git a/module-gui/test/test-google/test-gui-visitor-call.cpp b/module-gui/test/test-google/test-gui-visitor-call.cpp new file mode 100644 index 0000000000000000000000000000000000000000..032eb0f5c0f0b949b756b0979dce7fbed8d0eeb7 --- /dev/null +++ b/module-gui/test/test-google/test-gui-visitor-call.cpp @@ -0,0 +1,77 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "visitor/GuiVisitor.hpp" +#include "Text.hpp" +#include "Item.hpp" +#include "Rect.hpp" +#include "Label.hpp" +#include "Window.hpp" +#include "BottomBar.hpp" +#include "TopBar.hpp" + +using ::testing::Matcher; +using ::testing::Ref; + +class VisitorMock : public gui::GuiVisitor +{ + public: + MOCK_METHOD1(visit, void(gui::Item &item)); + MOCK_METHOD1(visit, void(gui::Rect &item)); + MOCK_METHOD1(visit, void(gui::Text &item)); + MOCK_METHOD1(visit, void(gui::Window &item)); + MOCK_METHOD1(visit, void(gui::Label &item)); + MOCK_METHOD1(visit, void(gui::BottomBar &item)); + MOCK_METHOD1(visit, void(gui::TopBar &item)); +}; + +class CustomRect : public gui::Rect +{}; + +struct VisitAcceptors : public ::testing::Test +{ + gui::Item item; + gui::Rect rect; + + gui::Text text; + CustomRect customRect; +}; + +TEST_F(VisitAcceptors, VisitCallOnItem) +{ + auto &testSubject = item; + VisitorMock visitor; + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(1); + testSubject.accept(visitor); +} + +TEST_F(VisitAcceptors, VisitCallOnRect) +{ + auto &testSubject = rect; + VisitorMock visitor; + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(0); + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(1); + testSubject.accept(visitor); +} + +TEST_F(VisitAcceptors, VisitCallOnText) +{ + auto &testSubject = text; + VisitorMock visitor; + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(0); + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(0); + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(1); + testSubject.accept(visitor); +} + +TEST_F(VisitAcceptors, VisitCallOnCustomRect) +{ + auto &testSubject = customRect; + VisitorMock visitor; + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(0); + EXPECT_CALL(visitor, visit(Matcher(Ref(testSubject)))).Times(1); + testSubject.accept(visitor); +}