diff options
Diffstat (limited to 'src/boost/libs/lockfree/test/spsc_queue_test.cpp')
-rw-r--r-- | src/boost/libs/lockfree/test/spsc_queue_test.cpp | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/src/boost/libs/lockfree/test/spsc_queue_test.cpp b/src/boost/libs/lockfree/test/spsc_queue_test.cpp new file mode 100644 index 00000000..99f393f0 --- /dev/null +++ b/src/boost/libs/lockfree/test/spsc_queue_test.cpp @@ -0,0 +1,407 @@ +// Copyright (C) 2011 Tim Blechmann +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/lockfree/spsc_queue.hpp> + +#define BOOST_TEST_MAIN +#ifdef BOOST_LOCKFREE_INCLUDE_TESTS +#include <boost/test/included/unit_test.hpp> +#else +#include <boost/test/unit_test.hpp> +#endif + +#include <iostream> +#include <memory> + +#include "test_helpers.hpp" +#include "test_common.hpp" + +using namespace boost; +using namespace boost::lockfree; +using namespace std; + +BOOST_AUTO_TEST_CASE( simple_spsc_queue_test ) +{ + spsc_queue<int, capacity<64> > f; + + BOOST_REQUIRE(f.empty()); + f.push(1); + f.push(2); + + int i1(0), i2(0); + + BOOST_REQUIRE(f.pop(i1)); + BOOST_REQUIRE_EQUAL(i1, 1); + + BOOST_REQUIRE(f.pop(i2)); + BOOST_REQUIRE_EQUAL(i2, 2); + BOOST_REQUIRE(f.empty()); +} + +BOOST_AUTO_TEST_CASE( simple_spsc_queue_test_compile_time_size ) +{ + spsc_queue<int> f(64); + + BOOST_REQUIRE(f.empty()); + f.push(1); + f.push(2); + + int i1(0), i2(0); + + BOOST_REQUIRE(f.pop(i1)); + BOOST_REQUIRE_EQUAL(i1, 1); + + BOOST_REQUIRE(f.pop(i2)); + BOOST_REQUIRE_EQUAL(i2, 2); + BOOST_REQUIRE(f.empty()); +} + +BOOST_AUTO_TEST_CASE( ranged_push_test ) +{ + spsc_queue<int> stk(64); + + int data[2] = {1, 2}; + + BOOST_REQUIRE_EQUAL(stk.push(data, data + 2), data + 2); + + int out; + BOOST_REQUIRE(stk.pop(out)); BOOST_REQUIRE_EQUAL(out, 1); + BOOST_REQUIRE(stk.pop(out)); BOOST_REQUIRE_EQUAL(out, 2); + BOOST_REQUIRE(!stk.pop(out)); +} + +BOOST_AUTO_TEST_CASE( spsc_queue_consume_one_test ) +{ + spsc_queue<int> f(64); + + BOOST_WARN(f.is_lock_free()); + BOOST_REQUIRE(f.empty()); + + f.push(1); + f.push(2); + +#ifdef BOOST_NO_CXX11_LAMBDAS + bool success1 = f.consume_one(test_equal(1)); + bool success2 = f.consume_one(test_equal(2)); +#else + bool success1 = f.consume_one([] (int i) { + BOOST_REQUIRE_EQUAL(i, 1); + }); + + bool success2 = f.consume_one([] (int i) { + BOOST_REQUIRE_EQUAL(i, 2); + }); +#endif + + BOOST_REQUIRE(success1); + BOOST_REQUIRE(success2); + + BOOST_REQUIRE(f.empty()); +} + +BOOST_AUTO_TEST_CASE( spsc_queue_consume_all_test ) +{ + spsc_queue<int> f(64); + + BOOST_WARN(f.is_lock_free()); + BOOST_REQUIRE(f.empty()); + + f.push(1); + f.push(2); + +#ifdef BOOST_NO_CXX11_LAMBDAS + size_t consumed = f.consume_all(dummy_functor()); +#else + size_t consumed = f.consume_all([] (int i) { + }); +#endif + + BOOST_REQUIRE_EQUAL(consumed, 2u); + + BOOST_REQUIRE(f.empty()); +} + +enum { + pointer_and_size, + reference_to_array, + iterator_pair, + output_iterator_ +}; + +BOOST_AUTO_TEST_CASE( spsc_queue_capacity_test ) +{ + spsc_queue<int, capacity<2> > f; + + BOOST_REQUIRE(f.push(1)); + BOOST_REQUIRE(f.push(2)); + BOOST_REQUIRE(!f.push(3)); + + spsc_queue<int> g(2); + + BOOST_REQUIRE(g.push(1)); + BOOST_REQUIRE(g.push(2)); + BOOST_REQUIRE(!g.push(3)); +} + +template <typename QueueType> +void spsc_queue_avail_test_run(QueueType & q) +{ + BOOST_REQUIRE_EQUAL( q.write_available(), 16 ); + BOOST_REQUIRE_EQUAL( q.read_available(), 0 ); + + for (size_t i = 0; i != 8; ++i) { + BOOST_REQUIRE_EQUAL( q.write_available(), 16 - i ); + BOOST_REQUIRE_EQUAL( q.read_available(), i ); + + q.push( 1 ); + } + + // empty queue + int dummy; + while (q.pop(dummy)) + {} + + for (size_t i = 0; i != 16; ++i) { + BOOST_REQUIRE_EQUAL( q.write_available(), 16 - i ); + BOOST_REQUIRE_EQUAL( q.read_available(), i ); + + q.push( 1 ); + } +} + +BOOST_AUTO_TEST_CASE( spsc_queue_avail_test ) +{ + spsc_queue<int, capacity<16> > f; + spsc_queue_avail_test_run(f); + + spsc_queue<int> g(16); + spsc_queue_avail_test_run(g); +} + + +template <int EnqueueMode> +void spsc_queue_buffer_push_return_value(void) +{ + const size_t xqueue_size = 64; + const size_t buffer_size = 100; + spsc_queue<int, capacity<100> > rb; + + int data[xqueue_size]; + for (size_t i = 0; i != xqueue_size; ++i) + data[i] = (int)i*2; + + switch (EnqueueMode) { + case pointer_and_size: + BOOST_REQUIRE_EQUAL(rb.push(data, xqueue_size), xqueue_size); + break; + + case reference_to_array: + BOOST_REQUIRE_EQUAL(rb.push(data), xqueue_size); + break; + + case iterator_pair: + BOOST_REQUIRE_EQUAL(rb.push(data, data + xqueue_size), data + xqueue_size); + break; + + default: + assert(false); + } + + switch (EnqueueMode) { + case pointer_and_size: + BOOST_REQUIRE_EQUAL(rb.push(data, xqueue_size), buffer_size - xqueue_size); + break; + + case reference_to_array: + BOOST_REQUIRE_EQUAL(rb.push(data), buffer_size - xqueue_size); + break; + + case iterator_pair: + BOOST_REQUIRE_EQUAL(rb.push(data, data + xqueue_size), data + buffer_size - xqueue_size); + break; + + default: + assert(false); + } +} + +BOOST_AUTO_TEST_CASE( spsc_queue_buffer_push_return_value_test ) +{ + spsc_queue_buffer_push_return_value<pointer_and_size>(); + spsc_queue_buffer_push_return_value<reference_to_array>(); + spsc_queue_buffer_push_return_value<iterator_pair>(); +} + +template <int EnqueueMode, + int ElementCount, + int BufferSize, + int NumberOfIterations + > +void spsc_queue_buffer_push(void) +{ + const size_t xqueue_size = ElementCount; + spsc_queue<int, capacity<BufferSize> > rb; + + int data[xqueue_size]; + for (size_t i = 0; i != xqueue_size; ++i) + data[i] = (int)i*2; + + std::vector<int> vdata(data, data + xqueue_size); + + for (int i = 0; i != NumberOfIterations; ++i) { + BOOST_REQUIRE(rb.empty()); + switch (EnqueueMode) { + case pointer_and_size: + BOOST_REQUIRE_EQUAL(rb.push(data, xqueue_size), xqueue_size); + break; + + case reference_to_array: + BOOST_REQUIRE_EQUAL(rb.push(data), xqueue_size); + break; + + case iterator_pair: + BOOST_REQUIRE_EQUAL(rb.push(data, data + xqueue_size), data + xqueue_size); + break; + + default: + assert(false); + } + + int out[xqueue_size]; + BOOST_REQUIRE_EQUAL(rb.pop(out, xqueue_size), xqueue_size); + for (size_t i = 0; i != xqueue_size; ++i) + BOOST_REQUIRE_EQUAL(data[i], out[i]); + } +} + +BOOST_AUTO_TEST_CASE( spsc_queue_buffer_push_test ) +{ + spsc_queue_buffer_push<pointer_and_size, 7, 16, 64>(); + spsc_queue_buffer_push<reference_to_array, 7, 16, 64>(); + spsc_queue_buffer_push<iterator_pair, 7, 16, 64>(); +} + +template <int EnqueueMode, + int ElementCount, + int BufferSize, + int NumberOfIterations + > +void spsc_queue_buffer_pop(void) +{ + const size_t xqueue_size = ElementCount; + spsc_queue<int, capacity<BufferSize> > rb; + + int data[xqueue_size]; + for (size_t i = 0; i != xqueue_size; ++i) + data[i] = (int)i*2; + + std::vector<int> vdata(data, data + xqueue_size); + + for (int i = 0; i != NumberOfIterations; ++i) { + BOOST_REQUIRE(rb.empty()); + BOOST_REQUIRE_EQUAL(rb.push(data), xqueue_size); + + int out[xqueue_size]; + vector<int> vout; + + switch (EnqueueMode) { + case pointer_and_size: + BOOST_REQUIRE_EQUAL(rb.pop(out, xqueue_size), xqueue_size); + break; + + case reference_to_array: + BOOST_REQUIRE_EQUAL(rb.pop(out), xqueue_size); + break; + + case output_iterator_: + BOOST_REQUIRE_EQUAL(rb.pop(std::back_inserter(vout)), xqueue_size); + break; + + default: + assert(false); + } + + if (EnqueueMode == output_iterator_) { + BOOST_REQUIRE_EQUAL(vout.size(), xqueue_size); + for (size_t i = 0; i != xqueue_size; ++i) + BOOST_REQUIRE_EQUAL(data[i], vout[i]); + } else { + for (size_t i = 0; i != xqueue_size; ++i) + BOOST_REQUIRE_EQUAL(data[i], out[i]); + } + } +} + +BOOST_AUTO_TEST_CASE( spsc_queue_buffer_pop_test ) +{ + spsc_queue_buffer_pop<pointer_and_size, 7, 16, 64>(); + spsc_queue_buffer_pop<reference_to_array, 7, 16, 64>(); + spsc_queue_buffer_pop<output_iterator_, 7, 16, 64>(); +} + +// Test front() and pop() +template < typename Queue > +void spsc_queue_front_pop(Queue& queue) +{ + queue.push(1); + queue.push(2); + queue.push(3); + + // front as ref and const ref + int& rfront = queue.front(); + const int& crfront = queue.front(); + + BOOST_REQUIRE_EQUAL(1, rfront); + BOOST_REQUIRE_EQUAL(1, crfront); + + int front = 0; + + // access element pushed first + front = queue.front(); + BOOST_REQUIRE_EQUAL(1, front); + + // front is still the same + front = queue.front(); + BOOST_REQUIRE_EQUAL(1, front); + + queue.pop(); + + front = queue.front(); + BOOST_REQUIRE_EQUAL(2, front); + + queue.pop(); // pop 2 + + bool pop_ret = queue.pop(); // pop 3 + BOOST_REQUIRE(pop_ret); + + pop_ret = queue.pop(); // pop on empty queue + BOOST_REQUIRE( ! pop_ret); +} + +BOOST_AUTO_TEST_CASE( spsc_queue_buffer_front_and_pop_runtime_sized_test ) +{ + spsc_queue<int, capacity<64> > queue; + spsc_queue_front_pop(queue); +} + +BOOST_AUTO_TEST_CASE( spsc_queue_buffer_front_and_pop_compiletime_sized_test ) +{ + spsc_queue<int> queue(64); + spsc_queue_front_pop(queue); +} + +BOOST_AUTO_TEST_CASE( spsc_queue_reset_test ) +{ + spsc_queue<int, capacity<64> > f; + + BOOST_REQUIRE(f.empty()); + f.push(1); + f.push(2); + + f.reset(); + + BOOST_REQUIRE(f.empty()); +} |