Index: src/libchcore/Tests/TOverlappedDataBufferQueueTests.cpp
===================================================================
diff -u -N -re4005a958c9412d890eeff1e8087c8298aa7bcf7 -radf2d680643ef85665b042e03fed274ab8f11180
--- src/libchcore/Tests/TOverlappedDataBufferQueueTests.cpp	(.../TOverlappedDataBufferQueueTests.cpp)	(revision e4005a958c9412d890eeff1e8087c8298aa7bcf7)
+++ src/libchcore/Tests/TOverlappedDataBufferQueueTests.cpp	(.../TOverlappedDataBufferQueueTests.cpp)	(revision adf2d680643ef85665b042e03fed274ab8f11180)
@@ -3,6 +3,7 @@
 #include "gmock/gmock.h"
 #include "../TOverlappedDataBufferQueue.h"
 #include "../TOverlappedDataBuffer.h"
+#include "../TCoreException.h"
 
 using namespace chcore;
 
@@ -31,14 +32,15 @@
 	EXPECT_NE(nullptr, queue.GetEventWritePossibleHandle());
 	EXPECT_NE(nullptr, queue.GetEventWriteFinishedHandle());
 
-	DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_TIMEOUT(queue.GetEventReadPossibleHandle());
+	EXPECT_TIMEOUT(queue.GetEventWritePossibleHandle());
+	EXPECT_TIMEOUT(queue.GetEventWriteFinishedHandle());
 
-	dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_FALSE(queue.IsDataSourceFinished());
+	EXPECT_FALSE(queue.IsDataWritingFinished());
 
-	dwResult = WaitForSingleObject(queue.GetEventWriteFinishedHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_EQ(0, queue.GetTotalBufferCount());
+	EXPECT_EQ(0, queue.GetSingleBufferSize());
 }
 
 TEST(TOverlappedDataBufferQueueTests, AllocatingConstructor_SanityTest)
@@ -53,35 +55,136 @@
 	EXPECT_NE(nullptr, queue.GetEventWritePossibleHandle());
 	EXPECT_NE(nullptr, queue.GetEventWriteFinishedHandle());
 
-	DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
+	EXPECT_TIMEOUT(queue.GetEventWritePossibleHandle());
+	EXPECT_TIMEOUT(queue.GetEventWriteFinishedHandle());
 
-	dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_FALSE(queue.IsDataSourceFinished());
+	EXPECT_FALSE(queue.IsDataWritingFinished());
+}
 
-	dwResult = WaitForSingleObject(queue.GetEventWriteFinishedHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+TEST(TOverlappedDataBufferQueueTests, AllocatingConstructor_CheckBufferSizes)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	EXPECT_EQ(3, queue.GetTotalBufferCount());
+	EXPECT_EQ(32768, queue.GetSingleBufferSize());
+
+	EXPECT_EQ(32768, pBuffers[0]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[1]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[2]->GetBufferSize());
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_FailsWithBuffersInUse)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+
+	queue.GetEmptyBuffer();
+
+	EXPECT_THROW(queue.ReinitializeBuffers(3, 65536), TCoreException);
+}
+
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_ZeroLengthBuffers)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+
+	EXPECT_THROW(queue.ReinitializeBuffers(3, 0), TCoreException);
+}
+
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_SameSizeSameCount)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	queue.ReinitializeBuffers(3, 32768);
+
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	EXPECT_EQ(3, queue.GetTotalBufferCount());
+	EXPECT_EQ(32768, queue.GetSingleBufferSize());
+
+	EXPECT_EQ(32768, pBuffers[0]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[1]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[2]->GetBufferSize());
+}
+
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_IncreaseSize)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	queue.ReinitializeBuffers(3, 65536);
+
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	EXPECT_EQ(3, queue.GetTotalBufferCount());
+	EXPECT_EQ(65536, queue.GetSingleBufferSize());
+
+	EXPECT_EQ(65536, pBuffers[0]->GetBufferSize());
+	EXPECT_EQ(65536, pBuffers[1]->GetBufferSize());
+	EXPECT_EQ(65536, pBuffers[2]->GetBufferSize());
+}
+
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_DecreaseSize)
+{
+	TOverlappedDataBufferQueue queue(3, 65536);
+	queue.ReinitializeBuffers(3, 32768);
+
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	EXPECT_EQ(3, queue.GetTotalBufferCount());
+	EXPECT_EQ(32768, queue.GetSingleBufferSize());
+
+	EXPECT_EQ(32768, pBuffers[0]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[1]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[2]->GetBufferSize());
+}
+
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_IncreaseCount)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	queue.ReinitializeBuffers(5, 32768);
+
+	EXPECT_EQ(5, queue.GetTotalBufferCount());
+	EXPECT_EQ(32768, queue.GetSingleBufferSize());
+
+	TOverlappedDataBuffer* pBuffers[5] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	EXPECT_EQ(32768, pBuffers[0]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[1]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[2]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[3]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[4]->GetBufferSize());
+}
+
+TEST(TOverlappedDataBufferQueueTests, ReinitializeBuffer_DecreaseCount)
+{
+	TOverlappedDataBufferQueue queue(5, 32768);
+	queue.ReinitializeBuffers(3, 32768);
+
+	EXPECT_EQ(3, queue.GetTotalBufferCount());
+	EXPECT_EQ(32768, queue.GetSingleBufferSize());
+
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	EXPECT_EQ(32768, pBuffers[0]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[1]->GetBufferSize());
+	EXPECT_EQ(32768, pBuffers[2]->GetBufferSize());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
 TEST(TOverlappedDataBufferQueueTests, GetEmptyBuffer)
 {
 	TOverlappedDataBufferQueue queue(3, 32768);
 
-	DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
 
 	EXPECT_NE(nullptr, queue.GetEmptyBuffer());
-	dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
 
 	EXPECT_NE(nullptr, queue.GetEmptyBuffer());
-	dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
 
 	EXPECT_NE(nullptr, queue.GetEmptyBuffer());
-	dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_TIMEOUT(queue.GetEventReadPossibleHandle());
 
 	EXPECT_EQ(nullptr, queue.GetEmptyBuffer());
 }
@@ -92,40 +195,106 @@
 
 	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
 
-	DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_TIMEOUT(queue.GetEventReadPossibleHandle());
 
 	queue.AddEmptyBuffer(pBuffers[0]);
-	dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
 
 	queue.AddEmptyBuffer(pBuffers[1]);
-	dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
 
 	queue.AddEmptyBuffer(pBuffers[2]);
-	dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
+	EXPECT_SIGNALED(queue.GetEventReadPossibleHandle());
 }
 
