#include "gtest/gtest.h" #include "piblockingqueue.h" class MockConditionVar: public PIConditionVariable { public: bool isWaitCalled = false; bool isWaitForCalled = false; bool isTrueCondition = false; int timeout = -1; void wait(PIMutex& lk) override { isWaitCalled = true; } void wait(PIMutex& lk, const std::function& condition) override { isWaitCalled = true; lk.lock(); isTrueCondition = condition(); lk.unlock(); } bool waitFor(PIMutex& lk, int timeoutMs) override { isWaitForCalled = true; timeout = timeoutMs; return false; } bool waitFor(PIMutex& lk, int timeoutMs, const std::function& condition) override { isWaitForCalled = true; lk.lock(); isTrueCondition = condition(); timeout = timeoutMs; lk.unlock(); return isTrueCondition; } }; TEST(BlockingDequeueUnitTest, put_is_block_when_capacity_reach) { size_t capacity = 0; auto conditionVarAdd = new MockConditionVar(); auto conditionVarRem = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVarAdd, conditionVarRem); dequeue.put(11); ASSERT_TRUE(conditionVarRem->isWaitCalled); ASSERT_FALSE(conditionVarRem->isTrueCondition); } TEST(BlockingDequeueUnitTest, offer_timedout_is_false_when_capacity_reach) { size_t capacity = 0; int timeout = 11; auto conditionVarAdd = new MockConditionVar(); auto conditionVarRem = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVarAdd, conditionVarRem); ASSERT_FALSE(dequeue.offer(11, timeout)); } TEST(BlockingDequeueUnitTest, offer_timedout_is_block_when_capacity_reach) { size_t capacity = 0; int timeout = 11; auto conditionVarAdd = new MockConditionVar(); auto conditionVarRem = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVarAdd, conditionVarRem); dequeue.offer(11, timeout); EXPECT_TRUE(conditionVarRem->isWaitForCalled); EXPECT_EQ(timeout, conditionVarRem->timeout); ASSERT_FALSE(conditionVarRem->isTrueCondition); } TEST(BlockingDequeueUnitTest, offer_is_true_before_capacity_reach) { size_t capacity = 1; PIBlockingQueue dequeue(capacity); ASSERT_TRUE(dequeue.offer(10)); } TEST(BlockingDequeueUnitTest, offer_is_false_when_capacity_reach) { size_t capacity = 1; PIBlockingQueue dequeue(capacity); dequeue.offer(11); ASSERT_FALSE(dequeue.offer(10)); } // TODO change take_is_block_when_empty to prevent segfault TEST(DISABLED_BlockingDequeueUnitTest, take_is_block_when_empty) { size_t capacity = 1; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); // May cause segfault because take front of empty queue dequeue.take(); EXPECT_TRUE(conditionVar->isWaitCalled); ASSERT_FALSE(conditionVar->isTrueCondition); } TEST(BlockingDequeueUnitTest, take_is_not_block_when_not_empty) { size_t capacity = 1; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.offer(111); dequeue.take(); EXPECT_TRUE(conditionVar->isWaitCalled); ASSERT_TRUE(conditionVar->isTrueCondition); } TEST(BlockingDequeueUnitTest, take_is_value_eq_to_offer_value) { size_t capacity = 1; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.offer(111); ASSERT_EQ(dequeue.take(), 111); } TEST(BlockingDequeueUnitTest, take_is_last) { size_t capacity = 10; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); EXPECT_TRUE(dequeue.offer(111)); EXPECT_TRUE(dequeue.offer(222)); ASSERT_EQ(dequeue.take(), 111); ASSERT_EQ(dequeue.take(), 222); } TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) { size_t capacity = 1; bool isOk; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.poll(0, 111, &isOk); EXPECT_FALSE(conditionVar->isWaitForCalled); } TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { size_t capacity = 1; bool isOk; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); ASSERT_EQ(dequeue.poll(0, 111, &isOk), 111); } TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { size_t capacity = 1; bool isOk; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.offer(111); ASSERT_EQ(dequeue.poll(0, -1, &isOk), 111); } TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.poll(timeout, 111); EXPECT_TRUE(conditionVar->isWaitForCalled); EXPECT_EQ(timeout, conditionVar->timeout); ASSERT_FALSE(conditionVar->isTrueCondition); } TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); ASSERT_EQ(dequeue.poll(timeout, 111), 111); } TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.offer(111); dequeue.poll(timeout, -1); EXPECT_TRUE(conditionVar->isWaitForCalled); ASSERT_TRUE(conditionVar->isTrueCondition); } TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.offer(111); ASSERT_EQ(dequeue.poll(timeout, -1), 111); } TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) { size_t capacity = 10; auto conditionVar = new MockConditionVar(); PIBlockingQueue dequeue(capacity, conditionVar); dequeue.offer(111); dequeue.offer(222); ASSERT_EQ(dequeue.poll(10, -1), 111); ASSERT_EQ(dequeue.poll(10, -1), 222); } TEST(BlockingDequeueUnitTest, capacity_is_eq_constructor_capacity) { size_t capacity = 10; PIBlockingQueue dequeue(capacity); ASSERT_EQ(dequeue.capacity(), capacity); } TEST(BlockingDequeueUnitTest, remainingCapacity_is_dif_of_capacity_and_size) { size_t capacity = 2; PIBlockingQueue dequeue(capacity); ASSERT_EQ(dequeue.remainingCapacity(), capacity); dequeue.offer(111); ASSERT_EQ(dequeue.remainingCapacity(), capacity - 1); } TEST(BlockingDequeueUnitTest, remainingCapacity_is_zero_when_capacity_reach) { size_t capacity = 1; PIBlockingQueue dequeue(capacity); dequeue.offer(111); dequeue.offer(111); ASSERT_EQ(dequeue.remainingCapacity(), 0); } TEST(BlockingDequeueUnitTest, size_is_eq_to_num_of_elements) { size_t capacity = 1; PIBlockingQueue dequeue(capacity); ASSERT_EQ(dequeue.size(), 0); dequeue.offer(111); ASSERT_EQ(dequeue.size(), 1); } TEST(BlockingDequeueUnitTest, size_is_eq_to_capacity_when_capacity_reach) { size_t capacity = 1; PIBlockingQueue dequeue(capacity); dequeue.offer(111); dequeue.offer(111); ASSERT_EQ(dequeue.size(), capacity); } TEST(BlockingDequeueUnitTest, drainTo_is_elements_moved) { size_t capacity = 10; PIDeque refDeque; for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); PIBlockingQueue blockingDequeue(refDeque); PIDeque deque; blockingDequeue.drainTo(deque); ASSERT_EQ(blockingDequeue.size(), 0); ASSERT_TRUE(deque == refDeque); } TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_size_when_all_moved) { size_t capacity = 10; PIDeque refDeque; for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); PIBlockingQueue blockingDequeue(refDeque); PIDeque deque; ASSERT_EQ(blockingDequeue.drainTo(deque), refDeque.size()); } TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_maxCount) { size_t capacity = 10; PIDeque refDeque; for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); PIBlockingQueue blockingDequeue(refDeque); PIDeque deque; ASSERT_EQ(blockingDequeue.drainTo(deque, refDeque.size() - 1), refDeque.size() - 1); }