Index: src/libchcore/TSharedMemory.cpp =================================================================== diff -u -r0d5b67ee96b435d63f7bf075dc8e28603793b187 -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/TSharedMemory.cpp (.../TSharedMemory.cpp) (revision 0d5b67ee96b435d63f7bf075dc8e28603793b187) +++ src/libchcore/TSharedMemory.cpp (.../TSharedMemory.cpp) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -95,6 +95,9 @@ void TSharedMemory::Create(const wchar_t* pszName, const BYTE* pbyData, shm_size_t stSize) { + if (!pbyData) + throw TCoreException(eErr_InvalidArgument, L"pbyData is NULL", LOCATION); + Create(pszName, stSize); TIpcMutexLock lock(m_mutex); @@ -203,6 +206,14 @@ return (BYTE*)m_pMappedMemory + sizeof(shm_size_t); } + const BYTE* TSharedMemory::GetFullData() const + { + if (!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(shm_size_t)) + return nullptr; + + return (BYTE*)m_pMappedMemory; + } + TSharedMemory::shm_size_t TSharedMemory::GetSharedMemorySize() const { if (!m_hFileMapping || !m_pMappedMemory) Index: src/libchcore/TSharedMemory.h =================================================================== diff -u -r0d5b67ee96b435d63f7bf075dc8e28603793b187 -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/TSharedMemory.h (.../TSharedMemory.h) (revision 0d5b67ee96b435d63f7bf075dc8e28603793b187) +++ src/libchcore/TSharedMemory.h (.../TSharedMemory.h) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -54,6 +54,7 @@ // below are the unsafe functions (i.e. not protected with mutex) const BYTE* GetData() const; BYTE* GetData(); + const BYTE* GetFullData() const; shm_size_t GetSharedMemorySize() const; shm_size_t GetDataSize() const; Index: src/libchcore/TWorkerThreadController.cpp =================================================================== diff -u -r9ddf8fdd5f641491dd30c49eb90f8f740314b6af -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/TWorkerThreadController.cpp (.../TWorkerThreadController.cpp) (revision 9ddf8fdd5f641491dd30c49eb90f8f740314b6af) +++ src/libchcore/TWorkerThreadController.cpp (.../TWorkerThreadController.cpp) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -115,13 +115,13 @@ throw TCoreWin32Exception(eErr_WaitingFailed, GetLastError(), L"Waiting failed", LOCATION); } - void TWorkerThreadController::StopThread() + void TWorkerThreadController::StopThread(DWORD dwMiliseconds) { boost::upgrade_lock lock(m_lock); SignalThreadToStop(lock); - WaitForThreadToExit(lock); + WaitForThreadToExit(lock, dwMiliseconds); } void TWorkerThreadController::ChangePriority(int iPriority) Index: src/libchcore/TWorkerThreadController.h =================================================================== diff -u -rb26ced3298e3e7e51d91f3ac70b56746786da83b -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/TWorkerThreadController.h (.../TWorkerThreadController.h) (revision b26ced3298e3e7e51d91f3ac70b56746786da83b) +++ src/libchcore/TWorkerThreadController.h (.../TWorkerThreadController.h) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -47,7 +47,7 @@ void SignalThreadToStop(); void WaitForThreadToExit(DWORD dwMiliseconds = INFINITE); - void StopThread(); + void StopThread(DWORD dwMiliseconds = INFINITE); void ChangePriority(int iPriority); // methods to be used only inside the thread being controlled Index: src/libchcore/Tests/TestsTFileTime.cpp =================================================================== diff -u -rc1f7af79a52133c6d4b14944c3370288be7f5af5 -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/Tests/TestsTFileTime.cpp (.../TestsTFileTime.cpp) (revision c1f7af79a52133c6d4b14944c3370288be7f5af5) +++ src/libchcore/Tests/TestsTFileTime.cpp (.../TestsTFileTime.cpp) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -12,3 +12,65 @@ EXPECT_EQ(0, fTime.GetAsFiletime().dwLowDateTime); EXPECT_EQ(0, fTime.GetAsFiletime().dwHighDateTime); } + +TEST(TestsTFileTime, ConstructionFromFILETIME) +{ + FILETIME filetime = { 0x00000034, 0x00000045 }; + + TFileTime fTime(filetime); + EXPECT_EQ(0x0000004500000034, fTime.ToUInt64()); + EXPECT_EQ(0x00000034, fTime.GetAsFiletime().dwLowDateTime); + EXPECT_EQ(0x00000045, fTime.GetAsFiletime().dwHighDateTime); +} + +TEST(TestsTFileTime, AssignmentOperator) +{ + FILETIME filetime1 = { 0x00000034, 0x00000045 }; + FILETIME filetime2 = { 0x00000074, 0x00000085 }; + + TFileTime fTime(filetime1); + fTime = filetime2; + EXPECT_EQ(0x0000008500000074, fTime.ToUInt64()); + EXPECT_EQ(0x00000074, fTime.GetAsFiletime().dwLowDateTime); + EXPECT_EQ(0x00000085, fTime.GetAsFiletime().dwHighDateTime); +} + +TEST(TestsTFileTime, CompareOperator_Default) +{ + TFileTime fTime1; + TFileTime fTime2; + EXPECT_TRUE(fTime1 == fTime2); + EXPECT_FALSE(fTime1 != fTime2); +} + +TEST(TestsTFileTime, CompareOperator_Same) +{ + FILETIME filetime = { 0x00000074, 0x00000085 }; + + TFileTime fTime1(filetime); + TFileTime fTime2(filetime); + EXPECT_TRUE(fTime1 == fTime2); + EXPECT_FALSE(fTime1 != fTime2); +} + +TEST(TestsTFileTime, CompareOperator_Different) +{ + FILETIME filetime1 = { 0x00000034, 0x00000045 }; + FILETIME filetime2 = { 0x00000074, 0x00000085 }; + + TFileTime fTime1(filetime1); + TFileTime fTime2(filetime2); + EXPECT_FALSE(fTime1 == fTime2); + EXPECT_TRUE(fTime1 != fTime2); +} + +TEST(TestsTFileTime, FromToUint64) +{ + FILETIME filetime = { 0x00000034, 0x00000045 }; + unsigned long long ullFiletime = 0x0000004500000034; + + TFileTime fTime; + fTime.FromUInt64(ullFiletime); + EXPECT_EQ(fTime.GetAsFiletime().dwLowDateTime, filetime.dwLowDateTime); + EXPECT_EQ(fTime.GetAsFiletime().dwLowDateTime, filetime.dwLowDateTime); +} Index: src/libchcore/Tests/TestsTSharedMemory.cpp =================================================================== diff -u --- src/libchcore/Tests/TestsTSharedMemory.cpp (revision 0) +++ src/libchcore/Tests/TestsTSharedMemory.cpp (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -0,0 +1,219 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../../libstring/TString.h" +#include "../TSharedMemory.h" +#include "../TCoreException.h" + +using namespace chcore; +using namespace string; + +TEST(TestsTSharedMemory, DefaultConstruction) +{ + TSharedMemory memory; + EXPECT_EQ(nullptr, memory.GetData()); + EXPECT_EQ(nullptr, memory.GetFullData()); + EXPECT_EQ(0, memory.GetDataSize()); + EXPECT_EQ(0, memory.GetSharedMemorySize()); +} + +TEST(TestsTSharedMemory, Create_ZeroSize) +{ + TSharedMemory memory; + EXPECT_THROW(memory.Create(L"UnitTestsSharedMemoryName", 0), TCoreException); +} + +TEST(TestsTSharedMemory, Create_NonZeroSize) +{ + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", 320); + + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(0, *(unsigned int*)memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(4, *(unsigned int*)memory.GetFullData()); + EXPECT_EQ(4, memory.GetDataSize()); + EXPECT_EQ(324, memory.GetSharedMemorySize()); +} + +TEST(TestsTSharedMemory, Create_FromEmptyString) +{ + TString strData; + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", strData); + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(0, *(unsigned int*)memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(2, *(unsigned int*)memory.GetFullData()); + EXPECT_EQ(2, memory.GetDataSize()); + EXPECT_EQ(6, memory.GetSharedMemorySize()); +} + +TEST(TestsTSharedMemory, Create_FromFullString) +{ + TString strData(L"SomeString"); + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", strData); + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(L'S', *memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(22, *memory.GetFullData()); + EXPECT_EQ(22, memory.GetDataSize()); + EXPECT_EQ(26, memory.GetSharedMemorySize()); +} + +TEST(TestsTSharedMemory, Create_FromBufferZeroSize) +{ + char* pszData = "SomeString"; + TSharedMemory memory; + EXPECT_THROW(memory.Create(L"UnitTestsSharedMemoryName", (BYTE*)pszData, 0), TCoreException); +} + +TEST(TestsTSharedMemory, Create_FromNullBufferWithZeroSize) +{ + TSharedMemory memory; + EXPECT_THROW(memory.Create(L"UnitTestsSharedMemoryName", nullptr, 0), TCoreException); +} + +TEST(TestsTSharedMemory, Create_FromNullBufferWithNonZeroSize) +{ + TSharedMemory memory; + EXPECT_THROW(memory.Create(L"UnitTestsSharedMemoryName", nullptr, 5), TCoreException); +} + +TEST(TestsTSharedMemory, Create_FromEmptyBuffer) +{ + char* pszData = ""; + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", (BYTE*)pszData, 1); + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(0, *(unsigned int*)memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(1, *(unsigned int*)memory.GetFullData()); + EXPECT_EQ(1, memory.GetDataSize()); + EXPECT_EQ(5, memory.GetSharedMemorySize()); +} + +TEST(TestsTSharedMemory, Create_FromFullBuffer) +{ + char* pszData = "SomeString"; + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", (BYTE*)pszData, 4); + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(L'S', *memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(4, *memory.GetFullData()); + EXPECT_EQ(4, memory.GetDataSize()); + EXPECT_EQ(8, memory.GetSharedMemorySize()); +} + +//////////////////////////////////////////////////////////////////////////////// +// Receiving side + +TEST(TestsTSharedMemory, Open) +{ + char* pszData = "SomeString"; + TSharedMemory srcMemory; + srcMemory.Create(L"UnitTestsSharedMemoryName", (BYTE*)pszData, 4); + + TSharedMemory dstMemory; + dstMemory.Open(L"UnitTestsSharedMemoryName"); + + EXPECT_TRUE(dstMemory.GetData() != nullptr); + EXPECT_EQ(L'S', *dstMemory.GetData()); + EXPECT_TRUE(dstMemory.GetFullData() != nullptr); + EXPECT_EQ(4, *dstMemory.GetFullData()); + EXPECT_EQ(4, dstMemory.GetDataSize()); + EXPECT_EQ(8, dstMemory.GetSharedMemorySize()); +} + +TEST(TestsTSharedMemory, OpenNonExistentMemory) +{ + TSharedMemory dstMemory; + EXPECT_THROW(dstMemory.Open(L"UnitTestsSharedMemoryName"), TCoreException); +} + +////////////////////////////////////////////////////////////////////////////////// +// Read/write + +TEST(TestsTSharedMemory, WriteStringReadString) +{ + TString strData(L"SomeString"); + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", 256); + memory.Write(strData); + + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(L'S', *memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(22, *memory.GetFullData()); + EXPECT_EQ(22, memory.GetDataSize()); + EXPECT_EQ(260, memory.GetSharedMemorySize()); + + TString strReadData; + memory.Read(strReadData); + EXPECT_EQ(strData, strReadData); +} + +TEST(TestsTSharedMemory, WriteBufferReadString) +{ + wchar_t* pszData = L"SomeString"; + TSharedMemory memory; + memory.Create(L"UnitTestsSharedMemoryName", 256); + memory.Write((BYTE*)pszData, (unsigned int)((wcslen(pszData) + 1) * sizeof(wchar_t))); + + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(L'S', *memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(22, *memory.GetFullData()); + EXPECT_EQ(22, memory.GetDataSize()); + EXPECT_EQ(260, memory.GetSharedMemorySize()); + + TString strReadData; + memory.Read(strReadData); + EXPECT_STREQ(L"SomeString", strReadData.c_str()); +} + +TEST(TestsTSharedMemory, WriteStringReadString_ReceiverSide) +{ + TString strData(L"SomeString"); + TSharedMemory srcMemory; + srcMemory.Create(L"UnitTestsSharedMemoryName", 256); + srcMemory.Write(strData); + + TSharedMemory memory; + memory.Open(L"UnitTestsSharedMemoryName"); + + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(L'S', *memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(22, *memory.GetFullData()); + EXPECT_EQ(22, memory.GetDataSize()); + EXPECT_EQ(26, memory.GetSharedMemorySize()); + + TString strReadData; + memory.Read(strReadData); + EXPECT_EQ(strData, strReadData); +} + +TEST(TestsTSharedMemory, WriteBufferReadString_ReceiverSide) +{ + wchar_t* pszData = L"SomeString"; + TSharedMemory srcMemory; + srcMemory.Create(L"UnitTestsSharedMemoryName", 256); + srcMemory.Write((BYTE*)pszData, (unsigned int)((wcslen(pszData) + 1) * sizeof(wchar_t))); + + TSharedMemory memory; + memory.Open(L"UnitTestsSharedMemoryName"); + + EXPECT_TRUE(memory.GetData() != nullptr); + EXPECT_EQ(L'S', *memory.GetData()); + EXPECT_TRUE(memory.GetFullData() != nullptr); + EXPECT_EQ(22, *memory.GetFullData()); + EXPECT_EQ(22, memory.GetDataSize()); + EXPECT_EQ(26, memory.GetSharedMemorySize()); + + TString strReadData; + memory.Read(strReadData); + EXPECT_STREQ(L"SomeString", strReadData.c_str()); +} Index: src/libchcore/Tests/TestsTTimestampProviderTickCount.cpp =================================================================== diff -u --- src/libchcore/Tests/TestsTTimestampProviderTickCount.cpp (revision 0) +++ src/libchcore/Tests/TestsTTimestampProviderTickCount.cpp (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -0,0 +1,15 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../TTimestampProviderTickCount.h" + +using namespace chcore; + +TEST(TestsTTimestampProviderTickCount, DefaultConstruction) +{ + TTimestampProviderTickCount provider; + unsigned long long ullTimestamp1 = provider.GetCurrentTimestamp(); + unsigned long long ullTimestamp2 = provider.GetCurrentTimestamp(); + + EXPECT_LE(ullTimestamp1, ullTimestamp2); +} Index: src/libchcore/Tests/TestsTWorkerThreadController.cpp =================================================================== diff -u --- src/libchcore/Tests/TestsTWorkerThreadController.cpp (revision 0) +++ src/libchcore/Tests/TestsTWorkerThreadController.cpp (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -0,0 +1,55 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../TWorkerThreadController.h" + +using namespace chcore; + +struct SampleThreadOwner +{ + SampleThreadOwner() : m_alCounter(0) + { + } + + static DWORD WINAPI ThreadRoutine(LPVOID lpThreadParameter) + { + SampleThreadOwner* pThis = (SampleThreadOwner*)lpThreadParameter; + + ++pThis->m_alCounter; + + while (!pThis->m_controller.KillRequested(10)) + { + ++pThis->m_alCounter; + } + + return 0; + } + + std::atomic m_alCounter; + TWorkerThreadController m_controller; +}; + +TEST(TestsTWorkerThreadController, DefaultConstruction) +{ + TWorkerThreadController controller; + EXPECT_TRUE(controller.GetKillThreadHandle() != INVALID_HANDLE_VALUE); +} + +TEST(TestsTWorkerThreadController, StartStopThread_Manual) +{ + SampleThreadOwner owner; + owner.m_controller.StartThread(&SampleThreadOwner::ThreadRoutine, &owner); + owner.m_controller.SignalThreadToStop(); + owner.m_controller.WaitForThreadToExit(100); + + EXPECT_LE(1, owner.m_alCounter); +} + +TEST(TestsTWorkerThreadController, StartStopThread_Auto) +{ + SampleThreadOwner owner; + owner.m_controller.StartThread(&SampleThreadOwner::ThreadRoutine, &owner); + owner.m_controller.StopThread(100); + + EXPECT_LE(1, owner.m_alCounter); +} Index: src/libchcore/libchcore.vc140.vcxproj =================================================================== diff -u -rf7188919a918dabb245e9150f1fa7c57cdbb58ff -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision f7188919a918dabb245e9150f1fa7c57cdbb58ff) +++ src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -545,6 +545,12 @@ true true + + true + true + true + true + true true @@ -557,6 +563,18 @@ true true + + true + true + true + true + + + true + true + true + true + Index: src/libchcore/libchcore.vc140.vcxproj.filters =================================================================== diff -u -rc1f7af79a52133c6d4b14944c3370288be7f5af5 -r776c47d61a5a67d5e2541d58013e221c685460ec --- src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision c1f7af79a52133c6d4b14944c3370288be7f5af5) +++ src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision 776c47d61a5a67d5e2541d58013e221c685460ec) @@ -179,6 +179,15 @@ Tests + + Tests + + + Tests + + + Tests +