+TEST(TOverlappedDataBufferQueueTests, AddEmptyBuffer_Null)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+
+	EXPECT_THROW(queue.AddEmptyBuffer(nullptr), TCoreException);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-TEST(TOverlappedDataBufferQueueTests, GetFullBuffer_AddFullBuffer)
+TEST(TOverlappedDataBufferQueueTests, AddFullBuffer_GetFullBuffer)
 {
 	TOverlappedDataBufferQueue queue(3, 32768);
 	TOverlappedDataBuffer* pBuffer = queue.GetEmptyBuffer();
 
+	queue.AddFullBuffer(pBuffer);
+	EXPECT_SIGNALED(queue.GetEventWritePossibleHandle());
+
+	pBuffer = queue.GetFullBuffer();
+	EXPECT_TIMEOUT(queue.GetEventWritePossibleHandle());
+}
+
+TEST(TOverlappedDataBufferQueueTests, GetFullBuffer_WrongOrder)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	queue.AddFullBuffer(pBuffers[1]);
+	EXPECT_EQ(nullptr, queue.GetFullBuffer());
+
+	queue.AddFullBuffer(pBuffers[2]);
+	EXPECT_EQ(nullptr, queue.GetFullBuffer());
+
+	queue.AddFullBuffer(pBuffers[0]);
+	EXPECT_NE(nullptr, queue.GetFullBuffer());
+}
+
+TEST(TOverlappedDataBufferQueueTests, AddFullBuffer_HandlingSrcEof)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	pBuffers[1]->SetLastPart(true);
+
+	queue.AddFullBuffer(pBuffers[0]);
+	EXPECT_FALSE(queue.IsDataSourceFinished());
+
+	queue.AddFullBuffer(pBuffers[1]);
+	EXPECT_TRUE(queue.IsDataSourceFinished());
+}
+
+TEST(TOverlappedDataBufferQueueTests, AddFullBuffer_HandlingDstEof)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	pBuffers[2]->SetLastPart(true);
+
+	queue.AddFullBuffer(pBuffers[0]);
+	queue.AddFullBuffer(pBuffers[1]);
+	queue.AddFullBuffer(pBuffers[2]);
+
+	TOverlappedDataBuffer* pBuffer = queue.GetFullBuffer();
+	EXPECT_FALSE(queue.IsDataWritingFinished());
+	pBuffer = queue.GetFullBuffer();
+	EXPECT_FALSE(queue.IsDataWritingFinished());
+
+	// getting the last buffer (marked as eof) causes setting the data-writing-finished flag
+	pBuffer = queue.GetFullBuffer();
+	EXPECT_TRUE(queue.IsDataWritingFinished());
+}
+
+TEST(TOverlappedDataBufferQueueTests, AddFullBuffer_Null)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+
+	EXPECT_THROW(queue.AddFullBuffer(nullptr), TCoreException);
+}
+
+TEST(TOverlappedDataBufferQueueTests, AddFullBuffer_SameBufferTwice)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffer = queue.GetEmptyBuffer();
+
 	pBuffer->InitForRead(0, 1280);
 	pBuffer->SetBytesTransferred(1230);
 	pBuffer->SetStatusCode(0);
 
 	queue.AddFullBuffer(pBuffer);
