Loading system/osi/Android.mk +3 −2 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ btosiCommonTestSrc := \ ./test/fixed_queue_test.cc \ ./test/future_test.cc \ ./test/hash_map_utils_test.cc \ ./test/leaky_bonded_queue_test.cc \ ./test/list_test.cc \ ./test/properties_test.cc \ ./test/rand_test.cc \ Loading Loading @@ -169,7 +170,7 @@ LOCAL_SRC_FILES := $(btosiCommonTestSrc) LOCAL_MODULE := net_test_osi LOCAL_MODULE_TAGS := tests LOCAL_SHARED_LIBRARIES := libc liblog libprotobuf-cpp-lite libchrome libcutils LOCAL_STATIC_LIBRARIES := libosi libbt-protos LOCAL_STATIC_LIBRARIES := libosi libbt-protos libgmock LOCAL_CFLAGS += $(bluetooth_CFLAGS) LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS) Loading @@ -188,7 +189,7 @@ LOCAL_LDLIBS := -lrt -lpthread LOCAL_MODULE := net_test_osi LOCAL_MODULE_TAGS := tests LOCAL_SHARED_LIBRARIES := liblog libprotobuf-cpp-lite libchrome LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos libgmock LOCAL_CFLAGS += $(bluetooth_CFLAGS) -DOS_GENERIC LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS) Loading system/osi/BUILD.gn +1 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ executable("net_test_osi") { "test/eager_reader_test.cc", "test/future_test.cc", "test/hash_map_utils_test.cc", "test/leaky_bonded_queue_test.cc", "test/list_test.cc", "test/properties_test.cc", "test/rand_test.cc", Loading system/osi/include/leaky_bonded_queue.h 0 → 100644 +158 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright (C) 2016 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #pragma once #include <memory> #include <mutex> #include <queue> namespace system_bt_osi { /* * LeakyBondedQueue<T> * * - LeakyLondedQueue<T> is a fixed size queue that leaks oldest item when * reaching its capacity. This is useful in creating memory bonded data * structure where freshness is more important than full coverage. * - The queue is protected by a simple mutex and is thread-safe, although * improvements could be made to lock enqueue and dequeue separately, it * is not implemented at this moment due to lack of demand * - The queue uses unique_ptr to automatically free its content when it is * destructed. It is the user's responsibility to implement T's destructor * correctly. * */ template <class T> class LeakyBondedQueue { public: LeakyBondedQueue(size_t capacity); /* Default destructor * * Call Clear() and free the queue structure itself */ ~LeakyBondedQueue(); /* * Add item NEW_ITEM to the underlining queue. If the queue is full, pop * the oldest item */ void Enqueue(T* new_item); /* * Add item NEW_ITEM to the underlining queue. If the queue is full, dequeue * the oldest item and returns it to the caller. Return nullptr otherwise. */ T* EnqueueWithPop(T* new_item); /* * Dequeues the oldest item from the queue. Return nullptr if queue is empty */ T* Dequeue(); /* * Returns the length of queue */ size_t Length(); /* * Returns the defined capacity of the queue */ size_t Capacity(); /* * Returns whether the queue is empty */ bool Empty(); /* * Pops all items from the queue */ void Clear(); private: // Put item in unique_ptr so that they get freed automatically when poped or // when queue_ is freed std::queue<std::unique_ptr<T>> queue_; std::mutex lock_; size_t capacity_; }; /* * Definitions must be in the header for template classes */ template <class T> LeakyBondedQueue<T>::LeakyBondedQueue(size_t capacity) { capacity_ = capacity; } template <class T> LeakyBondedQueue<T>::~LeakyBondedQueue() {} template <class T> void LeakyBondedQueue<T>::Enqueue(T* new_item) { std::lock_guard<std::mutex> lock(lock_); if ((queue_.size() + 1) > capacity_) { queue_.pop(); } std::unique_ptr<T> item_ptr(new_item); queue_.push(std::move(item_ptr)); } template <class T> T* LeakyBondedQueue<T>::EnqueueWithPop(T* new_item) { std::lock_guard<std::mutex> lock(lock_); T* old_item = nullptr; if ((queue_.size() + 1) > capacity_) { std::unique_ptr<T> item = std::move(queue_.front()); queue_.pop(); old_item = item.release(); } std::unique_ptr<T> item_ptr(new_item); queue_.push(std::move(item_ptr)); return old_item; } template <class T> T* LeakyBondedQueue<T>::Dequeue() { std::lock_guard<std::mutex> lock(lock_); std::unique_ptr<T> item = std::move(queue_.front()); queue_.pop(); return item.release(); } template <class T> void LeakyBondedQueue<T>::Clear() { std::lock_guard<std::mutex> lock(lock_); while (!queue_.empty()) { // unique_ptr does not need to be freed queue_.pop(); } } template <class T> size_t LeakyBondedQueue<T>::Length() { std::lock_guard<std::mutex> lock(lock_); return queue_.size(); } template <class T> size_t LeakyBondedQueue<T>::Capacity() { return capacity_; } template <class T> bool LeakyBondedQueue<T>::Empty() { std::lock_guard<std::mutex> lock(lock_); return queue_.empty(); } } // namespace system_bt_osi system/osi/test/leaky_bonded_queue_test.cc 0 → 100644 +242 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright (C) 2016 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #include <gmock/gmock.h> #include <gtest/gtest.h> #include <base/logging.h> #include "osi/include/leaky_bonded_queue.h" namespace testing { using system_bt_osi::LeakyBondedQueue; #define ITEM_EQ(a, b) \ do { \ EXPECT_EQ(a, b); \ EXPECT_EQ(a->index, b->index); \ } while (0) class Item { public: Item(int i) { index = i; } virtual ~Item() {} int index; }; class MockItem : public Item { public: MockItem(int i) : Item(i) {} ~MockItem() { Destruct(); } MOCK_METHOD0(Destruct, void()); }; TEST(LeakyBondedQueueTest, TestEnqueueDequeue) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(3); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(3)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(3)); EXPECT_CALL(*item1, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(3)); MockItem* item2_2 = queue->Dequeue(); MockItem* item3_3 = queue->Dequeue(); MockItem* item4_4 = queue->Dequeue(); EXPECT_THAT(item2_2, NotNull()); ITEM_EQ(item2_2, item2); EXPECT_THAT(item3_3, NotNull()); ITEM_EQ(item3_3, item3); EXPECT_THAT(item4_4, NotNull()); ITEM_EQ(item4_4, item4); LOG(INFO) << "All done release items"; EXPECT_CALL(*item2_2, Destruct()).Times(1); delete item2_2; EXPECT_CALL(*item3_3, Destruct()).Times(1); delete item3_3; EXPECT_CALL(*item4_4, Destruct()).Times(1); delete item4_4; delete queue; } TEST(LeakyBondedQueueTest, TestEnqueueDequeue2) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item2, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item3, Destruct()).Times(1); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item4_4_4 = queue->Dequeue(); MockItem* item1_1_1 = queue->Dequeue(); ITEM_EQ(item4_4_4, item4); ITEM_EQ(item1_1_1, item1); EXPECT_CALL(*item1_1_1, Destruct()).Times(1); delete item1_1_1; EXPECT_CALL(*item4_4_4, Destruct()).Times(1); delete item4_4_4; delete queue; } TEST(LeakyBondedQueueTest, TestEnqueuePop) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item2_2 = queue->EnqueueWithPop(item4); EXPECT_THAT(item2_2, NotNull()); ITEM_EQ(item2_2, item2); EXPECT_CALL(*item2, Destruct()).Times(1); delete item2_2; EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item3_3 = queue->EnqueueWithPop(item1); EXPECT_THAT(item3_3, NotNull()); ITEM_EQ(item3_3, item3); EXPECT_CALL(*item3, Destruct()).Times(1); delete item3_3; EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item4_4_4 = queue->Dequeue(); MockItem* item1_1_1 = queue->Dequeue(); ITEM_EQ(item4_4_4, item4); ITEM_EQ(item1_1_1, item1); EXPECT_CALL(*item1_1_1, Destruct()).Times(1); delete item1_1_1; EXPECT_CALL(*item4_4_4, Destruct()).Times(1); delete item4_4_4; delete queue; } TEST(LeakyBondedQueueTest, TestQueueClear) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item2, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item3, Destruct()).Times(1); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item1, Destruct()).Times(1); EXPECT_CALL(*item4, Destruct()).Times(1); queue->Clear(); delete queue; } TEST(LeakyBondedQueueTest, TestQueueFree) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item2, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item3, Destruct()).Times(1); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item1, Destruct()).Times(1); EXPECT_CALL(*item4, Destruct()).Times(1); delete queue; } TEST(LeakyBondedQueueTest, TestPushNull) { MockItem* item1 = nullptr; LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); queue->Enqueue(item1); MockItem* item1_1 = queue->Dequeue(); EXPECT_THAT(item1_1, IsNull()); } TEST(LeakyBondedQueueTest, TestPushNullOverflowQueue) { MockItem* item1 = nullptr; MockItem* item2 = nullptr; LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(1); queue->Enqueue(item1); queue->Enqueue(item2); MockItem* item2_2 = queue->Dequeue(); EXPECT_THAT(item2_2, IsNull()); } TEST(LeakyBondedQueueTest, TestPushNullDeleteQueue) { MockItem* item1 = nullptr; MockItem* item2 = nullptr; LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); queue->Enqueue(item1); queue->Enqueue(item2); delete queue; } } Loading
system/osi/Android.mk +3 −2 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ btosiCommonTestSrc := \ ./test/fixed_queue_test.cc \ ./test/future_test.cc \ ./test/hash_map_utils_test.cc \ ./test/leaky_bonded_queue_test.cc \ ./test/list_test.cc \ ./test/properties_test.cc \ ./test/rand_test.cc \ Loading Loading @@ -169,7 +170,7 @@ LOCAL_SRC_FILES := $(btosiCommonTestSrc) LOCAL_MODULE := net_test_osi LOCAL_MODULE_TAGS := tests LOCAL_SHARED_LIBRARIES := libc liblog libprotobuf-cpp-lite libchrome libcutils LOCAL_STATIC_LIBRARIES := libosi libbt-protos LOCAL_STATIC_LIBRARIES := libosi libbt-protos libgmock LOCAL_CFLAGS += $(bluetooth_CFLAGS) LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS) Loading @@ -188,7 +189,7 @@ LOCAL_LDLIBS := -lrt -lpthread LOCAL_MODULE := net_test_osi LOCAL_MODULE_TAGS := tests LOCAL_SHARED_LIBRARIES := liblog libprotobuf-cpp-lite libchrome LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos libgmock LOCAL_CFLAGS += $(bluetooth_CFLAGS) -DOS_GENERIC LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS) Loading
system/osi/BUILD.gn +1 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ executable("net_test_osi") { "test/eager_reader_test.cc", "test/future_test.cc", "test/hash_map_utils_test.cc", "test/leaky_bonded_queue_test.cc", "test/list_test.cc", "test/properties_test.cc", "test/rand_test.cc", Loading
system/osi/include/leaky_bonded_queue.h 0 → 100644 +158 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright (C) 2016 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #pragma once #include <memory> #include <mutex> #include <queue> namespace system_bt_osi { /* * LeakyBondedQueue<T> * * - LeakyLondedQueue<T> is a fixed size queue that leaks oldest item when * reaching its capacity. This is useful in creating memory bonded data * structure where freshness is more important than full coverage. * - The queue is protected by a simple mutex and is thread-safe, although * improvements could be made to lock enqueue and dequeue separately, it * is not implemented at this moment due to lack of demand * - The queue uses unique_ptr to automatically free its content when it is * destructed. It is the user's responsibility to implement T's destructor * correctly. * */ template <class T> class LeakyBondedQueue { public: LeakyBondedQueue(size_t capacity); /* Default destructor * * Call Clear() and free the queue structure itself */ ~LeakyBondedQueue(); /* * Add item NEW_ITEM to the underlining queue. If the queue is full, pop * the oldest item */ void Enqueue(T* new_item); /* * Add item NEW_ITEM to the underlining queue. If the queue is full, dequeue * the oldest item and returns it to the caller. Return nullptr otherwise. */ T* EnqueueWithPop(T* new_item); /* * Dequeues the oldest item from the queue. Return nullptr if queue is empty */ T* Dequeue(); /* * Returns the length of queue */ size_t Length(); /* * Returns the defined capacity of the queue */ size_t Capacity(); /* * Returns whether the queue is empty */ bool Empty(); /* * Pops all items from the queue */ void Clear(); private: // Put item in unique_ptr so that they get freed automatically when poped or // when queue_ is freed std::queue<std::unique_ptr<T>> queue_; std::mutex lock_; size_t capacity_; }; /* * Definitions must be in the header for template classes */ template <class T> LeakyBondedQueue<T>::LeakyBondedQueue(size_t capacity) { capacity_ = capacity; } template <class T> LeakyBondedQueue<T>::~LeakyBondedQueue() {} template <class T> void LeakyBondedQueue<T>::Enqueue(T* new_item) { std::lock_guard<std::mutex> lock(lock_); if ((queue_.size() + 1) > capacity_) { queue_.pop(); } std::unique_ptr<T> item_ptr(new_item); queue_.push(std::move(item_ptr)); } template <class T> T* LeakyBondedQueue<T>::EnqueueWithPop(T* new_item) { std::lock_guard<std::mutex> lock(lock_); T* old_item = nullptr; if ((queue_.size() + 1) > capacity_) { std::unique_ptr<T> item = std::move(queue_.front()); queue_.pop(); old_item = item.release(); } std::unique_ptr<T> item_ptr(new_item); queue_.push(std::move(item_ptr)); return old_item; } template <class T> T* LeakyBondedQueue<T>::Dequeue() { std::lock_guard<std::mutex> lock(lock_); std::unique_ptr<T> item = std::move(queue_.front()); queue_.pop(); return item.release(); } template <class T> void LeakyBondedQueue<T>::Clear() { std::lock_guard<std::mutex> lock(lock_); while (!queue_.empty()) { // unique_ptr does not need to be freed queue_.pop(); } } template <class T> size_t LeakyBondedQueue<T>::Length() { std::lock_guard<std::mutex> lock(lock_); return queue_.size(); } template <class T> size_t LeakyBondedQueue<T>::Capacity() { return capacity_; } template <class T> bool LeakyBondedQueue<T>::Empty() { std::lock_guard<std::mutex> lock(lock_); return queue_.empty(); } } // namespace system_bt_osi
system/osi/test/leaky_bonded_queue_test.cc 0 → 100644 +242 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright (C) 2016 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #include <gmock/gmock.h> #include <gtest/gtest.h> #include <base/logging.h> #include "osi/include/leaky_bonded_queue.h" namespace testing { using system_bt_osi::LeakyBondedQueue; #define ITEM_EQ(a, b) \ do { \ EXPECT_EQ(a, b); \ EXPECT_EQ(a->index, b->index); \ } while (0) class Item { public: Item(int i) { index = i; } virtual ~Item() {} int index; }; class MockItem : public Item { public: MockItem(int i) : Item(i) {} ~MockItem() { Destruct(); } MOCK_METHOD0(Destruct, void()); }; TEST(LeakyBondedQueueTest, TestEnqueueDequeue) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(3); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(3)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(3)); EXPECT_CALL(*item1, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(3)); MockItem* item2_2 = queue->Dequeue(); MockItem* item3_3 = queue->Dequeue(); MockItem* item4_4 = queue->Dequeue(); EXPECT_THAT(item2_2, NotNull()); ITEM_EQ(item2_2, item2); EXPECT_THAT(item3_3, NotNull()); ITEM_EQ(item3_3, item3); EXPECT_THAT(item4_4, NotNull()); ITEM_EQ(item4_4, item4); LOG(INFO) << "All done release items"; EXPECT_CALL(*item2_2, Destruct()).Times(1); delete item2_2; EXPECT_CALL(*item3_3, Destruct()).Times(1); delete item3_3; EXPECT_CALL(*item4_4, Destruct()).Times(1); delete item4_4; delete queue; } TEST(LeakyBondedQueueTest, TestEnqueueDequeue2) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item2, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item3, Destruct()).Times(1); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item4_4_4 = queue->Dequeue(); MockItem* item1_1_1 = queue->Dequeue(); ITEM_EQ(item4_4_4, item4); ITEM_EQ(item1_1_1, item1); EXPECT_CALL(*item1_1_1, Destruct()).Times(1); delete item1_1_1; EXPECT_CALL(*item4_4_4, Destruct()).Times(1); delete item4_4_4; delete queue; } TEST(LeakyBondedQueueTest, TestEnqueuePop) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item2_2 = queue->EnqueueWithPop(item4); EXPECT_THAT(item2_2, NotNull()); ITEM_EQ(item2_2, item2); EXPECT_CALL(*item2, Destruct()).Times(1); delete item2_2; EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item3_3 = queue->EnqueueWithPop(item1); EXPECT_THAT(item3_3, NotNull()); ITEM_EQ(item3_3, item3); EXPECT_CALL(*item3, Destruct()).Times(1); delete item3_3; EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); MockItem* item4_4_4 = queue->Dequeue(); MockItem* item1_1_1 = queue->Dequeue(); ITEM_EQ(item4_4_4, item4); ITEM_EQ(item1_1_1, item1); EXPECT_CALL(*item1_1_1, Destruct()).Times(1); delete item1_1_1; EXPECT_CALL(*item4_4_4, Destruct()).Times(1); delete item4_4_4; delete queue; } TEST(LeakyBondedQueueTest, TestQueueClear) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item2, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item3, Destruct()).Times(1); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item1, Destruct()).Times(1); EXPECT_CALL(*item4, Destruct()).Times(1); queue->Clear(); delete queue; } TEST(LeakyBondedQueueTest, TestQueueFree) { MockItem* item1 = new MockItem(1); MockItem* item2 = new MockItem(2); MockItem* item3 = new MockItem(3); MockItem* item4 = new MockItem(4); LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); MockItem* item1_1 = queue->Dequeue(); ITEM_EQ(item1, item1_1); EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); queue->Enqueue(item2); EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); queue->Enqueue(item3); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item2, Destruct()).Times(1); queue->Enqueue(item4); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item3, Destruct()).Times(1); queue->Enqueue(item1); EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); EXPECT_CALL(*item1, Destruct()).Times(1); EXPECT_CALL(*item4, Destruct()).Times(1); delete queue; } TEST(LeakyBondedQueueTest, TestPushNull) { MockItem* item1 = nullptr; LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); queue->Enqueue(item1); MockItem* item1_1 = queue->Dequeue(); EXPECT_THAT(item1_1, IsNull()); } TEST(LeakyBondedQueueTest, TestPushNullOverflowQueue) { MockItem* item1 = nullptr; MockItem* item2 = nullptr; LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(1); queue->Enqueue(item1); queue->Enqueue(item2); MockItem* item2_2 = queue->Dequeue(); EXPECT_THAT(item2_2, IsNull()); } TEST(LeakyBondedQueueTest, TestPushNullDeleteQueue) { MockItem* item1 = nullptr; MockItem* item2 = nullptr; LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); queue->Enqueue(item1); queue->Enqueue(item2); delete queue; } }