601 lines
15 KiB
C++
601 lines
15 KiB
C++
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "App/IndexedName.h"
|
|
|
|
#include <sstream>
|
|
|
|
// NOLINTBEGIN(readability-magic-numbers)
|
|
|
|
class IndexedNameTest: public ::testing::Test
|
|
{
|
|
protected:
|
|
// void SetUp() override {}
|
|
|
|
// void TearDown() override {}
|
|
|
|
// Create and return a list of invalid IndexedNames
|
|
static std::vector<Data::IndexedName> givenInvalidIndexedNames()
|
|
{
|
|
return std::vector<Data::IndexedName> {Data::IndexedName(),
|
|
Data::IndexedName("", 1),
|
|
Data::IndexedName("INVALID42NAME", 1),
|
|
Data::IndexedName(".EDGE", 1)};
|
|
}
|
|
|
|
// Create and return a list of valid IndexedNames
|
|
static std::vector<Data::IndexedName> givenValidIndexedNames()
|
|
{
|
|
return std::vector<Data::IndexedName> {Data::IndexedName("NAME"),
|
|
Data::IndexedName("NAME1"),
|
|
Data::IndexedName("NAME", 1),
|
|
Data::IndexedName("NAME_WITH_UNDERSCORES12345")};
|
|
}
|
|
|
|
// An arbitrary list of C strings used for testing some types of construction
|
|
// NOLINTNEXTLINE cppcoreguidelines-non-private-member-variables-in-classes
|
|
std::vector<const char*> allowedTypes {"VERTEX", "EDGE", "FACE", "WIRE"};
|
|
};
|
|
|
|
TEST_F(IndexedNameTest, defaultConstruction)
|
|
{
|
|
// Act
|
|
auto indexedName = Data::IndexedName();
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "");
|
|
EXPECT_EQ(indexedName.getIndex(), 0);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, nameOnlyConstruction)
|
|
{
|
|
// Act
|
|
auto indexedName = Data::IndexedName("TestName");
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "TestName");
|
|
EXPECT_EQ(indexedName.getIndex(), 0);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, nameAndIndexConstruction)
|
|
{
|
|
// Arrange
|
|
const int testIndex {42};
|
|
|
|
// Act
|
|
auto indexedName = Data::IndexedName("TestName", testIndex);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "TestName");
|
|
EXPECT_EQ(indexedName.getIndex(), testIndex);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, nameAndIndexConstructionWithOverride)
|
|
{
|
|
// Arrange
|
|
const int testIndex {42};
|
|
|
|
// Act
|
|
auto indexedName = Data::IndexedName("TestName17", testIndex);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "TestName");
|
|
EXPECT_EQ(indexedName.getIndex(), testIndex);
|
|
}
|
|
|
|
// Names must only contain ASCII letters and underscores (but may end with a number)
|
|
TEST_F(IndexedNameTest, constructionInvalidCharInName)
|
|
{
|
|
// Arrange
|
|
constexpr int lastASCIICode {127};
|
|
std::vector<char> illegalCharacters = {};
|
|
for (int code = 1; code <= lastASCIICode; ++code) {
|
|
if ((std::isalnum(code) == 0) && code != '_') {
|
|
illegalCharacters.push_back(char(code));
|
|
}
|
|
}
|
|
for (auto illegalChar : illegalCharacters) {
|
|
std::string testName {"TestName"};
|
|
testName += illegalChar;
|
|
|
|
// Act
|
|
auto indexedName = Data::IndexedName(testName.c_str(), 1);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "") << "Expected empty name when given " << testName;
|
|
}
|
|
}
|
|
|
|
// Names must not contain numbers in the middle:
|
|
TEST_F(IndexedNameTest, constructionNumberInName)
|
|
{
|
|
// Arrange
|
|
const int testIndex {42};
|
|
std::string testName;
|
|
testName += "Test" + std::to_string(testIndex) + "Name";
|
|
|
|
// Act
|
|
auto indexedName = Data::IndexedName(testName.c_str(), testIndex);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, nameAndTypeListConstructionWithoutAllowOthers)
|
|
{
|
|
// Act
|
|
auto indexedName = Data::IndexedName("EDGE19", allowedTypes, false);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "EDGE");
|
|
EXPECT_EQ(indexedName.getIndex(), 19);
|
|
|
|
// Act
|
|
indexedName = Data::IndexedName("EDGES_ARE_REALLY_GREAT19", allowedTypes, false);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "");
|
|
EXPECT_EQ(indexedName.getIndex(), 19);
|
|
|
|
// Act
|
|
indexedName = Data::IndexedName("NOT_IN_THE_LIST42", allowedTypes, false);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, nameAndTypeListConstructionWithAllowOthers)
|
|
{
|
|
// Act
|
|
auto indexedName = Data::IndexedName("NOT_IN_THE_LIST42", allowedTypes, true);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "NOT_IN_THE_LIST");
|
|
EXPECT_EQ(indexedName.getIndex(), 42);
|
|
}
|
|
|
|
// Check that the same memory location is used for two names that are not in the allowedTypes list
|
|
TEST_F(IndexedNameTest, nameAndTypeListConstructionReusedMemoryCheck)
|
|
{
|
|
// Arrange
|
|
auto indexedName1 = Data::IndexedName("NOT_IN_THE_LIST42", allowedTypes, true);
|
|
auto indexedName2 = Data::IndexedName("NOT_IN_THE_LIST43", allowedTypes, true);
|
|
|
|
// Act & Assert
|
|
EXPECT_EQ(indexedName1.getType(), indexedName2.getType());
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, byteArrayConstruction)
|
|
{
|
|
// Arrange
|
|
QByteArray qba {"EDGE42"};
|
|
|
|
// Act
|
|
auto indexedName = Data::IndexedName(qba);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "EDGE");
|
|
EXPECT_EQ(indexedName.getIndex(), 42);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, copyConstruction)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
|
|
// Act
|
|
auto indexedNameCopy {indexedName};
|
|
|
|
// Assert
|
|
EXPECT_EQ(indexedName, indexedNameCopy);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, streamInsertionOperator)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
std::stringstream ss;
|
|
|
|
// Act
|
|
ss << indexedName;
|
|
|
|
// Assert
|
|
EXPECT_EQ(ss.str(), std::string {"EDGE42"});
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, compoundAssignmentOperator)
|
|
{
|
|
// NOTE: Only += is defined for this class
|
|
|
|
// Arrange
|
|
constexpr int base {42};
|
|
constexpr int offset {10};
|
|
auto indexedName = Data::IndexedName("EDGE", base);
|
|
|
|
// Act
|
|
indexedName += offset;
|
|
|
|
// Assert
|
|
EXPECT_EQ(indexedName.getIndex(), 52);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, preincrementOperator)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
|
|
// Act
|
|
++indexedName;
|
|
|
|
// Assert
|
|
EXPECT_EQ(indexedName.getIndex(), 43);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, predecrementOperator)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
|
|
// Act
|
|
--indexedName;
|
|
|
|
// Assert
|
|
EXPECT_EQ(indexedName.getIndex(), 41);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, comparisonOperators)
|
|
{
|
|
// Arrange
|
|
auto indexedName1 = Data::IndexedName("EDGE42");
|
|
auto indexedName2 = Data::IndexedName("EDGE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_EQ(indexedName1.compare(indexedName2), 0);
|
|
EXPECT_TRUE(indexedName1 == indexedName2);
|
|
EXPECT_FALSE(indexedName1 != indexedName2);
|
|
EXPECT_FALSE(indexedName1 < indexedName2);
|
|
|
|
// Arrange
|
|
auto indexedName3 = Data::IndexedName("EDGE42");
|
|
auto indexedName4 = Data::IndexedName("FACE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_LT(indexedName3.compare(indexedName4), 0);
|
|
EXPECT_FALSE(indexedName3 == indexedName4);
|
|
EXPECT_TRUE(indexedName3 != indexedName4);
|
|
EXPECT_TRUE(indexedName3 < indexedName4);
|
|
|
|
// Arrange
|
|
auto indexedName5 = Data::IndexedName("FACE42");
|
|
auto indexedName6 = Data::IndexedName("EDGE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_GT(indexedName5.compare(indexedName6), 0);
|
|
EXPECT_FALSE(indexedName5 == indexedName6);
|
|
EXPECT_TRUE(indexedName5 != indexedName6);
|
|
EXPECT_FALSE(indexedName5 < indexedName6);
|
|
|
|
// Arrange
|
|
auto indexedName7 = Data::IndexedName("EDGE41");
|
|
auto indexedName8 = Data::IndexedName("EDGE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_LT(indexedName7.compare(indexedName8), 0);
|
|
EXPECT_FALSE(indexedName7 == indexedName8);
|
|
EXPECT_TRUE(indexedName7 != indexedName8);
|
|
EXPECT_TRUE(indexedName7 < indexedName8);
|
|
|
|
// Arrange
|
|
auto indexedName9 = Data::IndexedName("EDGE43");
|
|
auto indexedName10 = Data::IndexedName("EDGE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_GT(indexedName9.compare(indexedName10), 0);
|
|
EXPECT_FALSE(indexedName9 == indexedName10);
|
|
EXPECT_TRUE(indexedName9 != indexedName10);
|
|
EXPECT_FALSE(indexedName9 < indexedName10);
|
|
|
|
// Arrange
|
|
auto indexedName11 = Data::IndexedName("EDGE2");
|
|
auto indexedName12 = Data::IndexedName("EDGE12");
|
|
|
|
// Act & Assert
|
|
EXPECT_LT(indexedName11.compare(indexedName12), 0);
|
|
EXPECT_FALSE(indexedName11 == indexedName12);
|
|
EXPECT_TRUE(indexedName11 != indexedName12);
|
|
EXPECT_TRUE(indexedName11 < indexedName12);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, subscriptOperator)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_EQ(indexedName[0], 'E');
|
|
EXPECT_EQ(indexedName[1], 'D');
|
|
EXPECT_EQ(indexedName[2], 'G');
|
|
EXPECT_EQ(indexedName[3], 'E');
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, getType)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
|
|
// Act & Assert
|
|
EXPECT_STREQ(indexedName.getType(), "EDGE");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, setIndex)
|
|
{
|
|
// Arrange
|
|
auto indexedName = Data::IndexedName("EDGE42");
|
|
EXPECT_EQ(indexedName.getIndex(), 42);
|
|
|
|
// Act
|
|
indexedName.setIndex(1);
|
|
|
|
// Assert
|
|
EXPECT_EQ(indexedName.getIndex(), 1);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, isNullTrue)
|
|
{
|
|
// Arrange
|
|
auto invalidNames = givenInvalidIndexedNames();
|
|
for (const auto& name : invalidNames) {
|
|
|
|
// Act & Assert
|
|
EXPECT_TRUE(name.isNull());
|
|
}
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, isNullFalse)
|
|
{
|
|
// Arrange
|
|
auto validNames = givenValidIndexedNames();
|
|
for (const auto& name : validNames) {
|
|
|
|
// Act & Assert
|
|
EXPECT_FALSE(name.isNull());
|
|
}
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, booleanConversionFalse)
|
|
{
|
|
// Arrange
|
|
auto invalidNames = givenInvalidIndexedNames();
|
|
for (const auto& name : invalidNames) {
|
|
|
|
// Act & Assert
|
|
EXPECT_FALSE(static_cast<bool>(name));
|
|
}
|
|
|
|
// Usage example:
|
|
auto indexedName = Data::IndexedName(".EDGE", 1);// Invalid name
|
|
if (indexedName) {
|
|
FAIL() << "indexedName as a boolean should have been false for an invalid name";
|
|
}
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, booleanConversionTrue)
|
|
{
|
|
// Arrange
|
|
auto validNames = givenValidIndexedNames();
|
|
for (const auto& name : validNames) {
|
|
|
|
// Act & Assert
|
|
EXPECT_TRUE(static_cast<bool>(name));
|
|
}
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, fromConst)
|
|
{
|
|
// Arrange
|
|
const int testIndex {42};
|
|
|
|
// Act
|
|
auto indexedName = Data::IndexedName::fromConst("TestName", testIndex);
|
|
|
|
// Assert
|
|
EXPECT_STREQ(indexedName.getType(), "TestName");
|
|
EXPECT_EQ(indexedName.getIndex(), testIndex);
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, appendToStringBufferEmptyBuffer)
|
|
{
|
|
// Arrange
|
|
std::string bufferStartedEmpty;
|
|
Data::IndexedName testName("TEST_NAME", 1);
|
|
|
|
// Act
|
|
testName.appendToStringBuffer(bufferStartedEmpty);
|
|
|
|
// Assert
|
|
EXPECT_EQ(bufferStartedEmpty, "TEST_NAME1");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, appendToStringBufferNonEmptyBuffer)
|
|
{
|
|
// Arrange
|
|
std::string bufferWithData {"DATA"};
|
|
Data::IndexedName testName("TEST_NAME", 1);
|
|
|
|
// Act
|
|
testName.appendToStringBuffer(bufferWithData);
|
|
|
|
// Assert
|
|
EXPECT_EQ(bufferWithData, "DATATEST_NAME1");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, appendToStringBufferZeroIndex)
|
|
{
|
|
// Arrange
|
|
std::string bufferStartedEmpty;
|
|
Data::IndexedName testName("TEST_NAME", 0);
|
|
|
|
// Act
|
|
testName.appendToStringBuffer(bufferStartedEmpty);
|
|
|
|
// Assert
|
|
EXPECT_EQ(bufferStartedEmpty, "TEST_NAME");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, toString)
|
|
{
|
|
// Arrange
|
|
Data::IndexedName testName("TEST_NAME", 1);
|
|
|
|
// Act
|
|
auto result = testName.toString();
|
|
|
|
// Assert
|
|
EXPECT_EQ(result, "TEST_NAME1");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, toStringNoIndex)
|
|
{
|
|
// Arrange
|
|
Data::IndexedName testName("TEST_NAME", 0);
|
|
|
|
// Act
|
|
auto result = testName.toString();
|
|
|
|
// Assert
|
|
EXPECT_EQ(result, "TEST_NAME");
|
|
}
|
|
|
|
TEST_F(IndexedNameTest, assignmentOperator)
|
|
{
|
|
// Arrange
|
|
const int testIndex1 {42};
|
|
const int testIndex2 {24};
|
|
auto indexedName1 = Data::IndexedName::fromConst("TestName", testIndex1);
|
|
auto indexedName2 = Data::IndexedName::fromConst("TestName2", testIndex2);
|
|
EXPECT_NE(indexedName1, indexedName2);// Ensure the test is set up correctly
|
|
|
|
// Act
|
|
indexedName1 = indexedName2;
|
|
|
|
// Assert
|
|
EXPECT_EQ(indexedName1, indexedName2);
|
|
}
|
|
|
|
|
|
class ByteArrayTest: public ::testing::Test
|
|
{
|
|
protected:
|
|
// void SetUp() override {}
|
|
|
|
// void TearDown() override {}
|
|
};
|
|
|
|
TEST_F(ByteArrayTest, QByteArrayConstruction)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA("Data in a QByteArray");
|
|
|
|
// Act
|
|
Data::ByteArray testByteArray(testQBA);
|
|
|
|
// Assert
|
|
EXPECT_EQ(testQBA, testByteArray.bytes);
|
|
}
|
|
|
|
TEST_F(ByteArrayTest, CopyConstruction)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA("Data in a QByteArray");
|
|
Data::ByteArray originalByteArray(testQBA);
|
|
|
|
// Act
|
|
// NOLINTNEXTLINE performance-unnecessary-copy-initialization
|
|
Data::ByteArray copiedByteArray(originalByteArray);
|
|
|
|
// Assert
|
|
EXPECT_EQ(originalByteArray, copiedByteArray);
|
|
}
|
|
|
|
TEST_F(ByteArrayTest, MoveConstruction)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA("Data in a QByteArray");
|
|
Data::ByteArray originalByteArray(testQBA);
|
|
const auto* originalDataLocation = originalByteArray.bytes.constData();
|
|
|
|
// Act
|
|
Data::ByteArray copiedByteArray(std::move(originalByteArray));
|
|
|
|
// Assert
|
|
EXPECT_EQ(testQBA, copiedByteArray.bytes);
|
|
EXPECT_EQ(originalDataLocation, copiedByteArray.bytes.constData());
|
|
}
|
|
|
|
TEST_F(ByteArrayTest, ensureUnshared)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA("Data in a QByteArray");
|
|
Data::ByteArray originalByteArray(testQBA);
|
|
const auto* originalDataLocation = originalByteArray.bytes.constData();
|
|
Data::ByteArray copiedByteArray(originalByteArray);
|
|
|
|
// Act
|
|
copiedByteArray.ensureUnshared();
|
|
|
|
// Assert
|
|
EXPECT_EQ(testQBA, copiedByteArray.bytes);
|
|
EXPECT_NE(originalDataLocation, copiedByteArray.bytes.constData());
|
|
}
|
|
|
|
TEST_F(ByteArrayTest, equalityOperator)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA1("Data in a QByteArray");
|
|
QByteArray testQBA2("Data in a QByteArray");
|
|
QByteArray testQBA3("Not the same data in a QByteArray");
|
|
Data::ByteArray byteArray1(testQBA1);
|
|
Data::ByteArray byteArray2(testQBA2);
|
|
Data::ByteArray byteArray3(testQBA3);
|
|
|
|
// Act & Assert
|
|
EXPECT_TRUE(byteArray1 == byteArray2);
|
|
EXPECT_FALSE(byteArray1 == byteArray3);
|
|
}
|
|
|
|
TEST_F(ByteArrayTest, assignmentOperator)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA1("Data in a QByteArray");
|
|
QByteArray testQBA2("Different data in a QByteArray");
|
|
Data::ByteArray originalByteArray(testQBA1);
|
|
Data::ByteArray newByteArray(testQBA2);
|
|
ASSERT_FALSE(originalByteArray == newByteArray);
|
|
|
|
// Act
|
|
newByteArray = originalByteArray;
|
|
|
|
// Assert
|
|
EXPECT_TRUE(originalByteArray == newByteArray);
|
|
}
|
|
|
|
TEST_F(ByteArrayTest, moveAssignmentOperator)
|
|
{
|
|
// Arrange
|
|
QByteArray testQBA1("Data in a QByteArray");
|
|
QByteArray testQBA2("Different data in a QByteArray");
|
|
Data::ByteArray originalByteArray(testQBA1);
|
|
const auto* originalByteArrayLocation = originalByteArray.bytes.constData();
|
|
Data::ByteArray newByteArray(testQBA2);
|
|
ASSERT_FALSE(originalByteArray == newByteArray);
|
|
|
|
// Act
|
|
newByteArray = std::move(originalByteArray);
|
|
|
|
// Assert
|
|
EXPECT_EQ(originalByteArrayLocation, newByteArray.bytes.constData());
|
|
}
|
|
|
|
// NOLINTEND(readability-magic-numbers)
|