mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-25 06:57:28 +00:00
Add tests for LDF parsing and serialization. Cleanup LDF (#1062)
* Add tests and cleanup LDF header Also implements a speedup by using overloaded operators to put numbers directly to a stream as opposed to doing to_string first. Stage 2 of re-write Reduce scoping Add further optimizations Fix more edge cases Split out tests to many smaller ones Use EXPECT_NO_THROW Add edge cases to test Added these first with the before to confirm they failed, and now will be adding the remaining fixes needed to make the tests pass. Add edge case testing for LDF strings Add further tests Use characters instead of char* Update AMFDeserializeTests.cpp Add null tests * Add Test Fixture for dCommon * Add speed test * Convert to using string_view * Add explanation on early return * Remove "testing" code
This commit is contained in:
parent
2f919d101f
commit
e8590a5853
@ -3,122 +3,174 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
// C++
|
// C++
|
||||||
#include <sstream>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
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
|
//! 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::pair<LDFKey, LDFTypeAndValue> keyValue;
|
||||||
std::istringstream ssFormat(format);
|
keyValue.first = format.substr(0, equalsPosition);
|
||||||
std::string token;
|
keyValue.second = format.substr(equalsPosition + 1, format.size());
|
||||||
|
|
||||||
std::vector<std::string> keyValueArray;
|
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValue.first);
|
||||||
while (std::getline(ssFormat, token, '=')) {
|
|
||||||
keyValueArray.push_back(token);
|
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<LDFType, LDFValue> 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<eLDFType>(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) {
|
LDFBaseData* returnValue = nullptr;
|
||||||
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValueArray[0]);
|
|
||||||
|
|
||||||
std::vector<std::string> dataArray;
|
|
||||||
std::istringstream ssData(keyValueArray[1]);
|
|
||||||
while (std::getline(ssData, token, ':')) {
|
|
||||||
dataArray.push_back(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataArray.size() > 2) { // hacky fix for strings with colons in them
|
|
||||||
std::vector<std::string> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dataArray[0] == "0" || dataArray[0] == "13") && dataArray.size() == 1) {
|
|
||||||
dataArray.push_back("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataArray.size() == 2) {
|
|
||||||
eLDFType type = static_cast<eLDFType>(stoi(dataArray[0]));
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LDF_TYPE_UTF_16: {
|
case LDF_TYPE_UTF_16: {
|
||||||
std::u16string data = GeneralUtils::UTF8ToUTF16(dataArray[1]);
|
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfTypeAndValue.second);
|
||||||
return new LDFData<std::u16string>(key, data);
|
returnValue = new LDFData<std::u16string>(key, data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_S32: {
|
case LDF_TYPE_S32: {
|
||||||
int32_t data = static_cast<int32_t>(stoull(dataArray[1]));
|
try {
|
||||||
return new LDFData<int32_t>(key, data);
|
int32_t data = static_cast<int32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
returnValue = new LDFData<int32_t>(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_FLOAT: {
|
case LDF_TYPE_FLOAT: {
|
||||||
float data = static_cast<float>(stof(dataArray[1]));
|
try {
|
||||||
return new LDFData<float>(key, data);
|
float data = strtof(ldfTypeAndValue.second.data(), &storage);
|
||||||
|
returnValue = new LDFData<float>(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_DOUBLE: {
|
case LDF_TYPE_DOUBLE: {
|
||||||
double data = static_cast<float>(stod(dataArray[1]));
|
try {
|
||||||
return new LDFData<double>(key, data);
|
double data = strtod(ldfTypeAndValue.second.data(), &storage);
|
||||||
|
returnValue = new LDFData<double>(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_U32:
|
case LDF_TYPE_U32:
|
||||||
{
|
{
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
if (dataArray[1] == "true") {
|
if (ldfTypeAndValue.second == "true") {
|
||||||
data = 1;
|
data = 1;
|
||||||
} else if (dataArray[1] == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = 0;
|
data = 0;
|
||||||
} else {
|
} else {
|
||||||
data = static_cast<uint32_t>(stoul(dataArray[1]));
|
try {
|
||||||
|
data = static_cast<uint32_t>(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LDFData<uint32_t>(key, data);
|
returnValue = new LDFData<uint32_t>(key, data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_BOOLEAN: {
|
case LDF_TYPE_BOOLEAN: {
|
||||||
bool data;
|
bool data;
|
||||||
|
|
||||||
if (dataArray[1] == "true") {
|
if (ldfTypeAndValue.second == "true") {
|
||||||
data = true;
|
data = true;
|
||||||
} else if (dataArray[1] == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = false;
|
data = false;
|
||||||
} else {
|
} else {
|
||||||
data = static_cast<bool>(stoi(dataArray[1]));
|
try {
|
||||||
|
data = static_cast<bool>(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LDFData<bool>(key, data);
|
returnValue = new LDFData<bool>(key, data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_U64: {
|
case LDF_TYPE_U64: {
|
||||||
uint64_t data = static_cast<uint64_t>(stoull(dataArray[1]));
|
try {
|
||||||
return new LDFData<uint64_t>(key, data);
|
uint64_t data = static_cast<uint64_t>(strtoull(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
returnValue = new LDFData<uint64_t>(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: {
|
case LDF_TYPE_OBJID: {
|
||||||
LWOOBJID data = static_cast<LWOOBJID>(stoll(dataArray[1]));
|
try {
|
||||||
return new LDFData<LWOOBJID>(key, data);
|
LWOOBJID data = static_cast<LWOOBJID>(strtoll(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
returnValue = new LDFData<LWOOBJID>(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: {
|
case LDF_TYPE_UTF_8: {
|
||||||
std::string data = dataArray[1];
|
std::string data = ldfTypeAndValue.second.data();
|
||||||
return new LDFData<std::string>(key, data);
|
returnValue = new LDFData<std::string>(key, data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_UNKNOWN: {
|
case LDF_TYPE_UNKNOWN: {
|
||||||
return nullptr;
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
default: {
|
||||||
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#ifndef __LDFFORMAT__H__
|
||||||
|
#define __LDFFORMAT__H__
|
||||||
|
|
||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
@ -6,18 +7,12 @@
|
|||||||
|
|
||||||
// C++
|
// C++
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// RakNet
|
// 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 {
|
enum eLDFType {
|
||||||
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
|
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
|
||||||
LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring 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
|
LDF_TYPE_UTF_8 = 13, //!< UTF-8 string data type
|
||||||
};
|
};
|
||||||
|
|
||||||
//! A base class for the LDF data
|
|
||||||
class LDFBaseData {
|
class LDFBaseData {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Destructor
|
virtual ~LDFBaseData() {}
|
||||||
virtual ~LDFBaseData(void) {}
|
|
||||||
|
|
||||||
//! Writes the data to a packet
|
|
||||||
/*!
|
|
||||||
\param packet The packet
|
|
||||||
*/
|
|
||||||
virtual void WriteToPacket(RakNet::BitStream* packet) = 0;
|
virtual void WriteToPacket(RakNet::BitStream* packet) = 0;
|
||||||
|
|
||||||
//! Gets the key
|
virtual const std::u16string& GetKey() = 0;
|
||||||
/*!
|
|
||||||
\return The key
|
|
||||||
*/
|
|
||||||
virtual const std::u16string& GetKey(void) = 0;
|
|
||||||
|
|
||||||
//! Gets the value type
|
virtual eLDFType GetValueType() = 0;
|
||||||
/*!
|
|
||||||
\return The value type
|
|
||||||
*/
|
|
||||||
virtual eLDFType GetValueType(void) = 0;
|
|
||||||
|
|
||||||
//! Gets a string from the key/value pair
|
/** Gets a string from the key/value pair
|
||||||
/*!
|
* @param includeKey Whether or not to include the key in the data
|
||||||
\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
|
||||||
\param includeTypeId Whether or not to include the type id in the data
|
* @return The string representation of the data
|
||||||
\return The string representation of the data
|
|
||||||
*/
|
*/
|
||||||
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
|
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
|
||||||
|
|
||||||
@ -68,19 +48,15 @@ public:
|
|||||||
|
|
||||||
virtual LDFBaseData* Copy() = 0;
|
virtual LDFBaseData* Copy() = 0;
|
||||||
|
|
||||||
// MARK: Functions
|
/**
|
||||||
|
* Given an input string, return the data as a LDF key.
|
||||||
//! Returns a pointer to a LDFData value based on string format
|
|
||||||
/*!
|
|
||||||
\param format The format
|
|
||||||
*/
|
*/
|
||||||
static LDFBaseData* DataFromString(const std::string& format);
|
static LDFBaseData* DataFromString(const std::string_view& format);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! A structure for an LDF key-value pair
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class LDFData : public LDFBaseData {
|
class LDFData: public LDFBaseData {
|
||||||
private:
|
private:
|
||||||
std::u16string key;
|
std::u16string key;
|
||||||
T value;
|
T value;
|
||||||
@ -164,15 +140,11 @@ public:
|
|||||||
|
|
||||||
if (includeKey) {
|
if (includeKey) {
|
||||||
const std::string& sKey = GeneralUtils::UTF16ToWTF8(this->key, this->key.size());
|
const std::string& sKey = GeneralUtils::UTF16ToWTF8(this->key, this->key.size());
|
||||||
|
stream << sKey << '=';
|
||||||
stream << sKey << "=";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeTypeId) {
|
if (includeTypeId) {
|
||||||
const std::string& sType = std::to_string(this->GetValueType());
|
stream << this->GetValueType() << ':';
|
||||||
|
|
||||||
|
|
||||||
stream << sType << ":";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& sData = this->GetValueString();
|
const std::string& sData = this->GetValueString();
|
||||||
@ -234,20 +206,18 @@ inline void LDFData<std::string>::WriteValue(RakNet::BitStream* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: String Data
|
template<> inline std::string LDFData<std::u16string>::GetValueString() {
|
||||||
template<> inline std::string LDFData<std::u16string>::GetValueString(void) {
|
|
||||||
//std::string toReturn(this->value.begin(), this->value.end());
|
|
||||||
//return toReturn;
|
|
||||||
|
|
||||||
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<int32_t>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<float>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<float>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<double>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<double>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<uint32_t>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<uint32_t>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<bool>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<bool>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<uint64_t>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<uint64_t>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<LWOOBJID>::GetValueString(void) { return std::to_string(this->value); }
|
template<> inline std::string LDFData<LWOOBJID>::GetValueString() { return std::to_string(this->value); }
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::string>::GetValueString(void) { return this->value; }
|
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; }
|
||||||
|
|
||||||
|
#endif //!__LDFFORMAT__H__
|
||||||
|
@ -3,6 +3,7 @@ set(DCOMMONTEST_SOURCES
|
|||||||
"TestLDFFormat.cpp"
|
"TestLDFFormat.cpp"
|
||||||
"TestNiPoint3.cpp"
|
"TestNiPoint3.cpp"
|
||||||
"TestEncoding.cpp"
|
"TestEncoding.cpp"
|
||||||
|
"dCommonDependencies.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set our executable
|
# Set our executable
|
||||||
|
@ -1,25 +1,252 @@
|
|||||||
#include "LDFFormat.h"
|
#include "LDFFormat.h"
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
/**
|
#include "Game.h"
|
||||||
* @brief Test parsing an LDF value
|
#include "dCommonDependencies.h"
|
||||||
*/
|
#include "dLogger.h"
|
||||||
TEST(dCommonTests, LDFTest) {
|
|
||||||
// Create
|
|
||||||
auto* data = LDFBaseData::DataFromString("KEY=0:VALUE");
|
|
||||||
|
|
||||||
// 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<LDFBaseData>
|
||||||
|
|
||||||
|
// 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);
|
ASSERT_EQ(data->GetValueType(), eLDFType::LDF_TYPE_UTF_16);
|
||||||
|
|
||||||
// Check that the key is correct
|
|
||||||
ASSERT_EQ(data->GetKey(), u"KEY");
|
ASSERT_EQ(data->GetKey(), u"KEY");
|
||||||
|
ASSERT_EQ(((LDFData<std::u16string>*)data.get())->GetValue(), u"IAmA weird string with :::: and spac,./;'][\\es that I expect to be parsed correctly...; ");
|
||||||
// Check that the value is correct
|
ASSERT_EQ(data->GetString(), testWord);
|
||||||
ASSERT_EQ(((LDFData<std::u16string>*)data)->GetValue(), u"VALUE");
|
|
||||||
|
|
||||||
// Check that the serialization is correct
|
|
||||||
ASSERT_EQ(data->GetString(), "KEY=0:VALUE");
|
|
||||||
|
|
||||||
// Cleanup the object
|
|
||||||
delete data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<std::u16string>*)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<std::u16string>*)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<std::u16string>*)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<int32_t>*)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<uint32_t>*)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<uint32_t>*)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<uint32_t>*)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<float>*)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<double>*)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<bool>*)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<bool>*)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<bool>*)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<uint64_t>*)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<uint64_t>*)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<std::string>*)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<std::string>*)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<std::string>*)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<std::string>*)data.get())->GetValue(), "==");
|
||||||
|
ASSERT_EQ(data->GetString(), testWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(LDFTests, LDFParseEdgeCaseTest) {
|
||||||
|
std::vector<std::string> 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
|
||||||
|
7
tests/dCommonTests/dCommonDependencies.cpp
Normal file
7
tests/dCommonTests/dCommonDependencies.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "Game.h"
|
||||||
|
|
||||||
|
class dLogger;
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
dLogger* logger;
|
||||||
|
} // namespace Game
|
26
tests/dCommonTests/dCommonDependencies.h
Normal file
26
tests/dCommonTests/dCommonDependencies.h
Normal file
@ -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 <gtest/gtest.h>
|
||||||
|
|
||||||
|
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__
|
Loading…
Reference in New Issue
Block a user