From 4c133daee30e04d7740ca02a307f8e956de6dec6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 27 May 2010 12:58:37 -0700 Subject: work on buffers for recv --- host/test/CMakeLists.txt | 1 + host/test/bounded_buffer_test.cpp | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 host/test/bounded_buffer_test.cpp (limited to 'host/test') diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index 61b0b503d..c7c6d7fad 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -21,6 +21,7 @@ ADD_EXECUTABLE(main_test main_test.cpp addr_test.cpp + bounded_buffer_test.cpp dict_test.cpp error_test.cpp gain_handler_test.cpp diff --git a/host/test/bounded_buffer_test.cpp b/host/test/bounded_buffer_test.cpp new file mode 100644 index 000000000..5d6b6faec --- /dev/null +++ b/host/test/bounded_buffer_test.cpp @@ -0,0 +1,46 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include + +//test #Include +#include + +using namespace uhd::transport; + +static const boost::posix_time::milliseconds timeout(10); + +BOOST_AUTO_TEST_CASE(test_bounded_buffer){ + bounded_buffer::sptr bb(new bounded_buffer(3)); + + //push elements, check for timeout + BOOST_CHECK(bb->push_with_timed_wait(0, timeout)); + BOOST_CHECK(bb->push_with_timed_wait(1, timeout)); + BOOST_CHECK(bb->push_with_timed_wait(2, timeout)); + BOOST_CHECK(not bb->push_with_timed_wait(3, timeout)); + + int val; + //pop elements, check for timeout and check values + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 0); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 1); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 2); + BOOST_CHECK(not bb->pop_with_timed_wait(val, timeout)); +} -- cgit v1.2.3 From 6665d7eb90264f12abdce86302fffe968879d94d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 27 May 2010 18:47:27 -0700 Subject: work on bounded and alignment buffer with unit testing --- host/include/uhd/transport/alignment_buffer.hpp | 97 +++++++++++++------------ host/include/uhd/transport/bounded_buffer.hpp | 53 ++++++++------ host/test/bounded_buffer_test.cpp | 79 +++++++++++++++++++- 3 files changed, 153 insertions(+), 76 deletions(-) (limited to 'host/test') diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp index 7fa4f2694..b33b80da9 100644 --- a/host/include/uhd/transport/alignment_buffer.hpp +++ b/host/include/uhd/transport/alignment_buffer.hpp @@ -41,10 +41,9 @@ namespace uhd{ namespace transport{ * \param width the number of elements to align */ alignment_buffer(size_t capacity, size_t width){ - _buffs.resize(width); for (size_t i = 0; i < width; i++){ - _buffs[i].buff = bounded_buffer_sptr(new bounded_buffer_type(capacity)); - _buffs[i].has_popped_element = false; + _buffs.push_back(bounded_buffer_sptr(new bounded_buffer_type(capacity))); + _all_indexes.push_back(i); } } @@ -56,60 +55,72 @@ namespace uhd{ namespace transport{ } /*! - * Push a single element into the buffer specified by index. - * Notify the condition variable for a thread blocked in pop. + * Push an element with sequence id into the buffer at index. * \param elem the element to push * \param seq the sequence identifier * \param index the buffer index + * \return true if the element fit without popping for space */ - void push_elem_with_wait(const elem_type &elem, const seq_type &seq, size_t index){ - _buffs[index].buff.push_with_wait(buff_contents_type(elem, seq)); - _pushed_cond.notify_one(); + UHD_INLINE bool push_with_pop_on_full( + const elem_type &elem, + const seq_type &seq, + size_t index + ){ + return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq)); } /*! * Pop an aligned set of elements from this alignment buffer. * \param elems a collection to store the aligned elements + * \param time the timeout time + * \return false when the operation times out */ - template - void pop_elems_with_wait(elems_type &elems){ - //TODO................................ + template + bool pop_elems_with_timed_wait(elems_type &elems, const time_type &time){ buff_contents_type buff_contents_tmp; - for (size_t i = 0; i < _buffs.size();){ - if (_buffs[i].has_popped_element){ - i++: - continue; + std::list indexes_to_do(_all_indexes); + + //the seq identifier to align with + seq_type expected_seq_id = seq_type(); + bool expected_seq_id_valid = false; + + //get an aligned set of elements from the buffers: + while(indexes_to_do.size() != 0){ + size_t index = indexes_to_do.back(); + + //pop an element off for this index + if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; + + //grab the current sequence id if not valid + if (not expected_seq_id_valid){ + expected_seq_id_valid = true; + expected_seq_id = buff_contents_tmp.second; } - _buffs[i].pop_with_wait(buff_contents_tmp); - if (buff_contents_tmp.second == _expected_seq_id){ - _buffs[i].has_popped_element = true; - i++; + + //if the sequence id matches: + // store the popped element into the output, + // remove this index from the list and continue + if (buff_contents_tmp.second == expected_seq_id){ + elems[index] = buff_contents_tmp.first; + indexes_to_do.pop_back(); continue; } - //if the sequence number is older, pop until we get the current sequence number - //do this by setting has popped element false and continuing on the same condition - if (buff_contents_tmp.second < _expected_seq_id){ - _buffs[i].has_popped_element = false; + //if the sequence id is older: + // continue with the same index to try again + if (buff_contents_tmp.second < expected_seq_id){ continue; } - //if the sequence number is newer, start from scratch at the new sequence number - //do this by setting all has popped elements false and restarting on index zero - if (buff_contents_tmp.second > _expected_seq_id){ - _expected_seq_id = buff_contents_tmp.second; - for (size_t j = 0; j < i; j++){ - _buffs[j].has_popped_element = false; - } - i = 0; + //if the sequence id is newer: + // start from scratch at the new sequence number + if (buff_contents_tmp.second > expected_seq_id){ + expected_seq_id = buff_contents_tmp.second; + indexes_to_do = _all_indexes; continue; } } - //if aligned - for (size_t i = 0; i < _buffs.size(); i++){ - elems[i] = _buffs[i].popped_element; - _buffs[i].has_popped_element = false; - } + return true; } private: @@ -117,18 +128,8 @@ namespace uhd{ namespace transport{ typedef std::pair buff_contents_type; typedef bounded_buffer bounded_buffer_type; typedef boost::shared_ptr bounded_buffer_sptr; - struct buff_type{ - bounded_buffer_sptr buff; - elem_type popped_element; - bool has_popped_element; - }; - std::vector _buffs; - - //the seq identifier to align with - seq_type _expected_seq_id; - - //a condition to notify when a new element is pushed - boost::condition_variable _pushed_cond; + std::vector _buffs; + std::list _all_indexes; }; }} //namespace diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp index 26fc9c0a0..c50a626fb 100644 --- a/host/include/uhd/transport/bounded_buffer.hpp +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace uhd{ namespace transport{ @@ -41,7 +41,7 @@ namespace uhd{ namespace transport{ * Create a new bounded_buffer of a given size. * \param capacity the bounded_buffer capacity */ - bounded_buffer(size_t capacity) : _buffer(capacity), _size(0){ + bounded_buffer(size_t capacity) : _buffer(capacity){ /* NOP */ } @@ -53,19 +53,23 @@ namespace uhd{ namespace transport{ } /*! - * Is the bounded_buffer buffer not full? - * \return true for not full - */ - bool is_not_full(void) const{ - return _size != _buffer.capacity(); - } - - /*! - * Is the bounded_buffer buffer not empty? - * \return true for not empty + * Push a new element into the bounded buffer. + * If the buffer is full prior to the push, + * make room by poping the oldest element. + * \param elem the new element to push + * \return true if the element fit without popping for space */ - bool is_not_empty(void) const{ - return _size != 0; + UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ + boost::unique_lock lock(_mutex); + if(_buffer.full()){ + _buffer.pop_back(); + _buffer.push_front(elem); + return false; + } + else{ + _buffer.push_front(elem); + return true; + } } /*! @@ -75,8 +79,8 @@ namespace uhd{ namespace transport{ */ UHD_INLINE void push_with_wait(const elem_type &elem){ boost::unique_lock lock(_mutex); - _full_cond.wait(lock, boost::bind(&bounded_buffer::is_not_full, this)); - _buffer.push_front(elem); ++_size; + _full_cond.wait(lock, boost::bind(&bounded_buffer::not_full, this)); + _buffer.push_front(elem); lock.unlock(); _empty_cond.notify_one(); } @@ -91,8 +95,8 @@ namespace uhd{ namespace transport{ template UHD_INLINE bool push_with_timed_wait(const elem_type &elem, const time_type &time){ boost::unique_lock lock(_mutex); - if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer::is_not_full, this))) return false; - _buffer.push_front(elem); ++_size; + if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer::not_full, this))) return false; + _buffer.push_front(elem); lock.unlock(); _empty_cond.notify_one(); return true; @@ -105,8 +109,8 @@ namespace uhd{ namespace transport{ */ UHD_INLINE void pop_with_wait(elem_type &elem){ boost::unique_lock lock(_mutex); - _empty_cond.wait(lock, boost::bind(&bounded_buffer::is_not_empty, this)); - elem = _buffer[--_size]; + _empty_cond.wait(lock, boost::bind(&bounded_buffer::not_empty, this)); + elem = _buffer.back(); _buffer.pop_back(); lock.unlock(); _full_cond.notify_one(); } @@ -121,8 +125,8 @@ namespace uhd{ namespace transport{ template UHD_INLINE bool pop_with_timed_wait(elem_type &elem, const time_type &time){ boost::unique_lock lock(_mutex); - if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer::is_not_empty, this))) return false; - elem = _buffer[--_size]; + if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer::not_empty, this))) return false; + elem = _buffer.back(); _buffer.pop_back(); lock.unlock(); _full_cond.notify_one(); return true; @@ -130,10 +134,11 @@ namespace uhd{ namespace transport{ private: boost::mutex _mutex; - boost::condition_variable _empty_cond, _full_cond; + boost::condition _empty_cond, _full_cond; boost::circular_buffer _buffer; - size_t _size; + bool not_full(void) const{return not _buffer.full();} + bool not_empty(void) const{return not _buffer.empty();} }; }} //namespace diff --git a/host/test/bounded_buffer_test.cpp b/host/test/bounded_buffer_test.cpp index 5d6b6faec..dba1a4258 100644 --- a/host/test/bounded_buffer_test.cpp +++ b/host/test/bounded_buffer_test.cpp @@ -18,14 +18,11 @@ #include #include -//test #Include -#include - using namespace uhd::transport; static const boost::posix_time::milliseconds timeout(10); -BOOST_AUTO_TEST_CASE(test_bounded_buffer){ +BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_timed_wait){ bounded_buffer::sptr bb(new bounded_buffer(3)); //push elements, check for timeout @@ -44,3 +41,77 @@ BOOST_AUTO_TEST_CASE(test_bounded_buffer){ BOOST_CHECK_EQUAL(val, 2); BOOST_CHECK(not bb->pop_with_timed_wait(val, timeout)); } + +BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_pop_on_full){ + bounded_buffer::sptr bb(new bounded_buffer(3)); + + //push elements, check for timeout + BOOST_CHECK(bb->push_with_pop_on_full(0)); + BOOST_CHECK(bb->push_with_pop_on_full(1)); + BOOST_CHECK(bb->push_with_pop_on_full(2)); + BOOST_CHECK(not bb->push_with_pop_on_full(3)); + + int val; + //pop elements, check for timeout and check values + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 1); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 2); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 3); +} + +#include +#include + +using namespace boost::assign; + +BOOST_AUTO_TEST_CASE(test_alignment_buffer_tmp){ + alignment_buffer::sptr ab(new alignment_buffer(5, 3)); + //load index 0 with all good seq numbers + BOOST_CHECK(ab->push_with_pop_on_full(0, 0, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(1, 1, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(2, 2, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(3, 3, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(4, 4, 0)); + + //load index 1 with some skipped seq numbers + BOOST_CHECK(ab->push_with_pop_on_full(10, 0, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(11, 1, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(14, 4, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(15, 5, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(16, 6, 1)); + + //load index 2 with all good seq numbers + BOOST_CHECK(ab->push_with_pop_on_full(20, 0, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(21, 1, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(22, 2, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(23, 3, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(24, 4, 2)); + + //readback aligned values + std::vector aligned_elems(3); + + std::vector expected_elems0 = list_of(0)(10)(20); + BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); + BOOST_CHECK_EQUAL_COLLECTIONS( + aligned_elems.begin(), aligned_elems.end(), + expected_elems0.begin(), expected_elems0.end() + ); + + std::vector expected_elems1 = list_of(1)(11)(21); + BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); + BOOST_CHECK_EQUAL_COLLECTIONS( + aligned_elems.begin(), aligned_elems.end(), + expected_elems1.begin(), expected_elems1.end() + ); + + //there was a skip now find 4 + + std::vector expected_elems4 = list_of(4)(14)(24); + BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); + BOOST_CHECK_EQUAL_COLLECTIONS( + aligned_elems.begin(), aligned_elems.end(), + expected_elems4.begin(), expected_elems4.end() + ); +} -- cgit v1.2.3 From 8c0759df03520f010203fdeb3979f82fc41b72f7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 27 May 2010 21:53:17 -0700 Subject: work on alignment buffer, got unit test working --- host/include/uhd/transport/alignment_buffer.hpp | 49 +++++----- host/include/uhd/transport/bounded_buffer.hpp | 16 ++-- host/test/CMakeLists.txt | 2 +- host/test/bounded_buffer_test.cpp | 117 ------------------------ host/test/buffer_test.cpp | 115 +++++++++++++++++++++++ 5 files changed, 145 insertions(+), 154 deletions(-) delete mode 100644 host/test/bounded_buffer_test.cpp create mode 100644 host/test/buffer_test.cpp (limited to 'host/test') diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp index b33b80da9..dc6ccc3ed 100644 --- a/host/include/uhd/transport/alignment_buffer.hpp +++ b/host/include/uhd/transport/alignment_buffer.hpp @@ -36,22 +36,12 @@ namespace uhd{ namespace transport{ typedef boost::shared_ptr > sptr; /*! - * Create the alignment buffer. + * Make a new alignment buffer object. * \param capacity the maximum elements per index * \param width the number of elements to align */ - alignment_buffer(size_t capacity, size_t width){ - for (size_t i = 0; i < width; i++){ - _buffs.push_back(bounded_buffer_sptr(new bounded_buffer_type(capacity))); - _all_indexes.push_back(i); - } - } - - /*! - * Destroy this alignment buffer. - */ - ~alignment_buffer(void){ - /* NOP */ + static sptr make(size_t capacity, size_t width){ + return sptr(new alignment_buffer(capacity, width)); } /*! @@ -80,29 +70,25 @@ namespace uhd{ namespace transport{ buff_contents_type buff_contents_tmp; std::list indexes_to_do(_all_indexes); - //the seq identifier to align with - seq_type expected_seq_id = seq_type(); - bool expected_seq_id_valid = false; + //do an initial pop to load an initial sequence id + size_t index = indexes_to_do.front(); + if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; + elems[index] = buff_contents_tmp.first; + seq_type expected_seq_id = buff_contents_tmp.second; + indexes_to_do.pop_front(); //get an aligned set of elements from the buffers: while(indexes_to_do.size() != 0){ - size_t index = indexes_to_do.back(); - //pop an element off for this index + index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; - //grab the current sequence id if not valid - if (not expected_seq_id_valid){ - expected_seq_id_valid = true; - expected_seq_id = buff_contents_tmp.second; - } - //if the sequence id matches: // store the popped element into the output, // remove this index from the list and continue if (buff_contents_tmp.second == expected_seq_id){ elems[index] = buff_contents_tmp.first; - indexes_to_do.pop_back(); + indexes_to_do.pop_front(); continue; } @@ -113,10 +99,13 @@ namespace uhd{ namespace transport{ } //if the sequence id is newer: - // start from scratch at the new sequence number + // store the popped element into the output, + // add all other indexes back into the list if (buff_contents_tmp.second > expected_seq_id){ + elems[index] = buff_contents_tmp.first; expected_seq_id = buff_contents_tmp.second; indexes_to_do = _all_indexes; + indexes_to_do.remove(index); continue; } } @@ -130,6 +119,14 @@ namespace uhd{ namespace transport{ typedef boost::shared_ptr bounded_buffer_sptr; std::vector _buffs; std::list _all_indexes; + + //private constructor + alignment_buffer(size_t capacity, size_t width){ + for (size_t i = 0; i < width; i++){ + _buffs.push_back(bounded_buffer_type::make(capacity)); + _all_indexes.push_back(i); + } + } }; }} //namespace diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp index c50a626fb..cdec05849 100644 --- a/host/include/uhd/transport/bounded_buffer.hpp +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -38,18 +38,11 @@ namespace uhd{ namespace transport{ typedef boost::shared_ptr > sptr; /*! - * Create a new bounded_buffer of a given size. + * Make a new bounded buffer object. * \param capacity the bounded_buffer capacity */ - bounded_buffer(size_t capacity) : _buffer(capacity){ - /* NOP */ - } - - /*! - * Destroy this bounded_buffer. - */ - ~bounded_buffer(void){ - /* NOP */ + static sptr make(size_t capacity){ + return sptr(new bounded_buffer(capacity)); } /*! @@ -139,6 +132,9 @@ namespace uhd{ namespace transport{ bool not_full(void) const{return not _buffer.full();} bool not_empty(void) const{return not _buffer.empty();} + + //private constructor + bounded_buffer(size_t capacity) : _buffer(capacity){} }; }} //namespace diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index c7c6d7fad..24778d13e 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -21,7 +21,7 @@ ADD_EXECUTABLE(main_test main_test.cpp addr_test.cpp - bounded_buffer_test.cpp + buffer_test.cpp dict_test.cpp error_test.cpp gain_handler_test.cpp diff --git a/host/test/bounded_buffer_test.cpp b/host/test/bounded_buffer_test.cpp deleted file mode 100644 index dba1a4258..000000000 --- a/host/test/bounded_buffer_test.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include - -using namespace uhd::transport; - -static const boost::posix_time::milliseconds timeout(10); - -BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_timed_wait){ - bounded_buffer::sptr bb(new bounded_buffer(3)); - - //push elements, check for timeout - BOOST_CHECK(bb->push_with_timed_wait(0, timeout)); - BOOST_CHECK(bb->push_with_timed_wait(1, timeout)); - BOOST_CHECK(bb->push_with_timed_wait(2, timeout)); - BOOST_CHECK(not bb->push_with_timed_wait(3, timeout)); - - int val; - //pop elements, check for timeout and check values - BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); - BOOST_CHECK_EQUAL(val, 0); - BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); - BOOST_CHECK_EQUAL(val, 1); - BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); - BOOST_CHECK_EQUAL(val, 2); - BOOST_CHECK(not bb->pop_with_timed_wait(val, timeout)); -} - -BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_pop_on_full){ - bounded_buffer::sptr bb(new bounded_buffer(3)); - - //push elements, check for timeout - BOOST_CHECK(bb->push_with_pop_on_full(0)); - BOOST_CHECK(bb->push_with_pop_on_full(1)); - BOOST_CHECK(bb->push_with_pop_on_full(2)); - BOOST_CHECK(not bb->push_with_pop_on_full(3)); - - int val; - //pop elements, check for timeout and check values - BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); - BOOST_CHECK_EQUAL(val, 1); - BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); - BOOST_CHECK_EQUAL(val, 2); - BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); - BOOST_CHECK_EQUAL(val, 3); -} - -#include -#include - -using namespace boost::assign; - -BOOST_AUTO_TEST_CASE(test_alignment_buffer_tmp){ - alignment_buffer::sptr ab(new alignment_buffer(5, 3)); - //load index 0 with all good seq numbers - BOOST_CHECK(ab->push_with_pop_on_full(0, 0, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(1, 1, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(2, 2, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(3, 3, 0)); - BOOST_CHECK(ab->push_with_pop_on_full(4, 4, 0)); - - //load index 1 with some skipped seq numbers - BOOST_CHECK(ab->push_with_pop_on_full(10, 0, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(11, 1, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(14, 4, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(15, 5, 1)); - BOOST_CHECK(ab->push_with_pop_on_full(16, 6, 1)); - - //load index 2 with all good seq numbers - BOOST_CHECK(ab->push_with_pop_on_full(20, 0, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(21, 1, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(22, 2, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(23, 3, 2)); - BOOST_CHECK(ab->push_with_pop_on_full(24, 4, 2)); - - //readback aligned values - std::vector aligned_elems(3); - - std::vector expected_elems0 = list_of(0)(10)(20); - BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); - BOOST_CHECK_EQUAL_COLLECTIONS( - aligned_elems.begin(), aligned_elems.end(), - expected_elems0.begin(), expected_elems0.end() - ); - - std::vector expected_elems1 = list_of(1)(11)(21); - BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); - BOOST_CHECK_EQUAL_COLLECTIONS( - aligned_elems.begin(), aligned_elems.end(), - expected_elems1.begin(), expected_elems1.end() - ); - - //there was a skip now find 4 - - std::vector expected_elems4 = list_of(4)(14)(24); - BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); - BOOST_CHECK_EQUAL_COLLECTIONS( - aligned_elems.begin(), aligned_elems.end(), - expected_elems4.begin(), expected_elems4.end() - ); -} diff --git a/host/test/buffer_test.cpp b/host/test/buffer_test.cpp new file mode 100644 index 000000000..aadb3f951 --- /dev/null +++ b/host/test/buffer_test.cpp @@ -0,0 +1,115 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include +#include + +using namespace boost::assign; +using namespace uhd::transport; + +static const boost::posix_time::milliseconds timeout(10); + +BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_timed_wait){ + bounded_buffer::sptr bb(bounded_buffer::make(3)); + + //push elements, check for timeout + BOOST_CHECK(bb->push_with_timed_wait(0, timeout)); + BOOST_CHECK(bb->push_with_timed_wait(1, timeout)); + BOOST_CHECK(bb->push_with_timed_wait(2, timeout)); + BOOST_CHECK(not bb->push_with_timed_wait(3, timeout)); + + int val; + //pop elements, check for timeout and check values + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 0); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 1); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 2); + BOOST_CHECK(not bb->pop_with_timed_wait(val, timeout)); +} + +BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_pop_on_full){ + bounded_buffer::sptr bb(bounded_buffer::make(3)); + + //push elements, check for timeout + BOOST_CHECK(bb->push_with_pop_on_full(0)); + BOOST_CHECK(bb->push_with_pop_on_full(1)); + BOOST_CHECK(bb->push_with_pop_on_full(2)); + BOOST_CHECK(not bb->push_with_pop_on_full(3)); + + int val; + //pop elements, check for timeout and check values + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 1); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 2); + BOOST_CHECK(bb->pop_with_timed_wait(val, timeout)); + BOOST_CHECK_EQUAL(val, 3); +} + +BOOST_AUTO_TEST_CASE(test_alignment_buffer){ + alignment_buffer::sptr ab(alignment_buffer::make(7, 3)); + //load index 0 with all good seq numbers + BOOST_CHECK(ab->push_with_pop_on_full(0, 0, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(1, 1, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(2, 2, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(3, 3, 0)); + BOOST_CHECK(ab->push_with_pop_on_full(4, 4, 0)); + + //load index 1 with some skipped seq numbers + BOOST_CHECK(ab->push_with_pop_on_full(10, 0, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(11, 1, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(14, 4, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(15, 5, 1)); + BOOST_CHECK(ab->push_with_pop_on_full(16, 6, 1)); + + //load index 2 with all good seq numbers + BOOST_CHECK(ab->push_with_pop_on_full(20, 0, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(21, 1, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(22, 2, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(23, 3, 2)); + BOOST_CHECK(ab->push_with_pop_on_full(24, 4, 2)); + + //readback aligned values + std::vector aligned_elems(3); + + static const std::vector expected_elems0 = list_of(0)(10)(20); + BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); + BOOST_CHECK_EQUAL_COLLECTIONS( + aligned_elems.begin(), aligned_elems.end(), + expected_elems0.begin(), expected_elems0.end() + ); + + static const std::vector expected_elems1 = list_of(1)(11)(21); + BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); + BOOST_CHECK_EQUAL_COLLECTIONS( + aligned_elems.begin(), aligned_elems.end(), + expected_elems1.begin(), expected_elems1.end() + ); + + //there was a skip now find 4 + + static const std::vector expected_elems4 = list_of(4)(14)(24); + BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout)); + BOOST_CHECK_EQUAL_COLLECTIONS( + aligned_elems.begin(), aligned_elems.end(), + expected_elems4.begin(), expected_elems4.end() + ); +} -- cgit v1.2.3