-	DWORD dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0);
-	EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult);
-
-	pBuffer = queue.GetFullBuffer();
-
-	dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0);
-	EXPECT_EQ(WAIT_TIMEOUT, dwResult);
+	EXPECT_THROW(queue.AddFullBuffer(pBuffer), TCoreException);
 }
 
 TEST(TOverlappedDataBufferQueueTests, GetFullBuffer_AddFullBuffer_OutOfOrder)
@@ -159,7 +328,7 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-TEST(TOverlappedDataBufferQueueTests, GetFinishedBuffer_AddFinishedBuffer_OutOfOrder)
+TEST(TOverlappedDataBufferQueueTests, AddFinishedBuffer_OutOfOrder_Signals)
 {
 	TOverlappedDataBufferQueue queue(3, 32768);
 	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
@@ -184,3 +353,104 @@
 	queue.AddFinishedBuffer(pBuffers[0]);
 	EXPECT_SIGNALED(queue.GetEventWriteFinishedHandle());
 }
+
+TEST(TOverlappedDataBufferQueueTests, GetFinishedBuffer_Signals)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	pBuffers[0]->InitForRead(0, 1000);
+	pBuffers[0]->SetBytesTransferred(1000);
+	pBuffers[0]->SetStatusCode(0);
+
+	pBuffers[1]->InitForRead(0, 1200);
+	pBuffers[1]->SetBytesTransferred(1200);
+	pBuffers[1]->SetStatusCode(0);
+
+	pBuffers[2]->InitForRead(0, 1400);
+	pBuffers[2]->SetBytesTransferred(800);
+	pBuffers[2]->SetStatusCode(0);
+	pBuffers[2]->SetLastPart(true);
+
+	queue.AddFinishedBuffer(pBuffers[1]);
+	queue.AddFinishedBuffer(pBuffers[2]);
+	queue.AddFinishedBuffer(pBuffers[0]);
+
+	queue.GetFinishedBuffer();
+	EXPECT_SIGNALED(queue.GetEventWriteFinishedHandle());
+	queue.GetFinishedBuffer();
+	EXPECT_SIGNALED(queue.GetEventWriteFinishedHandle());
+	queue.GetFinishedBuffer();
+	EXPECT_TIMEOUT(queue.GetEventWriteFinishedHandle());
+}
+
+TEST(TOverlappedDataBufferQueueTests, GetFinishedBuffer_WrongOrder)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	pBuffers[0]->InitForRead(0, 1000);
+	pBuffers[0]->SetBytesTransferred(1000);
+	pBuffers[0]->SetStatusCode(0);
+
+	pBuffers[1]->InitForRead(0, 1200);
+	pBuffers[1]->SetBytesTransferred(1200);
+	pBuffers[1]->SetStatusCode(0);
+
+	pBuffers[2]->InitForRead(0, 1400);
+	pBuffers[2]->SetBytesTransferred(800);
+	pBuffers[2]->SetStatusCode(0);
+	pBuffers[2]->SetLastPart(true);
+
+	queue.AddFinishedBuffer(pBuffers[1]);
+	EXPECT_EQ(nullptr, queue.GetFinishedBuffer());
+
+	queue.AddFinishedBuffer(pBuffers[2]);
+	EXPECT_EQ(nullptr, queue.GetFinishedBuffer());
+
+	queue.AddFinishedBuffer(pBuffers[0]);
+	EXPECT_NE(nullptr, queue.GetFinishedBuffer());
+}
+
+TEST(TOverlappedDataBufferQueueTests, AddFinishedBuffer_Null)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+
+	EXPECT_THROW(queue.AddFinishedBuffer(nullptr), TCoreException);
+}
+
+TEST(TOverlappedDataBufferQueueTests, AddFinishedBuffer_SameBufferTwice)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffer = queue.GetEmptyBuffer();
+	queue.AddFinishedBuffer(pBuffer);
+	EXPECT_THROW(queue.AddFinishedBuffer(pBuffer), TCoreException);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+TEST(TOverlappedDataBufferQueueTests, DataSourceChanged_CleanupBuffers)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+	TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() };
+
+	pBuffers[0]->SetLastPart(true);
+	pBuffers[1]->SetLastPart(true);
+	pBuffers[2]->SetLastPart(true);
+
+	queue.AddFullBuffer(pBuffers[1]);
+	queue.AddFullBuffer(pBuffers[2]);
+	queue.AddFullBuffer(pBuffers[0]);
+
+	// this tests if the buffers are properly cleaned up - if they're not, DataSourceChanged() throws an exception
+	EXPECT_NO_THROW(queue.DataSourceChanged());
+}
+
+TEST(TOverlappedDataBufferQueueTests, DataSourceChanged_InvalidBufferCount)
+{
+	TOverlappedDataBufferQueue queue(3, 32768);
+
+	queue.GetEmptyBuffer();
+
+	// this tests if the buffers are properly cleaned up - if they're not, DataSourceChanged() throws an exception
+	EXPECT_THROW(queue.DataSourceChanged(), TCoreException);
+}