From 8b74cd3255886d0d9c637d6b3f1668bc167ac36c Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 16 Mar 2023 15:39:28 -0500 Subject: [PATCH] App/Toponaming: Add tests to MappedElement --- src/App/CMakeLists.txt | 4 +- src/App/MappedElement.cpp | 25 ++++++- src/App/MappedElement.h | 42 ++++++----- tests/src/App/CMakeLists.txt | 1 + tests/src/App/MappedElement.cpp | 129 ++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 24 deletions(-) create mode 100644 tests/src/App/MappedElement.cpp diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt index 4baebeacc1..4326b562f0 100644 --- a/src/App/CMakeLists.txt +++ b/src/App/CMakeLists.txt @@ -264,6 +264,7 @@ SET(FreeCADApp_CPP_SRCS ComplexGeoDataPyImp.cpp Enumeration.cpp IndexedName.cpp + MappedElement.cpp MappedName.cpp Material.cpp MaterialPyImp.cpp @@ -284,6 +285,7 @@ SET(FreeCADApp_HPP_SRCS Enumeration.h IndexedName.h MappedName.h + MappedElement.h Material.h Metadata.h ) @@ -296,7 +298,7 @@ SET(FreeCADApp_SRCS FreeCADTest.py PreCompiled.cpp PreCompiled.h - MappedElement.cpp MappedElement.h) +) if(FREECAD_USE_PCH) add_definitions(-D_PreComp_) diff --git a/src/App/MappedElement.cpp b/src/App/MappedElement.cpp index 62ba30a58b..14eb6f99ba 100644 --- a/src/App/MappedElement.cpp +++ b/src/App/MappedElement.cpp @@ -1,5 +1,24 @@ -// -// Created by Chris Hennes on 3/14/23. -// +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************************************** + * * + * Copyright (c) 2022 Zheng, Lei (realthunder) * + * Copyright (c) 2023 FreeCAD Project Association * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it under the terms of the * + * GNU Lesser General Public License as published by the Free Software Foundation, either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License along with * + * FreeCAD. If not, see . * + * * + **************************************************************************************************/ + +#include "PreCompiled.h" #include "MappedElement.h" diff --git a/src/App/MappedElement.h b/src/App/MappedElement.h index 2e4b99ffa1..ef5784d7d9 100644 --- a/src/App/MappedElement.h +++ b/src/App/MappedElement.h @@ -23,13 +23,6 @@ #ifndef APP_MAPPED_ELEMENT_H #define APP_MAPPED_ELEMENT_H -#include -#include -#include -#include -#include -#include -#include #include "ComplexGeoData.h" #include "IndexedName.h" #include "MappedName.h" @@ -42,6 +35,9 @@ class DocumentObject; namespace Data { +/// A MappedElement combines a MappedName and and IndexedName into a single entity and provides +/// simple comparison operators for the combination (including operator< so that the entity can +/// be sorted, or used in sorted containers). struct AppExport MappedElement { IndexedName index; @@ -49,42 +45,48 @@ struct AppExport MappedElement MappedElement() = default; - MappedElement(const IndexedName & idx, MappedName n) - : index(idx), name(std::move(n)) + MappedElement(const IndexedName& idx, MappedName n) + : index(idx), + name(std::move(n)) {} - MappedElement(MappedName n, const IndexedName & idx) - : index(idx), name(std::move(n)) + MappedElement(MappedName n, const IndexedName& idx) + : index(idx), + name(std::move(n)) {} ~MappedElement() = default; - MappedElement(const MappedElement & other) = default; + MappedElement(const MappedElement& other) = default; - MappedElement(MappedElement && other) noexcept - : index(other.index), name(std::move(other.name)) + MappedElement(MappedElement&& other) noexcept + : index(other.index), + name(std::move(other.name)) {} - MappedElement & operator=(MappedElement && other) noexcept + MappedElement& operator=(MappedElement&& other) noexcept { this->index = other.index; this->name = std::move(other.name); return *this; } - MappedElement & operator=(const MappedElement & other) = default; + MappedElement& operator=(const MappedElement& other) = default; - bool operator==(const MappedElement &other) const + bool operator==(const MappedElement& other) const { return this->index == other.index && this->name == other.name; } - bool operator!=(const MappedElement &other) const + bool operator!=(const MappedElement& other) const { return this->index != other.index || this->name != other.name; } - bool operator<(const MappedElement &other) const + /// For sorting purposes, one MappedElement is considered "less" than another if its index + /// compares less (which is first alphabetical, and then by numeric index). If the index of this + /// MappedElement is the same, then the names are compared lexicographically. + bool operator<(const MappedElement& other) const { int res = this->index.compare(other.index); if (res < 0) { @@ -97,7 +99,7 @@ struct AppExport MappedElement } }; -} //namespace Data +}// namespace Data #endif// APP_MAPPED_ELEMENT_H diff --git a/tests/src/App/CMakeLists.txt b/tests/src/App/CMakeLists.txt index ac4f46bc81..e159b934e5 100644 --- a/tests/src/App/CMakeLists.txt +++ b/tests/src/App/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/ElementMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/IndexedName.cpp ${CMAKE_CURRENT_SOURCE_DIR}/License.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MappedElement.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MappedName.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Metadata.cpp ) diff --git a/tests/src/App/MappedElement.cpp b/tests/src/App/MappedElement.cpp new file mode 100644 index 0000000000..9fc87b31f1 --- /dev/null +++ b/tests/src/App/MappedElement.cpp @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "gtest/gtest.h" + +#include "App/IndexedName.h" +#include "App/MappedElement.h" + +class MappedElementTest: public ::testing::Test +{ +protected: + // void SetUp() override {} + + // void TearDown() override {} + + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) + static Data::MappedElement givenMappedElement(const char* index, const char* name) + { + Data::IndexedName indexedName {index}; + Data::MappedName mappedName {name}; + return {indexedName, mappedName}; + } +}; + +TEST_F(MappedElementTest, constructFromNameAndIndex) +{ + // Arrange + Data::IndexedName indexedName {"EDGE1"}; + Data::MappedName mappedName {"OTHER_NAME"}; + + // Act + Data::MappedElement mappedElement {indexedName, mappedName}; + + // Assert + EXPECT_EQ(mappedElement.index, indexedName); + EXPECT_EQ(mappedElement.name, mappedName); +} + +TEST_F(MappedElementTest, moveConstructor) +{ + // Arrange + auto originalMappedElement = givenMappedElement("EDGE1", "OTHER_NAME"); + auto originalName = originalMappedElement.name; + auto originalIndex = originalMappedElement.index; + + // Act + Data::MappedElement newMappedElement {std::move(originalMappedElement)}; + + // Assert + EXPECT_EQ(originalName, newMappedElement.name); + EXPECT_EQ(originalIndex, newMappedElement.index); +} + +TEST_F(MappedElementTest, assignmentOperator) +{ + // Arrange + auto mappedElementA = givenMappedElement("EDGE1", "OTHER_NAME"); + auto mappedElementB = givenMappedElement("EDGE2", "ANOTHER_NAME"); + EXPECT_NE(mappedElementA, mappedElementB);// Verify test setup + + // Act + mappedElementA = mappedElementB; + + // Assert + EXPECT_EQ(mappedElementA, mappedElementB); +} + +TEST_F(MappedElementTest, moveAssignmentOperator) +{ + // Arrange + auto mappedElementA = givenMappedElement("EDGE1", "OTHER_NAME"); + auto mappedElementB = givenMappedElement("EDGE2", "ANOTHER_NAME"); + EXPECT_NE(mappedElementA, mappedElementB);// Verify test setup + + // Act + mappedElementA = std::move(mappedElementB); + + // Assert + EXPECT_EQ(mappedElementA.name.toString(), "ANOTHER_NAME"); + EXPECT_EQ(mappedElementA.index.toString(), "EDGE2"); +} + +TEST_F(MappedElementTest, equalityOperatorsWhenNotEqual) +{ + // Arrange + auto mappedElementA = givenMappedElement("EDGE1", "OTHER_NAME"); + auto mappedElementB = givenMappedElement("EDGE2", "ANOTHER_NAME"); + + // Act + bool aAndBAreEqual = mappedElementA == mappedElementB; + bool aAndBAreNotEqual = mappedElementA != mappedElementB; + + // Assert + EXPECT_TRUE(aAndBAreNotEqual); + EXPECT_FALSE(aAndBAreEqual); +} + +TEST_F(MappedElementTest, equalityOperatorsWhenEqual) +{ + // Arrange + auto mappedElementA = givenMappedElement("EDGE1", "OTHER_NAME"); + auto mappedElementB = givenMappedElement("EDGE1", "OTHER_NAME"); + + // Act + bool aAndBAreEqual = mappedElementA == mappedElementB; + bool aAndBAreNotEqual = mappedElementA != mappedElementB; + + // Assert + EXPECT_FALSE(aAndBAreNotEqual); + EXPECT_TRUE(aAndBAreEqual); +} + +TEST_F(MappedElementTest, lessThanOperator) +{ + // Index is compared first, then mappedName + + // Arrange + auto mappedElement1A = givenMappedElement("EDGE1", "A"); + auto mappedElement1B = givenMappedElement("EDGE1", "B"); + auto mappedElement2A = givenMappedElement("EDGE2", "A"); + auto mappedElement2B = givenMappedElement("EDGE2", "B"); + auto mappedElement2BDuplicate = givenMappedElement("EDGE2", "B"); + + // Act & Assert + EXPECT_TRUE(mappedElement1A < mappedElement1B); + EXPECT_TRUE(mappedElement1A < mappedElement2A); + EXPECT_TRUE(mappedElement1B < mappedElement2A); + EXPECT_FALSE(mappedElement2A < mappedElement1B); + EXPECT_FALSE(mappedElement2B < mappedElement2BDuplicate); +}