diff --git a/dCommon/LDFFormat.cpp b/dCommon/LDFFormat.cpp index 767ec81a..cb921842 100644 --- a/dCommon/LDFFormat.cpp +++ b/dCommon/LDFFormat.cpp @@ -3,122 +3,174 @@ // Custom Classes #include "GeneralUtils.h" +#include "Game.h" +#include "dLogger.h" + // C++ -#include +#include #include +using LDFKey = std::string_view; +using LDFTypeAndValue = std::string_view; + +using LDFType = std::string_view; +using LDFValue = std::string_view; + //! Returns a pointer to a LDFData value based on string format -LDFBaseData* LDFBaseData::DataFromString(const std::string& format) { +LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) { + // A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value) + if (format.empty() || format.length() <= 2) return nullptr; + auto equalsPosition = format.find('='); + // You can have an empty key, just make sure the type and value might exist + if (equalsPosition == std::string::npos || equalsPosition == (format.size() - 1)) return nullptr; - // First, check the format - std::istringstream ssFormat(format); - std::string token; + std::pair keyValue; + keyValue.first = format.substr(0, equalsPosition); + keyValue.second = format.substr(equalsPosition + 1, format.size()); - std::vector keyValueArray; - while (std::getline(ssFormat, token, '=')) { - keyValueArray.push_back(token); + std::u16string key = GeneralUtils::ASCIIToUTF16(keyValue.first); + + auto colonPosition = keyValue.second.find(':'); + + // If : is the first thing after an =, then this is an invalid LDF since + // we dont have a type to use. + if (colonPosition == std::string::npos || colonPosition == 0) return nullptr; + + std::pair ldfTypeAndValue; + ldfTypeAndValue.first = keyValue.second.substr(0, colonPosition); + ldfTypeAndValue.second = keyValue.second.substr(colonPosition + 1, keyValue.second.size()); + + // Only allow empty values for string values. + if (ldfTypeAndValue.second.size() == 0 && !(ldfTypeAndValue.first == "0" || ldfTypeAndValue.first == "13")) return nullptr; + + eLDFType type; + char* storage; + try { + type = static_cast(strtol(ldfTypeAndValue.first.data(), &storage, 10)); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data()); + return nullptr; } - if (keyValueArray.size() == 2) { - std::u16string key = GeneralUtils::ASCIIToUTF16(keyValueArray[0]); + LDFBaseData* returnValue = nullptr; + switch (type) { + case LDF_TYPE_UTF_16: { + std::u16string data = GeneralUtils::UTF8ToUTF16(ldfTypeAndValue.second); + returnValue = new LDFData(key, data); + break; + } - std::vector dataArray; - std::istringstream ssData(keyValueArray[1]); - while (std::getline(ssData, token, ':')) { - dataArray.push_back(token); + case LDF_TYPE_S32: { + try { + int32_t data = static_cast(strtoul(ldfTypeAndValue.second.data(), &storage, 10)); + returnValue = new LDFData(key, data); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + return nullptr; } + break; + } - if (dataArray.size() > 2) { // hacky fix for strings with colons in them - std::vector newDataArray; - newDataArray.push_back(dataArray[0]); - std::string value = ""; - for (size_t i = 1; i < dataArray.size(); ++i) { - value += dataArray[i] + ':'; - } - value.pop_back(); // remove last colon - newDataArray.push_back(value); - dataArray = newDataArray; + case LDF_TYPE_FLOAT: { + try { + float data = strtof(ldfTypeAndValue.second.data(), &storage); + returnValue = new LDFData(key, data); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + return nullptr; } + break; + } - if ((dataArray[0] == "0" || dataArray[0] == "13") && dataArray.size() == 1) { - dataArray.push_back(""); + case LDF_TYPE_DOUBLE: { + try { + double data = strtod(ldfTypeAndValue.second.data(), &storage); + returnValue = new LDFData(key, data); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + return nullptr; } + break; + } - if (dataArray.size() == 2) { - eLDFType type = static_cast(stoi(dataArray[0])); + case LDF_TYPE_U32: + { + uint32_t data; - switch (type) { - case LDF_TYPE_UTF_16: { - std::u16string data = GeneralUtils::UTF8ToUTF16(dataArray[1]); - return new LDFData(key, data); - } - - case LDF_TYPE_S32: { - int32_t data = static_cast(stoull(dataArray[1])); - return new LDFData(key, data); - } - - case LDF_TYPE_FLOAT: { - float data = static_cast(stof(dataArray[1])); - return new LDFData(key, data); - } - - case LDF_TYPE_DOUBLE: { - double data = static_cast(stod(dataArray[1])); - return new LDFData(key, data); - } - - case LDF_TYPE_U32: - { - uint32_t data; - - if (dataArray[1] == "true") { - data = 1; - } else if (dataArray[1] == "false") { - data = 0; - } else { - data = static_cast(stoul(dataArray[1])); - } - - return new LDFData(key, data); - } - - case LDF_TYPE_BOOLEAN: { - bool data; - - if (dataArray[1] == "true") { - data = true; - } else if (dataArray[1] == "false") { - data = false; - } else { - data = static_cast(stoi(dataArray[1])); - } - - return new LDFData(key, data); - } - - case LDF_TYPE_U64: { - uint64_t data = static_cast(stoull(dataArray[1])); - return new LDFData(key, data); - } - - case LDF_TYPE_OBJID: { - LWOOBJID data = static_cast(stoll(dataArray[1])); - return new LDFData(key, data); - } - - case LDF_TYPE_UTF_8: { - std::string data = dataArray[1]; - return new LDFData(key, data); - } - - case LDF_TYPE_UNKNOWN: { + if (ldfTypeAndValue.second == "true") { + data = 1; + } else if (ldfTypeAndValue.second == "false") { + data = 0; + } else { + try { + data = static_cast(strtoul(ldfTypeAndValue.second.data(), &storage, 10)); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); return nullptr; } - } } + + returnValue = new LDFData(key, data); + break; } - return nullptr; + case LDF_TYPE_BOOLEAN: { + bool data; + if (ldfTypeAndValue.second == "true") { + data = true; + } else if (ldfTypeAndValue.second == "false") { + data = false; + } else { + try { + data = static_cast(strtol(ldfTypeAndValue.second.data(), &storage, 10)); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + return nullptr; + } + } + + returnValue = new LDFData(key, data); + break; + } + + case LDF_TYPE_U64: { + try { + uint64_t data = static_cast(strtoull(ldfTypeAndValue.second.data(), &storage, 10)); + returnValue = new LDFData(key, data); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + return nullptr; + } + break; + } + + case LDF_TYPE_OBJID: { + try { + LWOOBJID data = static_cast(strtoll(ldfTypeAndValue.second.data(), &storage, 10)); + returnValue = new LDFData(key, data); + } catch (std::exception) { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + return nullptr; + } + break; + } + + case LDF_TYPE_UTF_8: { + std::string data = ldfTypeAndValue.second.data(); + returnValue = new LDFData(key, data); + break; + } + + case LDF_TYPE_UNKNOWN: { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); + break; + } + + default: { + Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data()); + break; + } + } + return returnValue; } diff --git a/dCommon/LDFFormat.h b/dCommon/LDFFormat.h index 9b62efa7..0921d04c 100644 --- a/dCommon/LDFFormat.h +++ b/dCommon/LDFFormat.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef __LDFFORMAT__H__ +#define __LDFFORMAT__H__ // Custom Classes #include "dCommonVars.h" @@ -6,18 +7,12 @@ // C++ #include +#include #include // RakNet +#include "BitStream.h" -#include "../thirdparty/raknet/Source/BitStream.h" - -/*! - \file LDFFormat.hpp - \brief A collection of LDF format classes - */ - - //! An enum for LDF Data Types enum eLDFType { LDF_TYPE_UNKNOWN = -1, //!< Unknown data type LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring data type @@ -31,36 +26,21 @@ enum eLDFType { LDF_TYPE_UTF_8 = 13, //!< UTF-8 string data type }; -//! A base class for the LDF data class LDFBaseData { public: - //! Destructor - virtual ~LDFBaseData(void) {} + virtual ~LDFBaseData() {} - //! Writes the data to a packet - /*! - \param packet The packet - */ virtual void WriteToPacket(RakNet::BitStream* packet) = 0; - //! Gets the key - /*! - \return The key - */ - virtual const std::u16string& GetKey(void) = 0; + virtual const std::u16string& GetKey() = 0; - //! Gets the value type - /*! - \return The value type - */ - virtual eLDFType GetValueType(void) = 0; + virtual eLDFType GetValueType() = 0; - //! Gets a string from the key/value pair - /*! - \param includeKey Whether or not to include the key in the data - \param includeTypeId Whether or not to include the type id in the data - \return The string representation of the data + /** Gets a string from the key/value pair + * @param includeKey Whether or not to include the key in the data + * @param includeTypeId Whether or not to include the type id in the data + * @return The string representation of the data */ virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0; @@ -68,19 +48,15 @@ public: virtual LDFBaseData* Copy() = 0; - // MARK: Functions - - //! Returns a pointer to a LDFData value based on string format - /*! - \param format The format + /** + * Given an input string, return the data as a LDF key. */ - static LDFBaseData* DataFromString(const std::string& format); + static LDFBaseData* DataFromString(const std::string_view& format); }; -//! A structure for an LDF key-value pair template -class LDFData : public LDFBaseData { +class LDFData: public LDFBaseData { private: std::u16string key; T value; @@ -164,15 +140,11 @@ public: if (includeKey) { const std::string& sKey = GeneralUtils::UTF16ToWTF8(this->key, this->key.size()); - - stream << sKey << "="; + stream << sKey << '='; } if (includeTypeId) { - const std::string& sType = std::to_string(this->GetValueType()); - - - stream << sType << ":"; + stream << this->GetValueType() << ':'; } const std::string& sData = this->GetValueString(); @@ -234,20 +206,18 @@ inline void LDFData::WriteValue(RakNet::BitStream* packet) { } } -// MARK: String Data -template<> inline std::string LDFData::GetValueString(void) { - //std::string toReturn(this->value.begin(), this->value.end()); - //return toReturn; - +template<> inline std::string LDFData::GetValueString() { return GeneralUtils::UTF16ToWTF8(this->value, this->value.size()); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } +template<> inline std::string LDFData::GetValueString() { return std::to_string(this->value); } -template<> inline std::string LDFData::GetValueString(void) { return this->value; } +template<> inline std::string LDFData::GetValueString() { return this->value; } + +#endif //!__LDFFORMAT__H__ diff --git a/tests/dCommonTests/CMakeLists.txt b/tests/dCommonTests/CMakeLists.txt index 86c00c58..dd282cb5 100644 --- a/tests/dCommonTests/CMakeLists.txt +++ b/tests/dCommonTests/CMakeLists.txt @@ -3,6 +3,7 @@ set(DCOMMONTEST_SOURCES "TestLDFFormat.cpp" "TestNiPoint3.cpp" "TestEncoding.cpp" + "dCommonDependencies.cpp" ) # Set our executable diff --git a/tests/dCommonTests/TestLDFFormat.cpp b/tests/dCommonTests/TestLDFFormat.cpp index 647c3cbf..36326e38 100644 --- a/tests/dCommonTests/TestLDFFormat.cpp +++ b/tests/dCommonTests/TestLDFFormat.cpp @@ -1,25 +1,252 @@ #include "LDFFormat.h" + #include -/** - * @brief Test parsing an LDF value - */ -TEST(dCommonTests, LDFTest) { - // Create - auto* data = LDFBaseData::DataFromString("KEY=0:VALUE"); +#include "Game.h" +#include "dCommonDependencies.h" +#include "dLogger.h" - // Check that the data type is correct +class LDFTests : public dCommonDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + + void TearDown() override { + TearDownDependencies(); + } +}; + +#define LdfUniquePtr std::unique_ptr + +// Suite of tests for parsing LDF values + +TEST_F(LDFTests, LDFUTF16Test) { + std::string testWord = "KEY=0:IAmA weird string with :::: and spac,./;'][\\es that I expect to be parsed correctly...; "; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_16); - - // Check that the key is correct ASSERT_EQ(data->GetKey(), u"KEY"); - - // Check that the value is correct - ASSERT_EQ(((LDFData*)data)->GetValue(), u"VALUE"); - - // Check that the serialization is correct - ASSERT_EQ(data->GetString(), "KEY=0:VALUE"); - - // Cleanup the object - delete data; + ASSERT_EQ(((LDFData*)data.get())->GetValue(), u"IAmA weird string with :::: and spac,./;'][\\es that I expect to be parsed correctly...; "); + ASSERT_EQ(data->GetString(), testWord); } + +TEST_F(LDFTests, LDFUTF16EmptyTest) { + std::string testWord = "KEY=0:"; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_16); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), u""); + ASSERT_EQ(data->GetString(), testWord); +} + +TEST_F(LDFTests, LDFUTF16ColonTest) { + std::string testWord = "KEY=0:::"; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_16); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), u"::"); + ASSERT_EQ(data->GetString(), testWord); +} + +TEST_F(LDFTests, LDFUTF16EqualsTest) { + std::string testWord = "KEY=0:=="; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_16); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), u"=="); + ASSERT_EQ(data->GetString(), testWord); +} + +TEST_F(LDFTests, LDFS32Test) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=1:-15")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_S32); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), -15); + ASSERT_EQ(data->GetString(), "KEY=1:-15"); +} +TEST_F(LDFTests, LDFU32Test) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=5:15")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_U32); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 15); + ASSERT_EQ(data->GetString(), "KEY=5:15"); +} + +TEST_F(LDFTests, LDFU32TrueTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=5:true")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_U32); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 1); + ASSERT_EQ(data->GetString(), "KEY=5:1"); +} + +TEST_F(LDFTests, LDFU32FalseTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=5:false")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_U32); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 0); + ASSERT_EQ(data->GetString(), "KEY=5:0"); +} + + +// Use find since floats and doubles generally have appended 0s +TEST_F(LDFTests, LDFFloatTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=3:15.5")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_FLOAT); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 15.5f); + ASSERT_EQ(data->GetString().find("KEY=3:15.5"), 0); +} + +TEST_F(LDFTests, LDFDoubleTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=4:15.5")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_DOUBLE); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 15.5); + ASSERT_EQ(data->GetString().find("KEY=4:15.5"), 0); +} + + +TEST_F(LDFTests, LDFBoolTrueTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=7:true")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_BOOLEAN); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), true); + ASSERT_EQ(data->GetString(), "KEY=7:1"); +} + +TEST_F(LDFTests, LDFBoolFalseTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=7:false")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_BOOLEAN); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), false); + ASSERT_EQ(data->GetString(), "KEY=7:0"); +} + +TEST_F(LDFTests, LDFBoolIntTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=7:3")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_BOOLEAN); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), true); + ASSERT_EQ(data->GetString(), "KEY=7:1"); +} + +TEST_F(LDFTests, LDFU64Test) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=8:15")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_U64); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 15); + ASSERT_EQ(data->GetString(), "KEY=8:15"); +} + +TEST_F(LDFTests, LDFLWOOBJIDTest) { + LdfUniquePtr data(LDFBaseData::DataFromString("KEY=9:15")); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_OBJID); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), 15); + ASSERT_EQ(data->GetString(), "KEY=9:15"); +} + +TEST_F(LDFTests, LDFUTF8Test) { + std::string testWord = "KEY=13:IAmA weird string with :::: and spac,./;'][\\es that I expect to be parsed correctly...; "; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_8); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), "IAmA weird string with :::: and spac,./;'][\\es that I expect to be parsed correctly...; "); + ASSERT_EQ(data->GetString(), testWord); +} + +TEST_F(LDFTests, LDFUTF8EmptyTest) { + std::string testWord = "KEY=13:"; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_8); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), ""); + ASSERT_EQ(data->GetString(), testWord); +} + +TEST_F(LDFTests, LDFUTF8ColonsTest) { + std::string testWord = "KEY=13:::"; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_8); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), "::"); + ASSERT_EQ(data->GetString(), testWord); +} +TEST_F(LDFTests, LDFUTF8EqualsTest) { + std::string testWord = "KEY=13:=="; + LdfUniquePtr data(LDFBaseData::DataFromString(testWord)); + ASSERT_NE(data, nullptr); + ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_8); + ASSERT_EQ(data->GetKey(), u"KEY"); + ASSERT_EQ(((LDFData*)data.get())->GetValue(), "=="); + ASSERT_EQ(data->GetString(), testWord); +} + + +TEST_F(LDFTests, LDFParseEdgeCaseTest) { + std::vector tests = { + // Test undefined data + "", // Empty + "=", // Only equals sign + ":", // Only colon + "=:", // Only colon and equals sign + + // Test no LDFType + "KEY=:", // No LDF Type + "KEY=:44", // No LDF Type, but has value + + // Test invalid values, but valid types + "key=1:", // no value for int32 + "key=1:banana", // invalid value for int32 + "key=3:", // No value for float + "key=3:banana", // invalid for float + "key=4:", // No value for double + "key=4:banana", // invalid for double + "key=5:", // No value for U32 + "key=5:banana", // invalid for U32 + "key=7:", // No value for bool + "key=7:banana", // invalid for bool + "key=8:", // No value for U64 + "key=8:banana", // invalid for U64 + "key=9:", // No value for LWOOBJID + "key=9:banana", // invalid for LWOOBJID + + // Test invalid LDF types + "key=14:value", // invalid LDF type + "key=-1:value", // invalid LDF type + "key=-2:value", // invalid LDF type (no enum definition) + "key=Garbage:value", // invalid LDF type + }; + for (auto testString : tests) { + Game::logger->Log("LDFTests", "Testing LDF Parsing of invalid string (%s)", testString.c_str()); + EXPECT_NO_THROW(LDFBaseData::DataFromString(testString)); + } +} + +#ifdef PERF_TEST + +TEST_F(LDFTests, LDFSpeedTest) { + std::string keyToTest = "KEY=0:IAmA weird string with :::: and s"; + for (int i = 0; i < 10000; i++) LDFBaseData::DataFromString(keyToTest); +} + +#endif //PERF diff --git a/tests/dCommonTests/dCommonDependencies.cpp b/tests/dCommonTests/dCommonDependencies.cpp new file mode 100644 index 00000000..5b25fd47 --- /dev/null +++ b/tests/dCommonTests/dCommonDependencies.cpp @@ -0,0 +1,7 @@ +#include "Game.h" + +class dLogger; +namespace Game +{ + dLogger* logger; +} // namespace Game diff --git a/tests/dCommonTests/dCommonDependencies.h b/tests/dCommonTests/dCommonDependencies.h new file mode 100644 index 00000000..12aeb938 --- /dev/null +++ b/tests/dCommonTests/dCommonDependencies.h @@ -0,0 +1,26 @@ +#ifndef __DCOMMONDEPENDENCIES__H__ +#define __DCOMMONDEPENDENCIES__H__ + +#include "Game.h" +#include "dLogger.h" +#include "dServer.h" +#include "EntityInfo.h" +#include "EntityManager.h" +#include "dConfig.h" +#include + +class dCommonDependenciesTest : public ::testing::Test { +protected: + void SetUpDependencies() { + Game::logger = new dLogger("./testing.log", true, true); + } + + void TearDownDependencies() { + if (Game::logger) { + Game::logger->Flush(); + delete Game::logger; + } + } +}; + +#endif //!__DCOMMONDEPENDENCIES__H__