]> git.seodisparate.com - UDPConnection/commitdiff
Add unit test and fixes for TSQueue
authorStephen Seo <seo.disparate@gmail.com>
Fri, 7 Jun 2019 02:33:44 +0000 (11:33 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 7 Jun 2019 02:33:44 +0000 (11:33 +0900)
cpp_impl/CMakeLists.txt
cpp_impl/src/TSQueue.cpp
cpp_impl/src/TSQueue.hpp
cpp_impl/src/test/TestTSQueue.cpp [new file with mode: 0644]
cpp_impl/src/test/UDPC_UnitTest.cpp

index 196674a818fe51baf214ec8fcea21303b81a18d4..8923206853060ddaa30398fbdaabc1efd53aecef 100644 (file)
@@ -26,11 +26,17 @@ target_compile_features(UDPConnection PUBLIC cxx_std_11)
 target_link_libraries(UDPConnection PUBLIC pthread)
 
 if(CMAKE_BUILD_TYPE MATCHES "Debug")
-    set(UDPC_UnitTest_SOURCES
-        src/test/UDPC_UnitTest.cpp)
-    add_executable(UnitTest ${UDPC_UnitTest_SOURCES})
-    target_link_libraries(UnitTest PUBLIC UDPConnection)
-    target_include_directories(UnitTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
+    find_package(GTest QUIET)
+    if(GTEST_FOUND)
+        set(UDPC_UnitTest_SOURCES
+            src/test/UDPC_UnitTest.cpp
+            src/test/TestTSQueue.cpp
+        )
+        add_executable(UnitTest ${UDPC_UnitTest_SOURCES})
+        target_link_libraries(UnitTest PUBLIC UDPConnection ${GTEST_BOTH_LIBRARIES})
+        target_include_directories(UnitTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
+    endif()
 
     set(UDPC_NetworkTest_SOURCES
         src/test/UDPC_NetworkTest.cpp)
index b2f7f338fbe28ac47754e7ffbc7420e446750f04..39c342eb61c487fbbb1f5925ca67db2c0f2a4620 100644 (file)
@@ -3,17 +3,19 @@
 #include <cstring>
 
 TSQueue::TSQueue(unsigned int elemSize, unsigned int capacity)
-    : elemSize(elemSize), capacity(capacity), head(0), tail(0), isEmpty(true),
+    : elemSize(elemSize), head(0), tail(0), isEmpty(true),
       spinLock(false) {
     if (elemSize == 0) {
         this->elemSize = 1;
     }
     if (capacity == 0) {
-        this->capacity = UDPC_TSQUEUE_DEFAULT_CAPACITY * this->elemSize;
+        this->capacityBytes = UDPC_TSQUEUE_DEFAULT_CAPACITY * this->elemSize;
+    } else {
+        this->capacityBytes = capacity * this->elemSize;
     }
 
     this->buffer =
-        std::unique_ptr<unsigned char[]>(new unsigned char[this->capacity]);
+        std::unique_ptr<unsigned char[]>(new unsigned char[this->capacityBytes]);
 }
 
 TSQueue::~TSQueue() {}
@@ -27,7 +29,7 @@ bool TSQueue::push(void *data) {
     }
 
     memcpy(buffer.get() + tail, data, elemSize);
-    tail = (tail + elemSize) % capacity;
+    tail = (tail + elemSize) % capacityBytes;
 
     isEmpty = false;
 
@@ -44,11 +46,7 @@ std::unique_ptr<unsigned char[]> TSQueue::top() {
     }
 
     auto data = std::unique_ptr<unsigned char[]>(new unsigned char[elemSize]);
-    if (tail != 0) {
-        memcpy(data.get(), buffer.get() + (tail - elemSize), elemSize);
-    } else {
-        memcpy(data.get(), buffer.get() + (capacity - elemSize), elemSize);
-    }
+    memcpy(data.get(), buffer.get() + head, elemSize);
     spinLock.store(false);
     return data;
 }
@@ -61,7 +59,7 @@ bool TSQueue::pop() {
         return false;
     }
     head += elemSize;
-    if (head >= capacity) {
+    if (head >= capacityBytes) {
         head = 0;
     }
     if (head == tail) {
@@ -89,14 +87,14 @@ void TSQueue::changeCapacity(unsigned int newCapacity) {
     while (spinLock.exchange(true) == true) {
     }
 
-    // repeat of size() to avoid deadlock
+    // repeat of sizeBytes() to avoid deadlock
     unsigned int size;
     if (head == tail) {
-        size = capacity;
+        size = capacityBytes;
     } else if (head < tail) {
         size = tail - head;
     } else {
-        size = capacity - head + tail;
+        size = capacityBytes - head + tail;
     }
 
     unsigned int newCap = newCapacity * elemSize;
@@ -107,15 +105,15 @@ void TSQueue::changeCapacity(unsigned int newCapacity) {
         unsigned int tempHead = head;
         if (size > newCap) {
             unsigned int diff = size - newCap;
-            tempHead = (head + diff) % capacity;
+            tempHead = (head + diff) % capacityBytes;
         }
         if (tempHead < tail) {
             memcpy(newBuffer.get(), buffer.get() + tempHead, tail - tempHead);
         } else {
             memcpy(newBuffer.get(), buffer.get() + tempHead,
-                   capacity - tempHead);
+                   capacityBytes - tempHead);
             if (tail != 0) {
-                memcpy(newBuffer.get() + capacity - tempHead, buffer.get(),
+                memcpy(newBuffer.get() + capacityBytes - tempHead, buffer.get(),
                        tail);
             }
         }
@@ -126,7 +124,7 @@ void TSQueue::changeCapacity(unsigned int newCapacity) {
             tail = tail - head;
             head = 0;
         } else {
-            tail = capacity - head + tail;
+            tail = capacityBytes - head + tail;
             head = 0;
         }
     } else {
@@ -135,7 +133,7 @@ void TSQueue::changeCapacity(unsigned int newCapacity) {
         isEmpty = false;
     }
     buffer = std::move(newBuffer);
-    capacity = newCap;
+    capacityBytes = newCap;
 
     spinLock.store(false);
 }
@@ -151,11 +149,34 @@ unsigned int TSQueue::size() {
 
     unsigned int size;
     if (head == tail) {
-        size = capacity;
+        size = capacityBytes;
+    } else if (head < tail) {
+        size = tail - head;
+    } else {
+        size = capacityBytes - head + tail;
+    }
+    size /= elemSize;
+
+    spinLock.store(false);
+    return size;
+}
+
+unsigned int TSQueue::sizeBytes() {
+    while (spinLock.exchange(true) == true) {
+    }
+
+    if (isEmpty) {
+        spinLock.store(false);
+        return 0;
+    }
+
+    unsigned int size;
+    if (head == tail) {
+        size = capacityBytes;
     } else if (head < tail) {
         size = tail - head;
     } else {
-        size = capacity - head + tail;
+        size = capacityBytes - head + tail;
     }
 
     spinLock.store(false);
index 257f2c317710a290ae5925a4918747428e9a6c0f..1afae60a6f353ce357335c3f3beb93fa1ddc6047 100644 (file)
@@ -29,12 +29,14 @@ class TSQueue {
 
   private:
     unsigned int elemSize;
-    unsigned int capacity;
+    unsigned int capacityBytes;
     unsigned int head;
     unsigned int tail;
     bool isEmpty;
     std::unique_ptr<unsigned char[]> buffer;
     std::atomic_bool spinLock;
+
+    unsigned int sizeBytes();
 };
 
 #endif
diff --git a/cpp_impl/src/test/TestTSQueue.cpp b/cpp_impl/src/test/TestTSQueue.cpp
new file mode 100644 (file)
index 0000000..698a0da
--- /dev/null
@@ -0,0 +1,109 @@
+#include <gtest/gtest.h>
+
+#include "TSQueue.hpp"
+
+TEST(TSQueue, Usage)
+{
+    TSQueue q(sizeof(int), 4);
+    int temp = 100;
+
+    EXPECT_EQ(q.size(), 0);
+    EXPECT_FALSE(q.pop());
+
+    EXPECT_TRUE(q.push(&temp));
+    EXPECT_EQ(q.size(), 1);
+
+    // { 100 }
+
+    temp = 200;
+    EXPECT_TRUE(q.push(&temp));
+    EXPECT_EQ(q.size(), 2);
+    auto top = q.top();
+    EXPECT_EQ(100, *((int*)top.get()));
+
+    // { 100, 200 }
+
+    temp = 300;
+    EXPECT_TRUE(q.push(&temp));
+    EXPECT_EQ(q.size(), 3);
+
+    // { 100, 200, 300 }
+
+    temp = 400;
+    EXPECT_TRUE(q.push(&temp));
+    EXPECT_EQ(q.size(), 4);
+
+    // { 100, 200, 300, 400 }
+
+    temp = 500;
+    EXPECT_FALSE(q.push(&temp));
+    EXPECT_EQ(q.size(), 4);
+
+    top = q.top();
+    EXPECT_EQ(100, *((int*)top.get()));
+
+    EXPECT_TRUE(q.pop());
+    EXPECT_EQ(q.size(), 3);
+
+    // { 200, 300, 400 }
+
+    top = q.top();
+    EXPECT_EQ(200, *((int*)top.get()));
+
+    temp = 1;
+    EXPECT_TRUE(q.push(&temp));
+    EXPECT_EQ(q.size(), 4);
+
+     // { 200, 300, 400, 1 }
+
+    top = q.top();
+    EXPECT_EQ(200, *((int*)top.get()));
+
+    temp = 2;
+    EXPECT_FALSE(q.push(&temp));
+    EXPECT_EQ(q.size(), 4);
+
+    q.changeCapacity(8);
+    EXPECT_EQ(q.size(), 4);
+
+    temp = 10;
+    EXPECT_TRUE(q.push(&temp));
+    EXPECT_EQ(q.size(), 5);
+
+    // { 200, 300, 400, 1, 10 }
+
+    top = q.top();
+    EXPECT_EQ(200, *((int*)top.get()));
+
+    EXPECT_TRUE(q.pop());
+    EXPECT_EQ(q.size(), 4);
+
+    // { 300, 400, 1, 10 }
+
+    top = q.top();
+    EXPECT_EQ(300, *((int*)top.get()));
+
+    EXPECT_TRUE(q.pop());
+    EXPECT_EQ(q.size(), 3);
+
+    // { 400, 1, 10 }
+
+    top = q.top();
+    EXPECT_EQ(400, *((int*)top.get()));
+
+    q.changeCapacity(1);
+
+    // { 10 }
+
+    EXPECT_EQ(q.size(), 1);
+
+    top = q.top();
+    EXPECT_EQ(10, *((int*)top.get()));
+
+    EXPECT_TRUE(q.pop());
+
+    // { }
+
+    EXPECT_FALSE(q.pop());
+    EXPECT_EQ(0, q.size());
+}
index b2f997621bea95c08664e45bcbdc81f3c264a051..5ebbc761adf7a8d271eab939989d5bbcc297f407 100644 (file)
@@ -1,2 +1,6 @@
-int main() {
+#include <gtest/gtest.h>
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }