/*! * \file equeue.cpp * \brief * Unit tests for equeue * * \copyright Copyright (C) 2020 Christos Choutouridis * *
License
* The MIT License (MIT) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *
* */ #include #include namespace Tequeue { using namespace utl; int global_flag =0; // Callable mocks void vfun(void) { ++global_flag; } struct vfoo { void operator() (void) { ++global_flag; } }; // Test construction TEST(Tequeue, contruct) { using Equeue = equeue; struct T { int a,b; }; int local{}; Equeue e1(Equeue::size_match::GE, 3, [](){ ++global_flag; }); Equeue e2(Equeue::size_match::GE, 3, [&](){ ++local; }); Equeue e3(Equeue::size_match::EQ, 7, vfun); equeue e4(equeue::size_match::EQ, 2, vfoo{}); equeue q1; equeue q2(equeue::size_match::DISABLED, 0, nullptr); EXPECT_EQ (8UL, e1.capacity()); EXPECT_EQ (8UL, e2.capacity()); EXPECT_EQ (8UL, e3.capacity()); EXPECT_EQ (8UL, e4.capacity()); EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (8UL, q2.capacity()); } // simple push-pop functionality TEST(Tequeue, base_class) { using Equeue = equeue; Equeue e1(Equeue::size_match::GE, 3, [](){ ++global_flag; }); // Access of base class functionality EXPECT_EQ (8UL, e1.capacity()); EXPECT_EQ (0UL, e1.size()); EXPECT_EQ (true, e1.empty()); EXPECT_EQ (false, e1.full()); e1.push(42); EXPECT_EQ (42, e1.front()); EXPECT_EQ (42, e1.back()); EXPECT_EQ (42, e1.pop()); e1.push(1); e1.push(2); e1.push(3); int check_it=1; for (auto it = e1.begin() ; it != e1.end() ; ++it) EXPECT_EQ(*it, check_it++); EXPECT_EQ(4, check_it); // run through all } // trigger functionality TEST (Tequeue, set_clear_check_trigger) { using Equeue = equeue; bool flag{}; Equeue e1(Equeue::size_match::GE, 1, [&](){ flag = true; }); flag = false; e1.clear_trigger(); EXPECT_EQ (false, flag); e1.push_back(1); // 1, no-trigger cleared EXPECT_EQ (false, flag); flag = false; e1.clear(); e1.clear_trigger(); EXPECT_EQ (false, flag); // no spurious triggers e1.push_back(1); // 1 e1.push_back(2); // 2 e1.set_trigger(Equeue::size_match::GE, 1, [&](){ flag = true; }); EXPECT_EQ (false, flag); // no spurious triggers e1.check_trigger(); // manual trigger EXPECT_EQ (true, flag); flag = false; e1.check_trigger(); // manual trigger attempt EXPECT_EQ (false, flag); // [SIZE triggers are auto clear] Equeue e2(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; }); flag = false; e2.clear_trigger(); EXPECT_EQ (false, flag); e2.push_back(42); // push 42, no-trigger cleared EXPECT_EQ (false, flag); e2.set_trigger(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; }); EXPECT_EQ (false, flag); // no spurious triggers e2.push_back(42); // push 42, trigger EXPECT_EQ (true, flag); flag = false; e2.push_back(42); // push 42, re-trigger [DATA re-triggers] EXPECT_EQ (true, flag); } // stream push-pop TEST(Tequeue, stream_push_pop) { equeue q1; q1 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8; EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (8UL, q1.size()); EXPECT_EQ (false, q1.empty()); EXPECT_EQ (true, q1.full()); q1 << 9; // try to insert in full queue EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (8UL, q1.size()); EXPECT_EQ (false, q1.empty()); EXPECT_EQ (true, q1.full()); int check_it=1; for (auto it = q1.begin() ; it != q1.end() ; ++it) EXPECT_EQ(*it, check_it++); EXPECT_EQ(9, check_it); // run through all for (int i =1 ; i <= 8 ; ++i) { check_it << q1; EXPECT_EQ(i, check_it); } EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (0UL, q1.size()); EXPECT_EQ (true, q1.empty()); EXPECT_EQ (false, q1.full()); q1 >> check_it; EXPECT_EQ (int{}, check_it); } // atomic // Test construction TEST(Tequeue, contruct_atomic) { using Equeue = equeue; struct T { int a,b; }; int local{}; Equeue e1(Equeue::size_match::GE, 3, [](){ ++global_flag; }); Equeue e2(Equeue::size_match::GE, 3, [&](){ ++local; }); Equeue e3(Equeue::size_match::EQ, 7, vfun); equeue e4(equeue::size_match::EQ, 2, vfoo{}); equeue q1; equeue q2(equeue::size_match::DISABLED, 0, nullptr); EXPECT_EQ (8UL, e1.capacity()); EXPECT_EQ (8UL, e2.capacity()); EXPECT_EQ (8UL, e3.capacity()); EXPECT_EQ (8UL, e4.capacity()); EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (8UL, q2.capacity()); } // simple push-pop functionality TEST(Tequeue, base_class_atomic) { using Equeue = equeue; Equeue e1(Equeue::size_match::GE, 3, [](){ ++global_flag; }); // Access of base class functionality EXPECT_EQ (8UL, e1.capacity()); EXPECT_EQ (0UL, e1.size()); EXPECT_EQ (true, e1.empty()); EXPECT_EQ (false, e1.full()); e1.push(42); EXPECT_EQ (42, e1.front()); EXPECT_EQ (42, e1.back()); EXPECT_EQ (42, e1.pop()); e1.push(1); e1.push(2); e1.push(3); int check_it=1; for (auto it = e1.begin() ; it != e1.end() ; ++it) EXPECT_EQ(*it, check_it++); EXPECT_EQ(4, check_it); // run through all } // trigger functionality TEST (Tequeue, set_clear_check_trigger_atomic) { using Equeue = equeue; bool flag{}; Equeue e1(Equeue::size_match::GE, 1, [&](){ flag = true; }); flag = false; e1.clear_trigger(); EXPECT_EQ (false, flag); e1.push_back(1); // 1, no-trigger cleared EXPECT_EQ (false, flag); flag = false; e1.clear(); e1.clear_trigger(); EXPECT_EQ (false, flag); // no spurious triggers e1.push_back(1); // 1 e1.push_back(2); // 2 e1.set_trigger(Equeue::size_match::GE, 1, [&](){ flag = true; }); EXPECT_EQ (false, flag); // no spurious triggers e1.check_trigger(); // manual trigger EXPECT_EQ (true, flag); flag = false; e1.check_trigger(); // manual trigger attempt EXPECT_EQ (false, flag); // [SIZE triggers are auto clear] Equeue e2(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; }); flag = false; e2.clear_trigger(); EXPECT_EQ (false, flag); e2.push_back(42); // push 42, no-trigger cleared EXPECT_EQ (false, flag); e2.set_trigger(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; }); EXPECT_EQ (false, flag); // no spurious triggers e2.push_back(42); // push 42, trigger EXPECT_EQ (true, flag); flag = false; e2.push_back(42); // push 42, re-trigger [DATA re-triggers] EXPECT_EQ (true, flag); } // stream push-pop TEST(Tequeue, stream_push_pop_atomic) { equeue q1; q1 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8; EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (8UL, q1.size()); EXPECT_EQ (false, q1.empty()); EXPECT_EQ (true, q1.full()); q1 << 9; // try to insert in full queue EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (8UL, q1.size()); EXPECT_EQ (false, q1.empty()); EXPECT_EQ (true, q1.full()); int check_it=1; for (auto it = q1.begin() ; it != q1.end() ; ++it) EXPECT_EQ(*it, check_it++); EXPECT_EQ(9, check_it); // run through all for (int i =1 ; i <= 8 ; ++i) { check_it << q1; EXPECT_EQ(i, check_it); } EXPECT_EQ (8UL, q1.capacity()); EXPECT_EQ (0UL, q1.size()); EXPECT_EQ (true, q1.empty()); EXPECT_EQ (false, q1.full()); q1 >> check_it; EXPECT_EQ (int{}, check_it); } }