diff --git a/HephAudio.sln b/HephAudio.sln index c11d3f12..82ccee12 100644 --- a/HephAudio.sln +++ b/HephAudio.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HephCommon", "HephCommon\He EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.vcxproj", "{BC8D5B66-59C4-43D9-9A46-C08291B8035D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{D483B09F-9D19-4761-BD95-CE4C7BB1FADB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -25,6 +27,14 @@ Global {BC8D5B66-59C4-43D9-9A46-C08291B8035D}.Release|x64.Build.0 = Release|x64 {BC8D5B66-59C4-43D9-9A46-C08291B8035D}.Release|x86.ActiveCfg = Release|Win32 {BC8D5B66-59C4-43D9-9A46-C08291B8035D}.Release|x86.Build.0 = Release|Win32 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Debug|x64.ActiveCfg = Debug|x64 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Debug|x64.Build.0 = Debug|x64 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Debug|x86.ActiveCfg = Debug|Win32 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Debug|x86.Build.0 = Debug|Win32 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Release|x64.ActiveCfg = Release|x64 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Release|x64.Build.0 = Release|x64 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Release|x86.ActiveCfg = Release|Win32 + {D483B09F-9D19-4761-BD95-CE4C7BB1FADB}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -36,6 +46,8 @@ Global HephAudio\HephAudio.vcxitems*{bb93f558-91d0-4736-88af-56a3ad9532e9}*SharedItemsImports = 9 HephAudio\HephAudio.vcxitems*{bc8d5b66-59c4-43d9-9a46-c08291b8035d}*SharedItemsImports = 4 HephCommon\HephCommon.vcxitems*{bc8d5b66-59c4-43d9-9a46-c08291b8035d}*SharedItemsImports = 4 + HephAudio\HephAudio.vcxitems*{d483b09f-9d19-4761-bd95-ce4c7bb1fadb}*SharedItemsImports = 4 + HephCommon\HephCommon.vcxitems*{d483b09f-9d19-4761-bd95-ce4c7bb1fadb}*SharedItemsImports = 4 HephCommon\HephCommon.vcxitems*{de064538-da5c-4e0e-b44c-6a25c86fb48f}*SharedItemsImports = 9 EndGlobalSection EndGlobal diff --git a/HephCommon/HeaderFiles/Buffers/BufferBase.h b/HephCommon/HeaderFiles/Buffers/BufferBase.h index 92fd2ef6..c159363d 100644 --- a/HephCommon/HeaderFiles/Buffers/BufferBase.h +++ b/HephCommon/HeaderFiles/Buffers/BufferBase.h @@ -128,6 +128,14 @@ namespace Heph */ virtual Tself operator<<(size_t rhs) const { + if (rhs >= this->size) + { + Tself result{}; + result.pData = BufferBase::Allocate(this->SizeAsByte()); + result.size = this->size; + return result; + } + const size_t thisSize_byte = this->SizeAsByte(); const size_t rhsSize_byte = BufferBase::SizeAsByte(rhs); @@ -151,11 +159,16 @@ namespace Heph */ virtual BufferBase& operator<<=(size_t rhs) { - if (rhs > 0) + if (rhs >= this->size) + { + this->Reset(); + } + else if (rhs > 0) { (void)std::memcpy(this->pData, this->pData + rhs, this->SizeAsByte() - BufferBase::SizeAsByte(rhs)); BufferBase::Initialize(this->pData + this->size - rhs, this->pData + this->size); } + return *this; } @@ -168,6 +181,14 @@ namespace Heph */ virtual Tself operator>>(size_t rhs) const { + if (rhs >= this->size) + { + Tself result{}; + result.pData = BufferBase::Allocate(this->SizeAsByte()); + result.size = this->size; + return result; + } + const size_t thisSize_byte = this->SizeAsByte(); Tself result{}; @@ -190,7 +211,11 @@ namespace Heph */ virtual BufferBase& operator>>=(size_t rhs) { - if (rhs > 0) + if (rhs >= this->size) + { + this->Reset(); + } + else if (rhs > 0) { (void)std::memcpy(this->pData + rhs, this->pData, this->SizeAsByte() - BufferBase::SizeAsByte(rhs)); BufferBase::Initialize(this->pData, this->pData + rhs); @@ -391,8 +416,13 @@ namespace Heph */ virtual void Replace(const Tself& rhs, size_t index, size_t size) { + if (size > rhs.size) + { + HEPH_RAISE_AND_THROW_EXCEPTION(this, InvalidArgumentException(HEPH_FUNC, "size cannot be greater than the rhs buffer size")) + } + BufferBase::Replace(this->pData, this->SizeAsByte(), rhs.pData, - rhs.SizeAsByte(), BufferBase::SizeAsByte(index)); + BufferBase::SizeAsByte(size), BufferBase::SizeAsByte(index)); } /** @@ -495,7 +525,7 @@ namespace Heph * @param pDataEnd end of the memory region. */ template - static typename std::enable_if::value>::type Initialize(U* pData, U* pDataEnd) + static typename std::enable_if::value>::type Initialize(U* pData, U* pDataEnd) { (void)std::memset(pData, 0, ((uint8_t*)pDataEnd) - ((uint8_t*)pData)); } @@ -641,6 +671,10 @@ namespace Heph { return BufferBase::Append(pThisData, thisSize_byte, pRhsData, rhsSize_byte); } + else if (index_byte == 0) + { + return BufferBase::Prepend(pThisData, thisSize_byte, pRhsData, rhsSize_byte); + } Tdata* pResultData = (Tdata*)std::realloc(pThisData, thisSize_byte + rhsSize_byte); if (pResultData == nullptr) @@ -716,7 +750,7 @@ namespace Heph static void Replace(Tdata* pThisData, size_t thisSize_byte, Tdata* pRhsData, size_t rhsSize_byte, size_t index_byte) { - if (rhsSize_byte > 0) + if (thisSize_byte > 0 && rhsSize_byte > 0) { if (pThisData == nullptr) { diff --git a/HephCommon/HeaderFiles/Buffers/BufferOperators.h b/HephCommon/HeaderFiles/Buffers/BufferOperators.h index 6d399c98..aafb9e34 100644 --- a/HephCommon/HeaderFiles/Buffers/BufferOperators.h +++ b/HephCommon/HeaderFiles/Buffers/BufferOperators.h @@ -12,7 +12,7 @@ namespace Heph #pragma region Event /** * @brief contains the results of the \link BufferOperatorEvents::OnResultCreated BufferOperatorEvents::OnResultCreated \endlink event. - * + * */ template struct HEPH_API BufferOperatorResultCreatedEventArgs : public EventArgs @@ -36,7 +36,7 @@ namespace Heph #pragma region Addition /** * @brief provides + and += operators to the buffer. - * + * */ template class HEPH_API BufferAdditionOperator @@ -151,7 +151,7 @@ namespace Heph #pragma region Subtraction /** * @brief provides - and -= operators to the buffer. - * + * */ template class HEPH_API BufferSubtractionOperator @@ -310,7 +310,7 @@ namespace Heph #pragma region Multiplication /** * @brief provides * and *= operators to the buffer. - * + * */ template class HEPH_API BufferMultiplicationOperator @@ -425,7 +425,7 @@ namespace Heph #pragma region Division /** * @brief provides / and /= operators to the buffer. - * + * */ template class HEPH_API BufferDivisionOperator @@ -490,7 +490,7 @@ namespace Heph } template - static inline typename std::enable_if::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs) + static inline typename std::enable_if::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs) { Lhs result{}; BufferOperatorResultCreatedEventArgs args(lhs, rhs, result); @@ -545,7 +545,7 @@ namespace Heph } template - static inline typename std::enable_if, U>::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs) + static inline typename std::enable_if, U>::value, Lhs>::type ImplRhs(const U& rhs, const Lhs& lhs) { if (lhs.Size() != rhs.Size()) { @@ -584,7 +584,7 @@ namespace Heph #pragma region Arithmetic /** * @brief provides arithmetic operators to the buffer. - * + * */ template class HEPH_API BufferArithmeticOperators : @@ -602,7 +602,7 @@ namespace Heph #pragma region Unary Minus /** * @brief provides unary minus operator to the buffer. - * + * */ template class HEPH_API BufferUnaryMinusOperator diff --git a/HephCommon/HeaderFiles/Exceptions/Exception.h b/HephCommon/HeaderFiles/Exceptions/Exception.h index 8d533d18..8dc99727 100644 --- a/HephCommon/HeaderFiles/Exceptions/Exception.h +++ b/HephCommon/HeaderFiles/Exceptions/Exception.h @@ -26,7 +26,7 @@ */ #define HEPH_RAISE_AND_THROW_EXCEPTION(pSender, ex) { \ (ex).Raise((const void*)(pSender)); \ - throw *Heph::Exception::GetLastException().get(); \ + throw (ex); \ } namespace Heph diff --git a/HephCommon/HeaderFiles/HephShared.h b/HephCommon/HeaderFiles/HephShared.h index e7a36d04..6bd44341 100644 --- a/HephCommon/HeaderFiles/HephShared.h +++ b/HephCommon/HeaderFiles/HephShared.h @@ -168,7 +168,18 @@ namespace Heph */ HEPH_API void ChangeEndian(uint8_t* pData, uint8_t dataSize); - inline constexpr Endian operator!(const Endian& lhs) { return (lhs & Endian::Big) ? Endian::Little : ((lhs == Endian::Little) ? Endian::Big : Endian::Unknown); } + inline constexpr Endian operator!(const Endian& lhs) + { + switch (lhs) + { + case Endian::Little: + return Endian::Big; + case Endian::Big: + return Endian::Little; + default: + return Endian::Unknown; + } + } /** * endianness of the current system. @@ -180,7 +191,7 @@ namespace Heph * changes the endianness of the provided data. * */ -#define HEPH_CHANGE_ENDIAN(pData, dataSize) Heph::ChangeEndian(pData, dataSize) +#define HEPH_CHANGE_ENDIAN(pData, dataSize) Heph::ChangeEndian((uint8_t*)(pData), dataSize) enum ConvolutionMode { diff --git a/HephCommon/HeaderFiles/HephTypeTraits.h b/HephCommon/HeaderFiles/HephTypeTraits.h index ba85039d..2bbe4ffe 100644 --- a/HephCommon/HeaderFiles/HephTypeTraits.h +++ b/HephCommon/HeaderFiles/HephTypeTraits.h @@ -34,27 +34,27 @@ namespace Heph template struct has_addition_assignment_operator : std::false_type {}; template - struct has_addition_assignment_operator::value and std::is_arithmetic::value>::type> + struct has_addition_assignment_operator::value&& std::is_arithmetic::value>::type> : std::true_type {}; template - struct has_addition_assignment_operator() += std::declval())>::value>::type> : std::true_type {}; template struct has_subtraction_assignment_operator : std::false_type {}; template - struct has_subtraction_assignment_operator::value and std::is_arithmetic::value>::type> + struct has_subtraction_assignment_operator::value&& std::is_arithmetic::value>::type> : std::true_type {}; template - struct has_subtraction_assignment_operator() -= std::declval())>::value>::type> : std::true_type {}; template struct has_multiplication_assignment_operator : std::false_type {}; template - struct has_multiplication_assignment_operator::value and std::is_arithmetic::value>::type> + struct has_multiplication_assignment_operator::value&& std::is_arithmetic::value>::type> : std::true_type {}; template struct has_multiplication_assignment_operator struct has_division_assignment_operator : std::false_type {}; template - struct has_division_assignment_operator::value and std::is_arithmetic::value>::type> + struct has_division_assignment_operator::value&& std::is_arithmetic::value>::type> : std::true_type {}; template struct has_division_assignment_operator struct has_arithmetic_operators::value and - has_subtraction_operator::value and - has_multiplication_operator::value and - has_division_operator::value and - has_addition_assignment_operator::value and - has_subtraction_assignment_operator::value and - has_multiplication_assignment_operator::value and + has_addition_operator::value&& + has_subtraction_operator::value&& + has_multiplication_operator::value&& + has_division_operator::value&& + has_addition_assignment_operator::value&& + has_subtraction_assignment_operator::value&& + has_multiplication_assignment_operator::value&& has_division_assignment_operator::value >::type> : std::true_type {}; #pragma endregion diff --git a/HephCommon/SourceFiles/StringHelpers.cpp b/HephCommon/SourceFiles/StringHelpers.cpp index e74ab725..f080fa5f 100644 --- a/HephCommon/SourceFiles/StringHelpers.cpp +++ b/HephCommon/SourceFiles/StringHelpers.cpp @@ -141,7 +141,7 @@ namespace Heph std::string StringHelpers::ToString(const Guid& guid) { char buffer[HEPH_STRING_HELPERS_TO_STRING_BUFFER_SIZE]{ 0 }; - (void)sprintf(buffer, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid.data1, guid.data2, guid.data3, + (void)sprintf(buffer, "%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX", guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7]); return buffer; @@ -149,25 +149,25 @@ namespace Heph std::string StringHelpers::ToHexString(int8_t value) { char buffer[HEPH_STRING_HELPERS_TO_STRING_BUFFER_SIZE]{ 0 }; - (void)sprintf(buffer, "0x%02X", value); + (void)sprintf(buffer, "0x%02hhX", value); return buffer; } std::string StringHelpers::ToHexString(uint8_t value) { char buffer[HEPH_STRING_HELPERS_TO_STRING_BUFFER_SIZE]{ 0 }; - (void)sprintf(buffer, "0x%02X", value); + (void)sprintf(buffer, "0x%02hhX", value); return buffer; } std::string StringHelpers::ToHexString(int16_t value) { char buffer[HEPH_STRING_HELPERS_TO_STRING_BUFFER_SIZE]{ 0 }; - (void)sprintf(buffer, "0x%04X", value); + (void)sprintf(buffer, "0x%04hX", value); return buffer; } std::string StringHelpers::ToHexString(uint16_t value) { char buffer[HEPH_STRING_HELPERS_TO_STRING_BUFFER_SIZE]{ 0 }; - (void)sprintf(buffer, "0x%04X", value); + (void)sprintf(buffer, "0x%04hX", value); return buffer; } std::string StringHelpers::ToHexString(int32_t value) @@ -240,48 +240,78 @@ namespace Heph { Guid guid; const std::vector dataStr = StringHelpers::Split(string, "-"); - (void)sscanf(dataStr[0].c_str(), "%x", &guid.data1); - (void)sscanf(dataStr[1].c_str(), "%hx", &guid.data2); - (void)sscanf(dataStr[2].c_str(), "%hx", &guid.data3); - (void)sscanf(dataStr[3].c_str(), "%hhx", guid.data4); - (void)sscanf(dataStr[3].c_str() + 2, "%hhx", guid.data4 + 1); - (void)sscanf(dataStr[4].c_str(), "%hhx%hhx%hhx%hhx%hhx%hhx", guid.data4 + 2, guid.data4 + 3, guid.data4 + 4, guid.data4 + 5, guid.data4 + 6, guid.data4 + 7); + (void)sscanf(dataStr[0].c_str(), "%08X", &guid.data1); + (void)sscanf(dataStr[1].c_str(), "%04hX", &guid.data2); + (void)sscanf(dataStr[2].c_str(), "%04hX", &guid.data3); + (void)sscanf(dataStr[3].c_str(), "%02hhX", guid.data4); + (void)sscanf(dataStr[3].c_str() + 2, "%02hhX", guid.data4 + 1); + (void)sscanf(dataStr[4].c_str(), "%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX", guid.data4 + 2, guid.data4 + 3, guid.data4 + 4, guid.data4 + 5, guid.data4 + 6, guid.data4 + 7); return guid; } int16_t StringHelpers::HexStringToS16(const std::string& hexString) { int16_t number = 0; - (void)sscanf(hexString.c_str(), "%hX", &number); + + if(hexString.find("0x") == 0) + (void)sscanf(hexString.c_str(), "0x%04hX", &number); + else + (void)sscanf(hexString.c_str(), "%04hX", &number); + return number; } uint16_t StringHelpers::HexStringToU16(const std::string& hexString) { uint16_t number = 0; - (void)sscanf(hexString.c_str(), "%hX", &number); + + if (hexString.find("0x") == 0) + (void)sscanf(hexString.c_str(), "0x%04hX", &number); + else + (void)sscanf(hexString.c_str(), "%04hX", &number); + return number; } int32_t StringHelpers::HexStringToS32(const std::string& hexString) { int32_t number = 0; - (void)sscanf(hexString.c_str(), "%X", &number); + + if (hexString.find("0x") == 0) + (void)sscanf(hexString.c_str(), "0x%08X", &number); + else + (void)sscanf(hexString.c_str(), "%08X", &number); + return number; } uint32_t StringHelpers::HexStringToU32(const std::string& hexString) { uint32_t number = 0; - (void)sscanf(hexString.c_str(), "%X", &number); + + if (hexString.find("0x") == 0) + (void)sscanf(hexString.c_str(), "0x%08X", &number); + else + (void)sscanf(hexString.c_str(), "%08X", &number); + return number; } int64_t StringHelpers::HexStringToS64(const std::string& hexString) { int64_t number = 0; - (void)sscanf(hexString.c_str(), "%llX", &number); + + if (hexString.find("0x") == 0) + (void)sscanf(hexString.c_str(), "0x%016llX", &number); + else + (void)sscanf(hexString.c_str(), "%016llX", &number); + return number; } uint64_t StringHelpers::HexStringToU64(const std::string& hexString) { uint64_t number = 0; - (void)sscanf(hexString.c_str(), "%llX", &number); + + if (hexString.find("0x") == 0) + (void)sscanf(hexString.c_str(), "0x%016llX", &number); + else + (void)sscanf(hexString.c_str(), "%016llX", &number); + return number; } } \ No newline at end of file diff --git a/test/HephCommon/BufferBaseTest.cpp b/test/HephCommon/BufferBaseTest.cpp new file mode 100644 index 00000000..0f54a8a4 --- /dev/null +++ b/test/HephCommon/BufferBaseTest.cpp @@ -0,0 +1,897 @@ +#include "gtest/gtest.h" +#include "Buffers/BufferBase.h" +#include + +using namespace Heph; +using test_data_t = uint32_t; + +class TestBuffer : public BufferBase +{ +public: + TestBuffer() : BufferBase() {} + + explicit TestBuffer(size_t size) : BufferBase(size) {} + + TestBuffer(size_t size, BufferFlags flags) : BufferBase(size, flags) {} + + TestBuffer(const std::initializer_list& rhs) : BufferBase(rhs) {} + + TestBuffer(const TestBuffer& rhs) : BufferBase(rhs) {} + + TestBuffer(TestBuffer&& rhs) noexcept : BufferBase(std::move(rhs)) {} + + TestBuffer& operator=(const std::initializer_list& rhs) + { + this->Release(); + + if (rhs.size() > 0) + { + this->size = rhs.size(); + const size_t size_byte = this->SizeAsByte(); + + this->pData = BufferBase::AllocateUninitialized(size_byte); + (void)std::memcpy(this->pData, rhs.begin(), size_byte); + } + + return *this; + } + + TestBuffer& operator=(const TestBuffer& rhs) + { + this->Release(); + + if (this != &rhs && !rhs.IsEmpty()) + { + const size_t size_byte = rhs.SizeAsByte(); + + this->pData = BufferBase::AllocateUninitialized(size_byte); + (void)std::memcpy(this->pData, rhs.pData, size_byte); + + this->size = rhs.size; + } + + return *this; + } + + TestBuffer& operator=(TestBuffer&& rhs) noexcept + { + this->Release(); + + if (this != &rhs) + { + this->pData = rhs.pData; + this->size = rhs.size; + + rhs.pData = nullptr; + rhs.size = 0; + } + + return *this; + } +}; + +void PrintTo(const TestBuffer& b, std::ostream* os) +{ + *os << "{"; + + for (size_t i = 0; i < b.Size(); ++i) + { + *os << b[i]; + if (i != b.Size() - 1) + { + *os << ", "; + } + } + + *os << "}"; +} + +TEST(BufferBaseTest, Constructors) +{ + { + TestBuffer b; + EXPECT_EQ(b.Size(), 0); + EXPECT_TRUE(b.begin() == nullptr); + } + + { + TestBuffer b(5); + EXPECT_EQ(b.Size(), 5); + + for (const test_data_t& data : b) + EXPECT_EQ(data, 0); + } + + { + TestBuffer b(5, BufferFlags::AllocUninitialized); + EXPECT_EQ(b.Size(), 5); + EXPECT_FALSE(b.begin() == nullptr); + } + + { + TestBuffer b = { 1, 5, 3, 4, 7 }; + test_data_t expected[5] = { 1, 5, 3, 4, 7 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b[i], expected[i]); + } +} + +TEST(BufferBaseTest, Copy) +{ + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2(b1); + + EXPECT_EQ(b1.Size(), b2.Size()); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], b2[i]); +} + +TEST(BufferBaseTest, Move) +{ + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + + test_data_t* b1_begin = b1.begin(); + size_t b1_size = b1.Size(); + + TestBuffer b2(std::move(b1)); + + EXPECT_EQ(b1.Size(), 0); + EXPECT_TRUE(b1.begin() == nullptr); + EXPECT_EQ(b2.Size(), b1_size); + EXPECT_EQ(b2.begin(), b1_begin); +} + +TEST(BufferBaseTest, LeftShift) +{ + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + + { + TestBuffer b2(b1 << 2); + test_data_t expected[] = { 3, 4, 5, 0, 0 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2(b1 << 0); + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2(b1 << 10); + test_data_t expected[] = { 0, 0, 0, 0, 0 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2 = b1; + b2 <<= 2; + test_data_t expected[] = { 3, 4, 5, 0, 0 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2 = b1; + b2 <<= 0; + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2 = b1; + b2 <<= 10; + test_data_t expected[] = { 0, 0, 0, 0, 0 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } +} + +TEST(BufferBaseTest, RightShift) +{ + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + + { + TestBuffer b2(b1 >> 2); + test_data_t expected[] = { 0, 0, 1, 2, 3 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2(b1 >> 0); + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2(b1 >> 10); + test_data_t expected[] = { 0, 0, 0, 0, 0 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2 = b1; + b2 >>= 2; + test_data_t expected[] = { 0, 0, 1, 2, 3 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2 = b1; + b2 >>= 0; + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } + + { + TestBuffer b2 = b1; + b2 >>= 10; + test_data_t expected[] = { 0, 0, 0, 0, 0 }; + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b2[i], expected[i]); + } +} + +TEST(BufferBaseTest, Compare) +{ + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 1, 2, 3, 4, 5 }; + + EXPECT_EQ(b1, b2); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 1, 2, 3, 4, 70 }; + + EXPECT_NE(b1, b2); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 1, 2, 3 }; + + EXPECT_NE(b1, b2); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + EXPECT_NE(b1, b2); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2; + + EXPECT_NE(b1, b2); + } +} + +TEST(BufferBaseTest, SubscriptOperator) +{ + TestBuffer b = { 1, 2, 3, 4, 5, 6, 7 }; + + EXPECT_EQ(b[0], 1); + EXPECT_EQ(b[1], 2); + EXPECT_EQ(b[4], 5); + EXPECT_EQ(b[6], 7); +} + +TEST(BufferBaseTest, Size) +{ + TestBuffer b; + + EXPECT_EQ(b.Size(), 0); + + b = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + EXPECT_EQ(b.Size(), 8); +} + +TEST(BufferBaseTest, SizeAsByte) +{ + TestBuffer b; + + EXPECT_EQ(b.Size(), 0); + EXPECT_EQ(b.SizeAsByte(), 0); + + b = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + EXPECT_EQ(b.Size(), 8); + EXPECT_EQ(b.SizeAsByte(), 8 * sizeof(test_data_t)); +} + +TEST(BufferBaseTest, At) +{ + TestBuffer b = { 1, 2, 3, 4, 5, 6, 7 }; + + EXPECT_EQ(b.At(0), 1); + EXPECT_EQ(b.At(1), 2); + EXPECT_EQ(b.At(4), 5); + EXPECT_EQ(b.At(6), 7); + + EXPECT_THROW(b.At(b.Size() + 1), InvalidArgumentException); +} + +TEST(BufferBaseTest, IsEmpty) +{ + TestBuffer b; + + EXPECT_TRUE(b.IsEmpty()); + + b = { 1, 2, 3, 4, 5 }; + + EXPECT_FALSE(b.IsEmpty()); +} + +TEST(BufferBaseTest, Reset) +{ + TestBuffer b = { 1, 2, 3, 4, 5, 6, 7 }; + + b.Reset(); + + for (size_t i = 0; i < b.Size(); ++i) + EXPECT_EQ(b[i], 0); +} + +TEST(BufferBaseTest, Release) +{ + TestBuffer b = { 1, 2, 3, 4, 5, 6, 7 }; + + b.Release(); + + EXPECT_TRUE(b.begin() == nullptr); + EXPECT_EQ(b.Size(), 0); + + // test if actually freed? +} + +TEST(BufferBaseTest, Subbuffer) +{ + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + + { + TestBuffer sb = b.SubBuffer(2, 2); + test_data_t expected[] = { 3, 4 }; + + EXPECT_EQ(sb.Size(), 2); + + for (size_t i = 0; i < 2; ++i) + EXPECT_EQ(sb[i], expected[i]); + } + + { + TestBuffer sb = b.SubBuffer(3, 5); + test_data_t expected[] = { 4, 5, 0, 0, 0 }; + + EXPECT_EQ(sb.Size(), 5); + + for (size_t i = 0; i < 3; ++i) + EXPECT_EQ(sb[i], expected[i]); + } + + EXPECT_THROW(b.SubBuffer(b.Size() + 1, 5), InvalidArgumentException); + + { + TestBuffer sb = b.SubBuffer(3, 0); + EXPECT_EQ(sb.Size(), 0); + } + } + + + { + TestBuffer b; + EXPECT_THROW(b.SubBuffer(0, 3), InvalidArgumentException); + } +} + +TEST(BufferBaseTest, Prepend) +{ + { + TestBuffer b1 = { 4, 5, 6 }; + TestBuffer b2 = { 1, 2, 3 }; + test_data_t expected[] = { 1, 2, 3, 4, 5, 6 }; + size_t expectedSize = b1.Size() + b2.Size(); + + b1.Prepend(b2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 4, 5, 6 }; + TestBuffer b2; + test_data_t expected[] = { 4, 5, 6 }; + size_t expectedSize = b1.Size(); + + b1.Prepend(b2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2 = { 1, 2, 3 }; + test_data_t expected[] = { 1, 2, 3 }; + size_t expectedSize = b2.Size(); + + b1.Prepend(b2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2; + + b1.Prepend(b2); + EXPECT_EQ(b1.Size(), 0); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }; + size_t expectedSize = b.Size() * 2; + + b.Prepend(b); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } +} + +TEST(BufferBaseTest, Append) +{ + { + TestBuffer b1 = { 4, 5, 6 }; + TestBuffer b2 = { 1, 2, 3 }; + test_data_t expected[] = { 4, 5, 6, 1, 2, 3 }; + size_t expectedSize = b1.Size() + b2.Size(); + + b1.Append(b2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 4, 5, 6 }; + TestBuffer b2; + test_data_t expected[] = { 4, 5, 6 }; + size_t expectedSize = b1.Size(); + + b1.Append(b2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2 = { 1, 2, 3 }; + test_data_t expected[] = { 1, 2, 3 }; + size_t expectedSize = b2.Size(); + + b1.Append(b2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < b1.Size(); ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2; + + b1.Append(b2); + EXPECT_EQ(b1.Size(), 0); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }; + size_t expectedSize = b.Size() * 2; + + b.Append(b); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } +} + +TEST(BufferBaseTest, Insert) +{ + { + TestBuffer b1 = { 1, 2, 3, 4 }; + TestBuffer b2 = { 5, 6, 7, 8 }; + test_data_t expected[] = { 1, 2, 5, 6, 7, 8, 3, 4 }; + size_t expectedSize = b1.Size() + b2.Size(); + + b1.Insert(b2, 2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 1, 2, 3, 4 }; + TestBuffer b2 = { 5, 6, 7, 8 }; + test_data_t expected[] = { 5, 6, 7, 8, 1, 2, 3, 4 }; + size_t expectedSize = b1.Size() + b2.Size(); + + b1.Insert(b2, 0); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 1, 2, 3, 4 }; + TestBuffer b2 = { 5, 6, 7, 8 }; + test_data_t expected[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + size_t expectedSize = b1.Size() + b2.Size(); + + b1.Insert(b2, b1.Size()); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 1, 2, 3, 4 }; + TestBuffer b2 = { 5, 6, 7, 8 }; + test_data_t expected[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + EXPECT_THROW(b1.Insert(b2, b1.Size() + 1), InvalidArgumentException); + } + + { + TestBuffer b1 = { 1, 2, 3, 4 }; + TestBuffer b2; + test_data_t expected[] = { 1, 2, 3, 4 }; + size_t expectedSize = b1.Size(); + + b1.Insert(b2, 0); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2 = { 1, 2, 3, 4 }; + test_data_t expected[] = { 1, 2, 3, 4 }; + size_t expectedSize = b2.Size(); + + b1.Insert(b2, 0); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2; + + b1.Insert(b2, 0); + EXPECT_EQ(b1.Size(), 0); + } + + { + TestBuffer b = { 1, 2, 3, 4 }; + test_data_t expected[] = { 1, 2, 1, 2, 3, 4, 3, 4 }; + size_t expectedSize = b.Size() * 2; + + b.Insert(b, 2); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } +} + +TEST(BufferBaseTest, Cut) +{ + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 5 }; + size_t expectedSize = 3; + + b.Cut(2, 2); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 4, 5 }; + size_t expectedSize = 2; + + b.Cut(0, 3); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3 }; + size_t expectedSize = 3; + + b.Cut(3, 10); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 4, 5 }; + size_t expectedSize = 2; + + b.Cut(0, 3); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + size_t expectedSize = b.Size(); + + b.Cut(2, 0); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b; + b.Cut(0, 0); + EXPECT_EQ(b.Size(), 0); + } +} + +TEST(BufferBaseTest, Replace) +{ + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 6, 7, 8 }; + test_data_t expected[] = { 6, 7, 3, 4, 5 }; + size_t expectedSize = b1.Size(); + + b1.Replace(b2, 0, 2); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 6, 7, 8 }; + + EXPECT_THROW(b1.Replace(b2, 0, b2.Size() + 1), InvalidArgumentException); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 6, 7, 8 }; + test_data_t expected[] = { 1, 2, 3, 6, 7 }; + size_t expectedSize = b1.Size(); + + b1.Replace(b2, 3); + + EXPECT_EQ(b1.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2 = { 6, 7, 8 }; + + EXPECT_THROW(b1.Replace(b2, b1.Size()), InvalidArgumentException); + } + + { + TestBuffer b1 = { 1, 2, 3, 4, 5 }; + TestBuffer b2; + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + + b1.Replace(b2, 0); + + for (size_t i = 0; i < 5; ++i) + EXPECT_EQ(b1[i], expected[i]); + } + + { + TestBuffer b1; + TestBuffer b2 = { 1, 2, 3, 4, 5 }; + + b1.Replace(b2, 0); + + EXPECT_EQ(b1.Size(), 0); + } + + { + TestBuffer b1; + TestBuffer b2; + + b1.Replace(b2, 0); + + EXPECT_EQ(b1.Size(), 0); + } +} + +TEST(BufferBaseTest, Resize) +{ + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3, 4, 5, 0, 0, 0 }; + size_t expectedSize = 8; + + b.Resize(expectedSize); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3 }; + size_t expectedSize = 3; + + b.Resize(expectedSize); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 1, 2, 3, 4, 5 }; + size_t expectedSize = b.Size(); + + b.Resize(expectedSize); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + + b.Resize(0); + + EXPECT_EQ(b.Size(), 0); + EXPECT_TRUE(b.begin() == nullptr); + } +} + +TEST(BufferBaseTest, Reverse) +{ + { + TestBuffer b = { 1, 2, 3, 4, 5 }; + test_data_t expected[] = { 5, 4, 3, 2, 1 }; + size_t expectedSize = b.Size(); + + b.Reverse(); + + EXPECT_EQ(b.Size(), expectedSize); + + for (size_t i = 0; i < expectedSize; ++i) + EXPECT_EQ(b[i], expected[i]); + } + + { + TestBuffer b; + b.Reverse(); + EXPECT_EQ(b.Size(), 0); + EXPECT_TRUE(b.begin() == nullptr); + } +} + +TEST(BufferBaseTest, begin) +{ + { + TestBuffer b; + EXPECT_TRUE(b.begin() == nullptr); + } + + { + TestBuffer b(1); + EXPECT_FALSE(b.begin() == nullptr); + } +} + +TEST(BufferBaseTest, end) +{ + { + TestBuffer b; + EXPECT_TRUE(b.end() == nullptr); + } + + { + TestBuffer b(1); + test_data_t* expected = b.begin() + b.Size(); + + EXPECT_EQ(b.end(), expected); + } +} \ No newline at end of file diff --git a/test/HephCommon/ComplexTest.cpp b/test/HephCommon/ComplexTest.cpp new file mode 100644 index 00000000..f6af371c --- /dev/null +++ b/test/HephCommon/ComplexTest.cpp @@ -0,0 +1,117 @@ +#include "gtest/gtest.h" +#include "Complex.h" +#include "HephMath.h" +#include + +using namespace Heph; + +namespace Heph +{ + void PrintTo(const Complex& c, std::ostream* os) + { + if (c.imag >= 0) + *os << c.real << " + " << c.imag << "j"; + else + *os << c.real << " - " << -c.imag << "j"; + } +} + +TEST(ComplexTest, Compare) +{ + Complex c(5, 3); + + EXPECT_TRUE(c == Complex(5, 3)); + EXPECT_FALSE(c == Complex(-5, 3)); + EXPECT_FALSE(c == Complex(5, -3)); + EXPECT_FALSE(c == Complex(-5, -3)); + + EXPECT_FALSE(c != Complex(5, 3)); + EXPECT_TRUE(c != Complex(-5, 3)); + EXPECT_TRUE(c != Complex(5, -3)); + EXPECT_TRUE(c != Complex(-5, -3)); +} + +TEST(ComplexTest, Add) +{ + Complex c1(5, 3); + Complex c2(8, -20); + + EXPECT_EQ(c1 + c2, Complex(13, -17)); + EXPECT_EQ(c1 + 10, Complex(15, 3)); + EXPECT_EQ(10 + c1, Complex(15, 3)); + + c1 += c2; + EXPECT_EQ(c1, Complex(13, -17)); + + c2 += 10; + EXPECT_EQ(c2, Complex(18, -20)); +} + +TEST(ComplexTest, Subtract) +{ + Complex c1(5, 3); + Complex c2(8, -20); + + EXPECT_EQ(c1 - c2, Complex(-3, 23)); + EXPECT_EQ(c1 - 10, Complex(-5, 3)); + EXPECT_EQ(10 - c1, Complex(5, -3)); + + c1 -= c2; + EXPECT_EQ(c1, Complex(-3, 23)); + + c2 -= 10; + EXPECT_EQ(c2, Complex(-2, -20)); +} + +TEST(ComplexTest, Multiply) +{ + Complex c1(5, 3); + Complex c2(8, -10); + + EXPECT_EQ(c1 * c2, Complex(70, -26)); + EXPECT_EQ(c1 * 10, Complex(50, 30)); + EXPECT_EQ(10 * c1, Complex(50, 30)); + + c1 *= c2; + EXPECT_EQ(c1, Complex(70, -26)); + + c2 *= 10; + EXPECT_EQ(c2, Complex(80, -100)); +} + +TEST(ComplexTest, Divide) +{ + Complex c1(5, 3); + Complex c2(8, -10); + + EXPECT_EQ(c1 / c2, Complex(5.0 / 82, 37.0 / 82)); + EXPECT_EQ(c1 / 10, Complex(0.5, 0.3)); + EXPECT_EQ(10 / c1, Complex(25.0 / 17, -15.0 / 17)); + + c1 /= c2; + EXPECT_EQ(c1, Complex(5.0 / 82, 37.0 / 82)); + + c2 /= 10; + EXPECT_EQ(c2, Complex(0.8, -1)); +} + +TEST(ComplexTest, Conjugate) +{ + Complex c(5, 3); + + EXPECT_EQ(c.Conjugate(), Complex(5, -3)); +} + +TEST(ComplexTest, Magnitude) +{ + Complex c(3, 4); + + EXPECT_EQ(c.MagnitudeSquared(), 25); + EXPECT_EQ(c.Magnitude(), 5); +} + +TEST(ComplexTest, Phase) +{ + EXPECT_EQ(Complex(1, 1).Phase(), HEPH_MATH_PI / 4); + EXPECT_EQ(Complex(1, sqrt(3)).Phase(), HEPH_MATH_PI / 3); +} \ No newline at end of file diff --git a/test/HephCommon/EventTest.cpp b/test/HephCommon/EventTest.cpp new file mode 100644 index 00000000..03a21573 --- /dev/null +++ b/test/HephCommon/EventTest.cpp @@ -0,0 +1,182 @@ +#include "gtest/gtest.h" +#include "Event.h" +#include "Complex.h" +#include + +using namespace Heph; + +class EventTest : public testing::Test +{ +protected: + static constexpr const char* THIS_KEY = "this"; + static constexpr const char* PARAM1_KEY = "param1"; + static constexpr const char* PARAM2_KEY = "param2"; + static constexpr const char* PARAM3_KEY = "param3"; + +protected: + Event event; + + std::string param1; + int param2; + Complex param3; + + bool handler1; + bool handler2; + bool handler3; + bool handler4; + + EventArgs* pArgs; + EventResult* pResult; + +protected: + EventTest() + { + handler1 = false; + handler2 = false; + handler3 = false; + handler4 = false; + + param1 = "Hello World!"; + param2 = 37; + param3 = Complex(10, 20); + + pArgs = nullptr; + pResult = nullptr; + } + + static void Handler1(const EventParams& params) + { + EventTest* pThis = (EventTest*)params.userEventArgs[THIS_KEY]; + + EXPECT_TRUE(pThis != nullptr); + EXPECT_TRUE(params.userEventArgs.Exists(THIS_KEY)); + EXPECT_EQ(params.userEventArgs[PARAM1_KEY], &pThis->param1); + EXPECT_EQ(params.userEventArgs[PARAM2_KEY], &pThis->param2); + EXPECT_EQ(params.userEventArgs[PARAM3_KEY], &pThis->param3); + EXPECT_EQ(params.userEventArgs["DOES NOT EXIST"], nullptr); + EXPECT_FALSE(params.userEventArgs.Exists("DOES NOT EXIST")); + + pThis->handler1 = true; + } + + static void Handler2(const EventParams& params) + { + EventTest* pThis = (EventTest*)params.userEventArgs[THIS_KEY]; + pThis->handler2 = true; + params.pResult->isHandled = true; + } + + static void Handler3(const EventParams& params) + { + EventTest* pThis = (EventTest*)params.userEventArgs[THIS_KEY]; + pThis->handler3 = true; + } + + static void Handler4(const EventParams& params) + { + EventTest* pThis = (EventTest*)params.userEventArgs[THIS_KEY]; + + EXPECT_EQ(params.pArgs, pThis->pArgs); + EXPECT_EQ(params.pResult, pThis->pResult); + + pThis->handler4 = true; + } +}; + +TEST_F(EventTest, HandlerMethods) +{ + EXPECT_EQ(event.EventHandlerCount(), 0); + EXPECT_FALSE(event); + + event = &Handler1; + EXPECT_EQ(event.EventHandlerCount(), 1); + EXPECT_TRUE(event); + EXPECT_TRUE(event.EventHandlerExists(&Handler1)); + EXPECT_FALSE(event.EventHandlerExists(&Handler2)); + + event = &Handler2; + EXPECT_EQ(event.EventHandlerCount(), 1); + EXPECT_TRUE(event.EventHandlerExists(&Handler2)); + EXPECT_FALSE(event.EventHandlerExists(&Handler1)); + + event.SetEventHandler(&Handler3); + EXPECT_EQ(event.EventHandlerCount(), 1); + EXPECT_TRUE(event.EventHandlerExists(&Handler3)); + EXPECT_FALSE(event.EventHandlerExists(&Handler1)); + EXPECT_FALSE(event.EventHandlerExists(&Handler2)); + + event += &Handler1; + event.AddEventHandler(&Handler2); + EXPECT_EQ(event.EventHandlerCount(), 3); + EXPECT_TRUE(event.EventHandlerExists(&Handler1)); + EXPECT_TRUE(event.EventHandlerExists(&Handler2)); + EXPECT_TRUE(event.EventHandlerExists(&Handler3)); + EXPECT_EQ(event.GetEventHandler(0), &Handler3); + EXPECT_EQ(event.GetEventHandler(1), &Handler1); + EXPECT_EQ(event.GetEventHandler(2), &Handler2); + + event.InsertEventHandler(&Handler4, 2); + EXPECT_EQ(event.GetEventHandler(0), &Handler3); + EXPECT_EQ(event.GetEventHandler(1), &Handler1); + EXPECT_EQ(event.GetEventHandler(2), &Handler4); + EXPECT_EQ(event.GetEventHandler(3), &Handler2); + + event.ClearEventHandlers(); + EXPECT_EQ(event.EventHandlerCount(), 0); + EXPECT_FALSE(event); + + event = &Handler1; + event += &Handler2; + event.ClearAll(); + EXPECT_EQ(event.EventHandlerCount(), 0); + EXPECT_EQ(event.userEventArgs.Size(), 0); + EXPECT_FALSE(event); +} + +TEST_F(EventTest, Invoke) +{ + event = &Handler1; + event += &Handler2; + event += &Handler3; + event += &Handler4; + + EXPECT_EQ(event.userEventArgs.Size(), 0); + event.userEventArgs.Add(THIS_KEY, this); + event.userEventArgs.Add(PARAM1_KEY, ¶m1); + event.userEventArgs.Add(PARAM2_KEY, ¶m2); + event.userEventArgs.Add(PARAM3_KEY, ¶m3); + EXPECT_EQ(event.userEventArgs.Size(), 4); + + event.userEventArgs.Remove(PARAM3_KEY); + EXPECT_EQ(event.userEventArgs.Size(), 3); + EXPECT_FALSE(event.userEventArgs.Exists(PARAM3_KEY)); + event.userEventArgs.Add(PARAM3_KEY, ¶m3); + + event.Invoke(nullptr, nullptr); + + EXPECT_TRUE(handler1); + EXPECT_TRUE(handler2); + EXPECT_FALSE(handler3); + EXPECT_FALSE(handler4); + + handler1 = false; + handler2 = false; + handler3 = false; + handler4 = false; + + event.RemoveEventHandler(1); + event.RemoveEventHandler(&Handler3); + + EventArgs args; + EventResult result; + + pArgs = &args; + pResult = &result; + + event(&args, &result); + + EXPECT_TRUE(handler1); + EXPECT_FALSE(handler2); + EXPECT_FALSE(handler3); + EXPECT_TRUE(handler4); +} \ No newline at end of file diff --git a/test/HephCommon/ExceptionTest.cpp b/test/HephCommon/ExceptionTest.cpp new file mode 100644 index 00000000..cf9c187d --- /dev/null +++ b/test/HephCommon/ExceptionTest.cpp @@ -0,0 +1,115 @@ +#include "gtest/gtest.h" +#include "Exceptions/Exception.h" +#include "Exceptions/ExceptionEventArgs.h" +#include "Exceptions/InsufficientMemoryException.h" +#include "Exceptions/InvalidArgumentException.h" +#include "Exceptions/InvalidOperationException.h" +#include "Exceptions/NotFoundException.h" +#include "Exceptions/NotImplementedException.h" +#include "Exceptions/NotSupportedException.h" +#include "Exceptions/TimeoutException.h" +#include +#include + +#define CHECK_EX_TYPE(pEx, type) { const type* _ex = dynamic_cast(pEx); EXPECT_TRUE(_ex != nullptr); } + +using namespace Heph; + +class ExceptionTest : public testing::Test +{ +protected: + static constexpr const char* METHOD = "Method"; + static constexpr const char* MESSAGE = "Message"; + +protected: + ExceptionTest() + { + Exception::GetExceptions().clear(); + Exception::OnException.ClearAll(); + } + + static void Handler1(const EventParams& params) + { + ExceptionEventArgs* pArgs = dynamic_cast(params.pArgs); + EXPECT_TRUE((&pArgs->exception) != nullptr); + EXPECT_EQ(pArgs->exception.GetMethod(), ExceptionTest::METHOD); + EXPECT_EQ(pArgs->exception.GetMessage(), ExceptionTest::MESSAGE); + } + + static void Handler2(const EventParams& params) + { + ExceptionEventArgs* pArgs = (ExceptionEventArgs*)params.pArgs; + CHECK_EX_TYPE(&pArgs->exception, InvalidArgumentException); + } + + static void TestThread() + { + EXPECT_EQ(Exception::GetExceptions().size(), 0); + HEPH_RAISE_EXCEPTION(nullptr, Exception()); + HEPH_RAISE_EXCEPTION(nullptr, InvalidArgumentException()); + HEPH_RAISE_EXCEPTION(nullptr, Exception()); + EXPECT_EQ(Exception::GetExceptions().size(), 3); + } +}; + +TEST_F(ExceptionTest, Handler) +{ + Exception::OnException = &Handler1; + HEPH_RAISE_EXCEPTION(nullptr, Exception(ExceptionTest::METHOD, ExceptionTest::MESSAGE)); +} + +TEST_F(ExceptionTest, GetName) +{ + std::vector names; + + auto test = [&names](const std::string& name) + { + bool exists = false; + + for (const std::string& n : names) + { + if (n == name) + { + exists = true; + EXPECT_NE(n, name) << "Duplicate exception name \"" << n << "\""; + } + } + + if (!exists) + names.push_back(name); + }; + + test(Exception().GetName()); + test(InsufficientMemoryException().GetName()); + test(InvalidArgumentException().GetName()); + test(InvalidOperationException().GetName()); + test(NotFoundException().GetName()); + test(NotImplementedException().GetName()); + test(NotSupportedException().GetName()); + test(TimeoutException().GetName()); +} + +TEST_F(ExceptionTest, GetExceptions) +{ + // test thread_local + EXPECT_EQ(Exception::GetExceptions().size(), 0); + HEPH_RAISE_EXCEPTION(nullptr, Exception()); + EXPECT_EQ(Exception::GetExceptions().size(), 1); + + std::thread t(&TestThread); + t.join(); + + EXPECT_EQ(Exception::GetExceptions().size(), 1); +} + +TEST_F(ExceptionTest, GetLastException) +{ + EXPECT_TRUE(Exception::GetLastException() == nullptr); + + HEPH_RAISE_EXCEPTION(nullptr, Exception()); + EXPECT_TRUE(Exception::GetLastException() != nullptr); + + Exception::OnException = &Handler2; + HEPH_RAISE_EXCEPTION(nullptr, InvalidArgumentException()); + CHECK_EX_TYPE(Exception::GetLastException().get(), InvalidArgumentException); +} \ No newline at end of file diff --git a/test/HephCommon/GuidTest.cpp b/test/HephCommon/GuidTest.cpp new file mode 100644 index 00000000..9b2a6f5a --- /dev/null +++ b/test/HephCommon/GuidTest.cpp @@ -0,0 +1,70 @@ +#include "gtest/gtest.h" +#include "Guid.h" +#include + +using namespace Heph; + +namespace Heph +{ + void PrintTo(const Guid& guid, std::ostream* os) + { + *os << std::uppercase; + os->width(8); + *os << std::hex << guid.data1 << '-'; + + os->width(4); + *os << std::hex << guid.data2 << '-'; + + os->width(4); + *os << std::hex << guid.data3 << '-'; + + os->width(2); + *os << std::hex + << static_cast(guid.data4[0]) + << static_cast(guid.data4[1]) + << '-' + << static_cast(guid.data4[2]) + << static_cast(guid.data4[3]) + << static_cast(guid.data4[4]) + << static_cast(guid.data4[5]) + << static_cast(guid.data4[6]) + << static_cast(guid.data4[7]); + } +} + +TEST(GuidTest, Compare) +{ + Guid g1; + g1.data1 = 0xABCDEF12; + g1.data2 = 0x3456; + g1.data3 = 0x7890; + g1.data4[0] = 0x53; + g1.data4[1] = 0x78; + g1.data4[4] = 0x2B; + g1.data4[7] = 0xA2; + + Guid g2; + g2.data1 = 0xABCDEF12; + g2.data2 = 0x3456; + g2.data3 = 0x7890; + g2.data4[0] = 0x53; + g2.data4[1] = 0x78; + g2.data4[4] = 0x2B; + g2.data4[7] = 0xA2; + + EXPECT_EQ(g1, g2); + + g2.data1 = 0; + EXPECT_NE(g1, g2); +} + +TEST(GuidTest, GenerateNew) +{ + constexpr size_t iterationCount = 100; + for (size_t i = 0; i < iterationCount; ++i) + { + const Guid g1 = Guid::GenerateNew(); + const Guid g2 = Guid::GenerateNew(); + EXPECT_NE(g1, g2); + } +} \ No newline at end of file diff --git a/test/HephCommon/HephMathTest.cpp b/test/HephCommon/HephMathTest.cpp new file mode 100644 index 00000000..5e47fa88 --- /dev/null +++ b/test/HephCommon/HephMathTest.cpp @@ -0,0 +1,39 @@ +#include "gtest/gtest.h" +#include "HephMath.h" + +TEST(HephMathTest, Sgn) +{ + EXPECT_EQ(HEPH_MATH_SGN(53), 1); + EXPECT_EQ(HEPH_MATH_SGN(-37), -1); + EXPECT_EQ(HEPH_MATH_SGN(0), 0); +} + +TEST(HephMathTest, Min) +{ + EXPECT_EQ(HEPH_MATH_MIN(10, 20), 10); + EXPECT_EQ(HEPH_MATH_MIN(20, 10), 10); + EXPECT_EQ(HEPH_MATH_MIN(-10, 8), -10); + EXPECT_EQ(HEPH_MATH_MIN(0, 8), 0); + EXPECT_EQ(HEPH_MATH_MIN(-7, 0), -7); +} + +TEST(HephMathTest, Max) +{ + EXPECT_EQ(HEPH_MATH_MAX(10, 20), 20); + EXPECT_EQ(HEPH_MATH_MAX(20, 10), 20); + EXPECT_EQ(HEPH_MATH_MAX(-10, 8), 8); + EXPECT_EQ(HEPH_MATH_MAX(0, 8), 8); + EXPECT_EQ(HEPH_MATH_MAX(-7, 0), 0); +} + +TEST(HephMathTest, Rad2Deg) +{ + EXPECT_EQ(HEPH_MATH_RAD_TO_DEG(HEPH_MATH_PI), 180); + EXPECT_EQ(HEPH_MATH_RAD_TO_DEG(-HEPH_MATH_PI / 4), -45); +} + +TEST(HephMathTest, Deg2Rad) +{ + EXPECT_EQ(HEPH_MATH_DEG_TO_RAD(180), HEPH_MATH_PI); + EXPECT_EQ(HEPH_MATH_DEG_TO_RAD(-45), -HEPH_MATH_PI / 4); +} \ No newline at end of file diff --git a/test/HephCommon/HephSharedTest.cpp b/test/HephCommon/HephSharedTest.cpp new file mode 100644 index 00000000..dc7642c2 --- /dev/null +++ b/test/HephCommon/HephSharedTest.cpp @@ -0,0 +1,37 @@ +#include "gtest/gtest.h" +#include "HephShared.h" + +using namespace Heph; + +namespace Heph +{ + void PrintTo(const Endian& endian, std::ostream* os) + { + switch (endian) + { + case Endian::Little: + *os << "Little Endian"; + break; + case Endian::Big: + *os << "Big Endian"; + break; + default: + *os << "Unknown Endian"; + break; + } + } +} + +TEST(HephSharedTest, NotOperator) +{ + EXPECT_EQ(!Endian::Big, Endian::Little); + EXPECT_EQ(!Endian::Little, Endian::Big); + EXPECT_EQ(!Endian::Unknown, Endian::Unknown); +} + +TEST(HephSharedTest, ChangeEndian) +{ + uint16_t x = 0xABCD; + HEPH_CHANGE_ENDIAN(&x, sizeof(uint16_t)); + EXPECT_EQ(x, 0xCDAB); +} \ No newline at end of file diff --git a/test/HephCommon/StringHelpersTest.cpp b/test/HephCommon/StringHelpersTest.cpp new file mode 100644 index 00000000..b0f4b0c5 --- /dev/null +++ b/test/HephCommon/StringHelpersTest.cpp @@ -0,0 +1,147 @@ +#include "gtest/gtest.h" +#include "StringHelpers.h" + +using namespace Heph; + +TEST(StringHelpersTest, StrToWide) +{ + std::string str = "Hello World!"; + std::wstring wstr = L"Hello World!"; + + EXPECT_EQ(StringHelpers::StrToWide(str), wstr); +} + +TEST(StringHelpersTest, WideToStr) +{ + std::string str = "Hello World!"; + std::wstring wstr = L"Hello World!"; + + EXPECT_EQ(StringHelpers::WideToStr(wstr), str); +} + +TEST(StringHelpersTest, Split) +{ + { + std::string str = "Hello World"; + std::vector split_str1 = { "Hello World" }; + std::vector split_str2 = { "Hello", "World" }; + std::vector split_str3 = { "He", "", "o Wor", "d" }; + std::vector split_str4 = { "", "ello World" }; + std::vector split_str5 = { "Hello Worl", "" }; + + EXPECT_EQ(StringHelpers::Split(str, ""), split_str1); + EXPECT_EQ(StringHelpers::Split(str, " "), split_str2); + EXPECT_EQ(StringHelpers::Split(str, "l"), split_str3); + EXPECT_EQ(StringHelpers::Split(str, "H"), split_str4); + EXPECT_EQ(StringHelpers::Split(str, "d"), split_str5); + } + + { + std::wstring str = L"Hello World"; + std::vector split_str1 = { L"Hello World" }; + std::vector split_str2 = { L"Hello", L"World" }; + std::vector split_str3 = { L"He", L"", L"o Wor", L"d" }; + std::vector split_str4 = { L"", L"ello World" }; + std::vector split_str5 = { L"Hello Worl", L"" }; + + EXPECT_EQ(StringHelpers::Split(str, L""), split_str1); + EXPECT_EQ(StringHelpers::Split(str, L" "), split_str2); + EXPECT_EQ(StringHelpers::Split(str, L"l"), split_str3); + EXPECT_EQ(StringHelpers::Split(str, L"H"), split_str4); + EXPECT_EQ(StringHelpers::Split(str, L"d"), split_str5); + } +} + +TEST(StringHelpersTest, ToString) +{ + int16_t s16 = -16; + uint16_t u16 = 16; + int32_t s32 = -32; + uint32_t u32 = 32; + int64_t s64 = -64; + uint64_t u64 = 64; + float f = 1.23456289; + double d = 5.43184214; + + EXPECT_EQ(StringHelpers::ToString(s16), "-16"); + EXPECT_EQ(StringHelpers::ToString(u16), "16"); + EXPECT_EQ(StringHelpers::ToString(s32), "-32"); + EXPECT_EQ(StringHelpers::ToString(u32), "32"); + EXPECT_EQ(StringHelpers::ToString(s64), "-64"); + EXPECT_EQ(StringHelpers::ToString(u64), "64"); + EXPECT_EQ(StringHelpers::ToString(f, 5), "1.23456"); + EXPECT_EQ(StringHelpers::ToString(d, 3), "5.432"); + + Guid guid; + guid.data1 = 0xABCDEF12; + guid.data2 = 0x3456; + guid.data3 = 0x7890; + guid.data4[0] = 0x53; + guid.data4[1] = 0x78; + guid.data4[4] = 0x2B; + guid.data4[7] = 0xA2; + + EXPECT_EQ(StringHelpers::ToString(guid), "ABCDEF12-3456-7890-5378-00002B0000A2"); +} + +TEST(StringHelpersTest, ToHexString) +{ + int8_t s8 = 0xAB; + int16_t s16 = 0xAB00; + int32_t s32 = 0xABCDEF00; + int64_t s64 = 0xABCDEF1234567800; + + EXPECT_EQ(StringHelpers::ToHexString(s8), "0xAB"); + EXPECT_EQ(StringHelpers::ToHexString((uint8_t)s8), "0xAB"); + + EXPECT_EQ(StringHelpers::ToHexString(s16), "0xAB00"); + EXPECT_EQ(StringHelpers::ToHexString((uint16_t)s16), "0xAB00"); + + EXPECT_EQ(StringHelpers::ToHexString(s32), "0xABCDEF00"); + EXPECT_EQ(StringHelpers::ToHexString((uint32_t)s32), "0xABCDEF00"); + + EXPECT_EQ(StringHelpers::ToHexString(s64), "0xABCDEF1234567800"); + EXPECT_EQ(StringHelpers::ToHexString((uint64_t)s64), "0xABCDEF1234567800"); +} + +TEST(StringHelpersTest, FromString) +{ + EXPECT_EQ(StringHelpers::StringToU16("35"), 35); + EXPECT_EQ(StringHelpers::StringToS16("-35"), -35); + + EXPECT_EQ(StringHelpers::StringToU32("35"), 35); + EXPECT_EQ(StringHelpers::StringToS32("-35"), -35); + + EXPECT_EQ(StringHelpers::StringToU64("35"), 35); + EXPECT_EQ(StringHelpers::StringToS64("-35"), -35); + + EXPECT_EQ(StringHelpers::StringToDouble("0.351342"), 0.351342); + + Guid guid = Guid::GenerateNew(); + EXPECT_EQ(StringHelpers::StringToGuid(StringHelpers::ToString(guid)), guid); +} + +TEST(StringHelpersTest, FromHexString) +{ + int16_t s16 = 0x8B00; + uint16_t u16 = 0x8B00; + int32_t s32 = 0x8BCDEF00; + uint32_t u32 = 0x8BCDEF00; + int64_t s64 = 0x8BCDEF1234567800; + uint64_t u64 = 0x8BCDEF1234567800; + + EXPECT_EQ(StringHelpers::HexStringToS16("8B00"), s16); + EXPECT_EQ(StringHelpers::HexStringToS16("0x8B00"), s16); + EXPECT_EQ(StringHelpers::HexStringToU16("8B00"), u16); + EXPECT_EQ(StringHelpers::HexStringToU16("0x8B00"), u16); + + EXPECT_EQ(StringHelpers::HexStringToS32("8BCDEF00"), s32); + EXPECT_EQ(StringHelpers::HexStringToS32("0x8BCDEF00"), s32); + EXPECT_EQ(StringHelpers::HexStringToU32("8BCDEF00"), u32); + EXPECT_EQ(StringHelpers::HexStringToU32("0x8BCDEF00"), u32); + + EXPECT_EQ(StringHelpers::HexStringToS64("8BCDEF1234567800"), s64); + EXPECT_EQ(StringHelpers::HexStringToS64("0x8BCDEF1234567800"), s64); + EXPECT_EQ(StringHelpers::HexStringToU64("8BCDEF1234567800"), u64); + EXPECT_EQ(StringHelpers::HexStringToU64("0x8BCDEF1234567800"), u64); +} \ No newline at end of file diff --git a/test/HephCommon/UserEventArgsTest.cpp b/test/HephCommon/UserEventArgsTest.cpp new file mode 100644 index 00000000..30192bd8 --- /dev/null +++ b/test/HephCommon/UserEventArgsTest.cpp @@ -0,0 +1,44 @@ +#include "gtest/gtest.h" +#include "UserEventArgs.h" + +using namespace Heph; + +TEST(UserEventArgsTest, TestAll) +{ + UserEventArgs args; + + int data1 = 30; + std::string data2 = "Hello World!"; + double data3 = 27.35; + + std::string key1 = "key1"; + std::string key2 = "key2"; + std::string key3 = "key3"; + + args.Add(key1, (void*)&data1); + args.Add(key2, (void*)&data2); + + EXPECT_EQ(args.Size(), 2); + EXPECT_TRUE(args.Exists(key1)); + EXPECT_TRUE(args.Exists(key2)); + EXPECT_FALSE(args.Exists(key3)); + + EXPECT_EQ(args[key1], (void*)&data1); + EXPECT_EQ(args[key2], (void*)&data2); + EXPECT_TRUE(args[key3] == nullptr); + + args.Add(key3, (void*)&data3); + + EXPECT_EQ(args.Size(), 3); + + args.Remove(key2); + + EXPECT_EQ(args.Size(), 2); + EXPECT_TRUE(args.Exists(key1)); + EXPECT_FALSE(args.Exists(key2)); + EXPECT_TRUE(args.Exists(key3)); + + args.Clear(); + + EXPECT_EQ(args.Size(), 0); +} \ No newline at end of file diff --git a/test/packages.config b/test/packages.config new file mode 100644 index 00000000..fb949baf --- /dev/null +++ b/test/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/test/test.vcxproj b/test/test.vcxproj new file mode 100644 index 00000000..0cc69568 --- /dev/null +++ b/test/test.vcxproj @@ -0,0 +1,131 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {d483b09f-9d19-4761-bd95-ce4c7bb1fadb} + Win32Proj + 10.0.22621.0 + Application + v143 + Unicode + + + + + + + + + + + + + + Use + pch.h + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + + + true + Console + + + + + NotUsing + pch.h + Disabled + _CRT_SECURE_NO_WARNINGS;X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ..\HephCommon\HeaderFiles;..\HephAudio\HeaderFiles;..\dependencies\ffmpeg\include;..\dependencies\libmysofa\include;%(AdditionalIncludeDirectories) + stdcpp17 + + + true + Console + ..\dependencies;%(AdditionalLibraryDirectories) + + + + + Use + pch.h + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Console + true + true + + + + + NotUsing + pch.h + _CRT_SECURE_NO_WARNINGS;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + ..\HephCommon\HeaderFiles;..\HephAudio\HeaderFiles;..\dependencies\ffmpeg\include;..\dependencies\libmysofa\include;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + stdcpp17 + + + true + Console + true + true + ..\dependencies;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file