Add test causing crash and fix map sorting function. (#22889)
* Add test causing crash and fix map sorting function. When opening a model from FreeCAD 0.7, the model would crash when I changed some of the parameters. This turned out to be due to the ElementNameComparator::operator() not correctly sorting the items going into the map, which caused the map to be invalid. This change adds a test that represented the exact names causing the crash as well as a fix for the problem. Names are now sorted: 1. Empty names first 2. Identifier based names second. 3. Hex based names last. Identifiers are sorted lexicographically for the name portion and numerically for the number portion, smallest to largest. Hex based names are sorted by the value of the hex number, smallest to largest. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix lint issues. * Add another test form to the mix. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "App/IndexedName.h"
|
||||
#include "App/MappedElement.h"
|
||||
@@ -172,13 +177,24 @@ TEST_F(MappedElementTest, comparatorBothStartWithTheSameHexDigits)
|
||||
EXPECT_FALSE(comp(mappedName1, mappedName2));
|
||||
}
|
||||
|
||||
TEST_F(MappedElementTest, DISABLED_comparatorHexWithoutTerminatorIsBroken)
|
||||
TEST_F(MappedElementTest, comparatorHexWithoutTerminator)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName mappedName1 {"#fed"};
|
||||
Data::MappedName mappedName2 {"#abcdef"};
|
||||
auto comp = Data::ElementNameComparator();
|
||||
|
||||
// Act & Assert
|
||||
EXPECT_TRUE(comp(mappedName1, mappedName2));
|
||||
}
|
||||
|
||||
TEST_F(MappedElementTest, comparatorHexWithoutTerminatorSameLength)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName mappedName1 {"#fed"};
|
||||
Data::MappedName mappedName2 {"#abc"};
|
||||
auto comp = Data::ElementNameComparator();
|
||||
|
||||
// Act & Assert
|
||||
EXPECT_FALSE(comp(mappedName1, mappedName2));
|
||||
}
|
||||
@@ -205,7 +221,7 @@ TEST_F(MappedElementTest, comparatorNoHexDigitsSameStringNumericCompare)
|
||||
EXPECT_FALSE(comp(mappedName1, mappedName2));
|
||||
}
|
||||
|
||||
TEST_F(MappedElementTest, DISABLED_comparatorIntegerWithoutTerminatorIsBroken)
|
||||
TEST_F(MappedElementTest, comparatorIntegerWithoutTerminatorIsBroken)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName mappedName1 {"Edge123456"};
|
||||
@@ -215,3 +231,87 @@ TEST_F(MappedElementTest, DISABLED_comparatorIntegerWithoutTerminatorIsBroken)
|
||||
// Act & Assert
|
||||
EXPECT_FALSE(comp(mappedName1, mappedName2));
|
||||
}
|
||||
|
||||
TEST_F(MappedElementTest, comparatorThreeComplexHexNamesInMap)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName name1("#19c9:e;:U;FUS;:Hce4:7,E");
|
||||
Data::MappedName name2("#1dadb:11;:L#1061a;FUS;:H:d,E");
|
||||
Data::MappedName name3("#1dae6:8;:L#1dae4;FUS;:H:d,E");
|
||||
|
||||
std::map<Data::MappedName, int, Data::ElementNameComparator> testMap;
|
||||
testMap[name1] = 1;
|
||||
testMap[name2] = 2;
|
||||
testMap[name3] = 3;
|
||||
|
||||
// Assert: map should have 3 unique keys
|
||||
EXPECT_EQ(testMap.size(), 3);
|
||||
|
||||
// Collect keys in order
|
||||
std::vector<std::string> keys;
|
||||
for (const auto& kv : testMap) {
|
||||
keys.push_back(kv.first.toString());
|
||||
}
|
||||
|
||||
// Print for debug (optional)
|
||||
// for (const auto& k : keys) std::cout << k << std::endl;
|
||||
|
||||
// The expected order depends on your comparator logic.
|
||||
// If you want to check the exact order, set it here:
|
||||
// (Replace with the correct expected order if needed)
|
||||
std::vector<std::string> expectedOrder = {"#19c9:e;:U;FUS;:Hce4:7,E",
|
||||
"#1dadb:11;:L#1061a;FUS;:H:d,E",
|
||||
"#1dae6:8;:L#1dae4;FUS;:H:d,E"};
|
||||
|
||||
EXPECT_EQ(keys, expectedOrder);
|
||||
}
|
||||
|
||||
TEST_F(MappedElementTest, comparatorLargerWorkedExampleWithMap)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName name0("Edge123;:U;FUS;:Hce4:7,E");
|
||||
Data::MappedName name1("#1dad:e;:U;FUS;:Hce4:7,E");
|
||||
Data::MappedName name2("#1dadb:11;:L#1061a;FUS;:H:d,E");
|
||||
Data::MappedName name3("#1dae6:8;:L#1dae4;FUS;:H:d,E");
|
||||
Data::MappedName name4("Edge999;;:L#1dae4;FUS;:H:d,E");
|
||||
Data::MappedName name5("g4v2;SKT;:H1234,F;:H5678:2,E;:G0(g1;SKT;:H9012,E);XTR;:H3456:2,F");
|
||||
|
||||
|
||||
std::map<Data::MappedName, int, Data::ElementNameComparator> testMap;
|
||||
testMap[name0] = 1;
|
||||
testMap[name1] = 2;
|
||||
testMap[name2] = 3;
|
||||
testMap[name3] = 4;
|
||||
testMap[name0] = 5; // Duplicate, should not affect size
|
||||
testMap[name1] = 6; // Duplicate, should not affect size
|
||||
testMap[name4] = 7; // New entry
|
||||
testMap[name4] = 8; // Duplicate, should not affect size
|
||||
testMap[name2] = 9; // Duplicate, should not affect size
|
||||
testMap[name3] = 10; // Duplicate, should not affect size
|
||||
testMap[name5] = 11;
|
||||
|
||||
// Assert: map should have 5 unique keys
|
||||
EXPECT_EQ(testMap.size(), 6);
|
||||
|
||||
// Collect keys in order
|
||||
std::vector<std::string> keys;
|
||||
for (const auto& kv : testMap) {
|
||||
keys.push_back(kv.first.toString());
|
||||
}
|
||||
|
||||
// Print for debug (optional)
|
||||
// for (const auto& k : keys) std::cout << k << std::endl;
|
||||
|
||||
// The expected order depends on your comparator logic.
|
||||
// If you want to check the exact order, set it here:
|
||||
// (Replace with the correct expected order if needed)
|
||||
std::vector<std::string> expectedOrder = {
|
||||
"Edge123;:U;FUS;:Hce4:7,E",
|
||||
"Edge999;;:L#1dae4;FUS;:H:d,E",
|
||||
"g4v2;SKT;:H1234,F;:H5678:2,E;:G0(g1;SKT;:H9012,E);XTR;:H3456:2,F",
|
||||
"#1dad:e;:U;FUS;:Hce4:7,E",
|
||||
"#1dadb:11;:L#1061a;FUS;:H:d,E",
|
||||
"#1dae6:8;:L#1dae4;FUS;:H:d,E"};
|
||||
|
||||
EXPECT_EQ(keys, expectedOrder);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user