aboutsummaryrefslogtreecommitdiff
path: root/EASTL/test/source/TestRingBuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/test/source/TestRingBuffer.cpp')
-rw-r--r--EASTL/test/source/TestRingBuffer.cpp1139
1 files changed, 1139 insertions, 0 deletions
diff --git a/EASTL/test/source/TestRingBuffer.cpp b/EASTL/test/source/TestRingBuffer.cpp
new file mode 100644
index 0000000..d640380
--- /dev/null
+++ b/EASTL/test/source/TestRingBuffer.cpp
@@ -0,0 +1,1139 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "EASTLTest.h"
+#include <EASTL/bonus/ring_buffer.h>
+#include <EASTL/bonus/fixed_ring_buffer.h>
+#include <EASTL/vector.h>
+#include <EASTL/deque.h>
+#include <EASTL/string.h>
+#include <EASTL/list.h>
+#include <EASTL/fixed_vector.h>
+#include <EASTL/fixed_string.h>
+
+
+
+using namespace eastl;
+
+
+// Template instantations.
+// These tell the compiler to compile all the functions for the given class.
+template class eastl::ring_buffer< int, eastl::vector<int> >;
+template class eastl::ring_buffer< Align64, eastl::vector<Align64> >;
+template class eastl::ring_buffer< TestObject, eastl::vector<TestObject> >;
+
+template class eastl::ring_buffer< int, eastl::deque<int> >;
+template class eastl::ring_buffer< Align64, eastl::deque<Align64> >;
+template class eastl::ring_buffer< TestObject, eastl::deque<TestObject> >;
+
+template class eastl::ring_buffer< int, eastl::list<int> >;
+template class eastl::ring_buffer< Align64, eastl::list<Align64> >;
+template class eastl::ring_buffer< TestObject, eastl::list<TestObject> >;
+
+// TODO(rparolin): To consider adding support for eastl::array.
+// template class eastl::ring_buffer< int, eastl::array<int, 64>>;
+
+typedef eastl::fixed_string<char, 256, false> RBFixedString;
+typedef eastl::fixed_vector<RBFixedString, 100, false> RBFixedStringVector;
+typedef RBFixedStringVector::overflow_allocator_type RBFixedStringVectorOverflowAllocator;
+template class eastl::ring_buffer<RBFixedString, RBFixedStringVector, RBFixedStringVectorOverflowAllocator>;
+
+typedef eastl::fixed_vector<int, 100, false> RBFixedIntVector;
+template class eastl::ring_buffer<int, RBFixedIntVector, RBFixedIntVector::overflow_allocator_type>;
+// template class eastl::ring_buffer<int, RBFixedIntVector>; // currently fails to compile
+
+typedef eastl::fixed_vector<int, 100> RBFixedIntVectorWithOverFlow;
+template class eastl::ring_buffer<int, RBFixedIntVectorWithOverFlow, RBFixedIntVectorWithOverFlow::overflow_allocator_type>;
+// template class eastl::ring_buffer<int, RBFixedIntVectorWithOverFlow>; // currently fails to compile
+
+
+
+int TestRingBuffer()
+{
+ int nErrorCount = 0;
+
+ // GCC prior to 4.1 has a fatal code generation bug in string arrays, which we use below.
+ #if !defined(EA_DEBUG) && defined(__GNUC__) && !defined(__EDG__) && (((__GNUC__ * 100) + __GNUC_MINOR__) < 401)
+ return nErrorCount;
+ #endif
+
+ { // regression for bug in the capacity() function for the case of capacity == 0.
+
+ vector<int> emptyIntArray;
+ ring_buffer<int, vector<int> > intRingBuffer(emptyIntArray);
+
+ EATEST_VERIFY(intRingBuffer.validate());
+ EATEST_VERIFY(intRingBuffer.capacity() == 0);
+
+ intRingBuffer.resize(0);
+ EATEST_VERIFY(intRingBuffer.validate());
+ EATEST_VERIFY(intRingBuffer.size() == 0);
+
+ intRingBuffer.resize(1);
+ EATEST_VERIFY(intRingBuffer.validate());
+ EATEST_VERIFY(intRingBuffer.size() == 1);
+ }
+
+ {
+ EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());
+
+ typedef ring_buffer< string, vector<string> > RBVectorString;
+
+ int counter = 0;
+ char counterBuffer[32];
+
+ // explicit ring_buffer(size_type size = 0);
+ const int kOriginalCapacity = 50;
+ RBVectorString rbVectorString(50);
+
+ // bool empty() const;
+ // size_type size() const;
+ // bool validate() const;
+ EATEST_VERIFY(rbVectorString.validate());
+ EATEST_VERIFY(rbVectorString.empty());
+ EATEST_VERIFY(rbVectorString.size() == 0);
+ EATEST_VERIFY(rbVectorString.capacity() == 50);
+
+ // void clear();
+ rbVectorString.clear();
+ EATEST_VERIFY(rbVectorString.validate());
+ EATEST_VERIFY(rbVectorString.empty());
+ EATEST_VERIFY(rbVectorString.size() == 0);
+ EATEST_VERIFY(rbVectorString.capacity() == 50);
+
+ // container_type& get_container();
+ RBVectorString::container_type& c = rbVectorString.get_container();
+ EATEST_VERIFY(c.size() == (kOriginalCapacity + 1)); // We need to add one because the ring_buffer mEnd is necessarily an unused element.
+
+ // iterator begin();
+ // iterator end();
+ // int validate_iterator(const_iterator i) const;
+ RBVectorString::iterator it = rbVectorString.begin();
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));
+
+ while(it != rbVectorString.end()) // This loop should do nothing.
+ {
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));
+ ++it;
+ }
+
+ // void push_back(const value_type& value);
+ sprintf(counterBuffer, "%d", counter++);
+ rbVectorString.push_back(string(counterBuffer));
+ EATEST_VERIFY(rbVectorString.validate());
+ EATEST_VERIFY(!rbVectorString.empty());
+ EATEST_VERIFY(rbVectorString.size() == 1);
+ EATEST_VERIFY(rbVectorString.capacity() == 50);
+
+ it = rbVectorString.begin();
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ EATEST_VERIFY(*it == "0");
+
+ // reference front();
+ // reference back();
+ string& sFront = rbVectorString.front();
+ string& sBack = rbVectorString.back();
+ EATEST_VERIFY(&sFront == &sBack);
+
+ // void push_back();
+ string& ref = rbVectorString.push_back();
+ EATEST_VERIFY(rbVectorString.validate());
+ EATEST_VERIFY(rbVectorString.size() == 2);
+ EATEST_VERIFY(rbVectorString.capacity() == 50);
+ EATEST_VERIFY(&ref == &rbVectorString.back());
+
+ it = rbVectorString.begin();
+ ++it;
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ EATEST_VERIFY(it->empty());
+
+ sprintf(counterBuffer, "%d", counter++);
+ *it = counterBuffer;
+ EATEST_VERIFY(*it == "1");
+
+ ++it;
+ EATEST_VERIFY(it == rbVectorString.end());
+
+ it = rbVectorString.begin();
+ while(it != rbVectorString.end())
+ {
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ ++it;
+ }
+
+ // reference operator[](size_type n);
+ string& s0 = rbVectorString[0];
+ EATEST_VERIFY(s0 == "0");
+
+ string& s1 = rbVectorString[1];
+ EATEST_VERIFY(s1 == "1");
+
+ // Now we start hammering the ring buffer with push_back.
+ for(eastl_size_t i = 0, iEnd = rbVectorString.capacity() * 5; i != iEnd; i++)
+ {
+ sprintf(counterBuffer, "%d", counter++);
+ rbVectorString.push_back(string(counterBuffer));
+ EATEST_VERIFY(rbVectorString.validate());
+ }
+
+ int counterCheck = counter - 1;
+ char counterCheckBuffer[32];
+ sprintf(counterCheckBuffer, "%d", counterCheck);
+ EATEST_VERIFY(rbVectorString.back() == counterCheckBuffer);
+
+ // reverse_iterator rbegin();
+ // reverse_iterator rend();
+ for(RBVectorString::reverse_iterator ri = rbVectorString.rbegin(); ri != rbVectorString.rend(); ++ri)
+ {
+ sprintf(counterCheckBuffer, "%d", counterCheck--);
+ EATEST_VERIFY(*ri == counterCheckBuffer);
+ }
+
+ ++counterCheck;
+
+ // iterator begin();
+ // iterator end();
+ for(RBVectorString::iterator i = rbVectorString.begin(); i != rbVectorString.end(); ++i)
+ {
+ EATEST_VERIFY(rbVectorString.validate_iterator(i) == (isf_valid | isf_current | isf_can_dereference));
+ EATEST_VERIFY(*i == counterCheckBuffer);
+ sprintf(counterCheckBuffer, "%d", ++counterCheck);
+ }
+
+ // void clear();
+ rbVectorString.clear();
+ EATEST_VERIFY(rbVectorString.validate());
+ EATEST_VERIFY(rbVectorString.empty());
+ EATEST_VERIFY(rbVectorString.size() == 0);
+ EATEST_VERIFY(rbVectorString.capacity() == 50);
+
+ // Random operations
+ // Not easy to test the expected values without some tedium.
+ for(int j = 0; j < 10000 + (gEASTL_TestLevel * 10000); j++)
+ {
+ sprintf(counterBuffer, "%d", counter++);
+
+ const eastl_size_t op = rng.RandLimit(12);
+ const eastl_size_t s = rbVectorString.size();
+
+ if(op == 0)
+ {
+ // void push_back(const value_type& value);
+
+ rbVectorString.push_back(string(counterBuffer));
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));
+ }
+ else if(op == 1)
+ {
+ // void push_back();
+
+ string& ref2 = rbVectorString.push_back();
+ rbVectorString.back() = string(counterBuffer);
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));
+ EATEST_VERIFY(&ref2 == &rbVectorString.back());
+ }
+ else if(op == 2)
+ {
+ // void pop_back();
+
+ if(!rbVectorString.empty())
+ {
+ rbVectorString.pop_back();
+ EATEST_VERIFY(rbVectorString.size() == (s - 1));
+ }
+ }
+ else if(op == 3)
+ {
+ // void push_front(const value_type& value);
+
+ rbVectorString.push_front(string(counterBuffer));
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));
+ }
+ else if(op == 4)
+ {
+ // void push_front();
+
+ string& ref2 = rbVectorString.push_front();
+ rbVectorString.front() = string(counterBuffer);
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));
+ EATEST_VERIFY(&ref2 == &rbVectorString.front());
+ }
+ else if(op == 5)
+ {
+ // void pop_front();
+
+ if(!rbVectorString.empty())
+ {
+ rbVectorString.pop_front();
+ EATEST_VERIFY(rbVectorString.size() == (s - 1));
+ }
+ }
+ else if(op == 6)
+ {
+ // iterator insert(iterator position, const value_type& value);
+
+ it = rbVectorString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);
+ eastl::advance(it, dist);
+
+ if(it == rbVectorString.end())
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+
+ rbVectorString.insert(it, string(counterBuffer));
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));
+ }
+ else if(op == 7)
+ {
+ // void insert(iterator position, size_type n, const value_type& value);
+
+ it = rbVectorString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);
+ eastl::advance(it, dist);
+
+ if(it == rbVectorString.end())
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+
+ const eastl_size_t count = (eastl_size_t)rng.RandLimit(10);
+
+ rbVectorString.insert(it, count, string(counterBuffer));
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + count, rbVectorString.capacity()));
+ }
+ else if(op == 8)
+ {
+ // template <typename InputIterator>
+ // void insert(iterator position, InputIterator first, InputIterator last);
+
+ string stringArray[10];
+
+ it = rbVectorString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);
+ eastl::advance(it, dist);
+
+ if(it == rbVectorString.end())
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+
+ const eastl_size_t count = (eastl_size_t)rng.RandLimit(10);
+
+ rbVectorString.insert(it, stringArray, stringArray + count);
+ EATEST_VERIFY(rbVectorString.size() == eastl::min(s + count, rbVectorString.capacity()));
+ }
+ else if(op == 9)
+ {
+ // iterator erase(iterator position);
+
+ if(!rbVectorString.empty())
+ {
+ it = rbVectorString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s);
+ eastl::advance(it, dist);
+ EATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ rbVectorString.erase(it);
+
+ EATEST_VERIFY(rbVectorString.size() == (s - 1));
+ }
+ }
+ else if(op == 10)
+ {
+ // iterator erase(iterator first, iterator last);
+
+ if(!rbVectorString.empty())
+ {
+ RBVectorString::iterator it1 = rbVectorString.begin();
+ const eastl_size_t pos = rng.RandLimit((uint32_t)s / 4);
+ eastl::advance(it1, pos);
+ EATEST_VERIFY(rbVectorString.validate_iterator(it1) == (isf_valid | isf_current | isf_can_dereference));
+
+ RBVectorString::iterator it2 = it1;
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s / 4);
+ eastl::advance(it2, dist);
+ EATEST_VERIFY(rbVectorString.validate_iterator(it2) == (isf_valid | isf_current | isf_can_dereference));
+
+ EATEST_VERIFY(s > (pos + dist));
+ rbVectorString.erase(it1, it2);
+ EATEST_VERIFY(rbVectorString.size() == (s - dist));
+ }
+ }
+ else if(op == 11)
+ {
+ // void resize(size_type n);
+ const eastl_size_t nSubOp = rng.RandLimit(100);
+
+ if(nSubOp == 1)
+ {
+ rbVectorString.resize(kOriginalCapacity);
+ EATEST_VERIFY(rbVectorString.size() == (RBVectorString::size_type)kOriginalCapacity);
+ }
+ else if(nSubOp == 2)
+ {
+ const eastl_size_t newSize = rng.RandLimit((uint32_t)s * 2) + 2;
+
+ rbVectorString.resize(newSize);
+ EATEST_VERIFY(rbVectorString.size() == newSize);
+ }
+ else if(nSubOp == 3)
+ {
+ rbVectorString.clear();
+ EATEST_VERIFY(rbVectorString.size() == 0);
+ }
+ }
+
+ EATEST_VERIFY(rbVectorString.validate());
+ }
+
+ // We make sure that after the above we still have some contents.
+ if(rbVectorString.size() < 8)
+ rbVectorString.resize(8);
+
+ EATEST_VERIFY(rbVectorString.validate());
+
+ // Test const functions
+ // const_iterator begin() const;
+ // const_iterator end() const;
+ // const_reverse_iterator rbegin() const;
+ // const_reverse_iterator rend() const;
+ // const_reference front() const;
+ // const_reference back() const;
+ // const_reference operator[](size_type n) const;
+ // const container_type& get_container() const;
+ const RBVectorString& rbVSConst = rbVectorString;
+
+ for(RBVectorString::const_iterator ic = rbVSConst.begin(); ic != rbVSConst.end(); ++ic)
+ {
+ EATEST_VERIFY(rbVectorString.validate_iterator(ic) == (isf_valid | isf_current | isf_can_dereference));
+ }
+
+ for(RBVectorString::const_reverse_iterator ric = rbVSConst.rbegin(); ric != rbVSConst.rend(); ++ric)
+ {
+ if(ric == rbVSConst.rbegin())
+ EATEST_VERIFY(rbVectorString.validate_iterator(ric.base()) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbVectorString.validate_iterator(ric.base()) == (isf_valid | isf_current | isf_can_dereference));
+ }
+
+ EATEST_VERIFY(rbVSConst.front() == rbVectorString.front());
+ EATEST_VERIFY(rbVSConst.back() == rbVectorString.back());
+ EATEST_VERIFY(rbVSConst[0] == rbVectorString[0]);
+ EATEST_VERIFY(&rbVSConst.get_container() == &rbVectorString.get_container());
+
+
+ // Test additional constructors.
+ // ring_buffer(const this_type& x);
+ // explicit ring_buffer(const Container& x);
+ // this_type& operator=(const this_type& x);
+ // void swap(this_type& x);
+ RBVectorString rbVectorString2(rbVectorString);
+ RBVectorString rbVectorString3(rbVectorString.get_container());
+ RBVectorString rbVectorString4(rbVectorString.capacity() / 2);
+ RBVectorString rbVectorString5(rbVectorString.capacity() * 2);
+
+ EATEST_VERIFY(rbVectorString.validate());
+ EATEST_VERIFY(rbVectorString2.validate());
+ EATEST_VERIFY(rbVectorString3.validate());
+ EATEST_VERIFY(rbVectorString4.validate());
+ EATEST_VERIFY(rbVectorString5.validate());
+
+ EATEST_VERIFY(rbVectorString == rbVectorString2);
+ EATEST_VERIFY(rbVectorString3.get_container() == rbVectorString2.get_container());
+
+ rbVectorString3 = rbVectorString4;
+ EATEST_VERIFY(rbVectorString3.validate());
+
+ eastl::swap(rbVectorString2, rbVectorString4);
+ EATEST_VERIFY(rbVectorString2.validate());
+ EATEST_VERIFY(rbVectorString3.validate());
+ EATEST_VERIFY(rbVectorString4.validate());
+ EATEST_VERIFY(rbVectorString == rbVectorString4);
+ EATEST_VERIFY(rbVectorString2 == rbVectorString3);
+
+ // void ring_buffer<T, Container>::reserve(size_type n)
+ eastl_size_t cap = rbVectorString2.capacity();
+ rbVectorString2.reserve(cap += 2);
+ EATEST_VERIFY(rbVectorString2.validate());
+ EATEST_VERIFY(rbVectorString2.capacity() == cap);
+ rbVectorString2.reserve(cap -= 4); // This should act as a no-op if we are following convention.
+ EATEST_VERIFY(rbVectorString2.validate());
+
+ // void ring_buffer<T, Container>::set_capacity(size_type n)
+ cap = rbVectorString2.capacity();
+ rbVectorString2.resize(cap);
+ EATEST_VERIFY(rbVectorString2.size() == cap);
+ rbVectorString2.set_capacity(cap += 2);
+ EATEST_VERIFY(rbVectorString2.validate());
+ EATEST_VERIFY(rbVectorString2.capacity() == cap);
+ rbVectorString2.set_capacity(cap -= 4);
+ EATEST_VERIFY(rbVectorString2.capacity() == cap);
+ EATEST_VERIFY(rbVectorString2.validate());
+
+ // template <typename InputIterator>
+ // void assign(InputIterator first, InputIterator last);
+ string stringArray[10];
+ for(int q = 0; q < 10; q++)
+ stringArray[q] = (char)('0' + (char)q);
+
+ rbVectorString5.assign(stringArray, stringArray + 10);
+ EATEST_VERIFY(rbVectorString5.validate());
+ EATEST_VERIFY(rbVectorString5.size() == 10);
+ EATEST_VERIFY(rbVectorString5.front() == "0");
+ EATEST_VERIFY(rbVectorString5.back() == "9");
+ }
+
+
+ {
+ // Additional testing
+ typedef ring_buffer< int, vector<int> > RBVectorInt;
+
+ RBVectorInt rbVectorInt(6);
+
+ rbVectorInt.push_back(0);
+ rbVectorInt.push_back(1);
+ rbVectorInt.push_back(2);
+ rbVectorInt.push_back(3);
+ rbVectorInt.push_back(4);
+ rbVectorInt.push_back(5);
+ EATEST_VERIFY(rbVectorInt[0] == 0);
+ EATEST_VERIFY(rbVectorInt[5] == 5);
+
+ // iterator insert(iterator position, const value_type& value);
+ rbVectorInt.insert(rbVectorInt.begin(), 999);
+ EATEST_VERIFY(rbVectorInt[0] == 999);
+ EATEST_VERIFY(rbVectorInt[1] == 0);
+ EATEST_VERIFY(rbVectorInt[5] == 4);
+
+ rbVectorInt.clear();
+ rbVectorInt.push_back(0);
+ rbVectorInt.push_back(1);
+ rbVectorInt.push_back(2);
+ rbVectorInt.push_back(3);
+ rbVectorInt.push_back(4);
+
+ // iterator insert(iterator position, const value_type& value);
+ rbVectorInt.insert(rbVectorInt.begin(), 999);
+ EATEST_VERIFY(rbVectorInt[0] == 999);
+ EATEST_VERIFY(rbVectorInt[1] == 0);
+ EATEST_VERIFY(rbVectorInt[5] == 4);
+
+ rbVectorInt.clear();
+ rbVectorInt.push_back(0);
+ rbVectorInt.push_back(1);
+ rbVectorInt.push_back(2);
+ rbVectorInt.push_back(3);
+ rbVectorInt.push_back(4);
+ rbVectorInt.push_back(5);
+ rbVectorInt.push_back(6);
+ EATEST_VERIFY(rbVectorInt[0] == 1);
+ EATEST_VERIFY(rbVectorInt[5] == 6);
+
+ // iterator insert(iterator position, const value_type& value);
+ rbVectorInt.insert(rbVectorInt.begin(), 999);
+ EATEST_VERIFY(rbVectorInt[0] == 999);
+ EATEST_VERIFY(rbVectorInt[1] == 1);
+ EATEST_VERIFY(rbVectorInt[5] == 5);
+
+ // iterator insert(iterator position, const value_type& value);
+ RBVectorInt::iterator it = rbVectorInt.begin();
+ eastl::advance(it, 3);
+ rbVectorInt.insert(it, 888);
+ EATEST_VERIFY(rbVectorInt[0] == 999);
+ EATEST_VERIFY(rbVectorInt[1] == 1);
+ EATEST_VERIFY(rbVectorInt[2] == 2);
+ EATEST_VERIFY(rbVectorInt[3] == 888);
+ EATEST_VERIFY(rbVectorInt[4] == 3);
+ EATEST_VERIFY(rbVectorInt[5] == 4);
+ }
+
+
+ {
+ EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());
+
+ typedef ring_buffer< string, list<string> > RBListString;
+
+ int counter = 0;
+ char counterBuffer[32];
+
+ // explicit ring_buffer(size_type size = 0);
+ const int kOriginalCapacity = 50;
+ RBListString rbListString(50);
+
+ // bool empty() const;
+ // size_type size() const;
+ // bool validate() const;
+ EATEST_VERIFY(rbListString.validate());
+ EATEST_VERIFY(rbListString.empty());
+ EATEST_VERIFY(rbListString.size() == 0);
+ EATEST_VERIFY(rbListString.capacity() == 50);
+
+ // void clear();
+ rbListString.clear();
+ EATEST_VERIFY(rbListString.validate());
+ EATEST_VERIFY(rbListString.empty());
+ EATEST_VERIFY(rbListString.size() == 0);
+ EATEST_VERIFY(rbListString.capacity() == 50);
+
+ // container_type& get_container();
+ RBListString::container_type& c = rbListString.get_container();
+ EATEST_VERIFY(c.size() == (kOriginalCapacity + 1)); // We need to add one because the ring_buffer mEnd is necessarily an unused element.
+
+ // iterator begin();
+ // iterator end();
+ // int validate_iterator(const_iterator i) const;
+ RBListString::iterator it = rbListString.begin();
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));
+
+ while(it != rbListString.end()) // This loop should do nothing.
+ {
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));
+ ++it;
+ }
+
+ // void push_back(const value_type& value);
+ sprintf(counterBuffer, "%d", counter++);
+ rbListString.push_back(string(counterBuffer));
+ EATEST_VERIFY(rbListString.validate());
+ EATEST_VERIFY(!rbListString.empty());
+ EATEST_VERIFY(rbListString.size() == 1);
+ EATEST_VERIFY(rbListString.capacity() == 50);
+
+ it = rbListString.begin();
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ EATEST_VERIFY(*it == "0");
+
+ // reference front();
+ // reference back();
+ string& sFront = rbListString.front();
+ string& sBack = rbListString.back();
+ EATEST_VERIFY(&sFront == &sBack);
+
+ // void push_back();
+ string& ref = rbListString.push_back();
+ EATEST_VERIFY(rbListString.validate());
+ EATEST_VERIFY(rbListString.size() == 2);
+ EATEST_VERIFY(rbListString.capacity() == 50);
+ EATEST_VERIFY(&ref == &rbListString.back());
+
+ it = rbListString.begin();
+ ++it;
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ EATEST_VERIFY(it->empty());
+
+ sprintf(counterBuffer, "%d", counter++);
+ *it = counterBuffer;
+ EATEST_VERIFY(*it == "1");
+
+ ++it;
+ EATEST_VERIFY(it == rbListString.end());
+
+ it = rbListString.begin();
+ while(it != rbListString.end())
+ {
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ ++it;
+ }
+
+ // reference operator[](size_type n);
+ string& s0 = rbListString[0];
+ EATEST_VERIFY(s0 == "0");
+
+ string& s1 = rbListString[1];
+ EATEST_VERIFY(s1 == "1");
+
+ // Now we start hammering the ring buffer with push_back.
+ for(eastl_size_t i = 0, iEnd = rbListString.capacity() * 5; i != iEnd; i++)
+ {
+ sprintf(counterBuffer, "%d", counter++);
+ rbListString.push_back(string(counterBuffer));
+ EATEST_VERIFY(rbListString.validate());
+ }
+
+ int counterCheck = counter - 1;
+ char counterCheckBuffer[32];
+ sprintf(counterCheckBuffer, "%d", counterCheck);
+ EATEST_VERIFY(rbListString.back() == counterCheckBuffer);
+
+ // reverse_iterator rbegin();
+ // reverse_iterator rend();
+ for(RBListString::reverse_iterator ri = rbListString.rbegin(); ri != rbListString.rend(); ++ri)
+ {
+ sprintf(counterCheckBuffer, "%d", counterCheck--);
+ EATEST_VERIFY(*ri == counterCheckBuffer);
+ }
+
+ ++counterCheck;
+
+ // iterator begin();
+ // iterator end();
+ for(RBListString::iterator i = rbListString.begin(); i != rbListString.end(); ++i)
+ {
+ EATEST_VERIFY(rbListString.validate_iterator(i) == (isf_valid | isf_current | isf_can_dereference));
+ EATEST_VERIFY(*i == counterCheckBuffer);
+ sprintf(counterCheckBuffer, "%d", ++counterCheck);
+ }
+
+ // void clear();
+ rbListString.clear();
+ EATEST_VERIFY(rbListString.validate());
+ EATEST_VERIFY(rbListString.empty());
+ EATEST_VERIFY(rbListString.size() == 0);
+ EATEST_VERIFY(rbListString.capacity() == 50);
+
+ // Random operations
+ // Not easy to test the expected values without some tedium.
+ for(int j = 0; j < 10000 + (gEASTL_TestLevel * 10000); j++)
+ {
+ sprintf(counterBuffer, "%d", counter++);
+
+ const eastl_size_t op = rng.RandLimit(12);
+ const eastl_size_t s = rbListString.size();
+
+ if(op == 0)
+ {
+ // void push_back(const value_type& value);
+
+ rbListString.push_back(string(counterBuffer));
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));
+ }
+ else if(op == 1)
+ {
+ // void push_back();
+
+ string& ref2 = rbListString.push_back();
+ rbListString.back() = string(counterBuffer);
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));
+ EATEST_VERIFY(&ref2 == &rbListString.back());
+ }
+ else if(op == 2)
+ {
+ // void pop_back();
+
+ if(!rbListString.empty())
+ {
+ rbListString.pop_back();
+ EATEST_VERIFY(rbListString.size() == (s - 1));
+ }
+ }
+ else if(op == 3)
+ {
+ // void push_front(const value_type& value);
+
+ rbListString.push_front(string(counterBuffer));
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));
+ }
+ else if(op == 4)
+ {
+ // void push_front();
+
+ string& ref2 = rbListString.push_front();
+ rbListString.front() = string(counterBuffer);
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));
+ EATEST_VERIFY(&ref2 == &rbListString.front());
+ }
+ else if(op == 5)
+ {
+ // void pop_front();
+
+ if(!rbListString.empty())
+ {
+ rbListString.pop_front();
+ EATEST_VERIFY(rbListString.size() == (s - 1));
+ }
+ }
+ else if(op == 6)
+ {
+ // iterator insert(iterator position, const value_type& value);
+
+ it = rbListString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);
+ eastl::advance(it, dist);
+
+ if(it == rbListString.end())
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+
+ rbListString.insert(it, string(counterBuffer));
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));
+ }
+ else if(op == 7)
+ {
+ // void insert(iterator position, size_type n, const value_type& value);
+
+ it = rbListString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);
+ eastl::advance(it, dist);
+
+ if(it == rbListString.end())
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+
+ const eastl_size_t count = (eastl_size_t)rng.RandLimit(10);
+
+ rbListString.insert(it, count, string(counterBuffer));
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + count, rbListString.capacity()));
+ }
+ else if(op == 8)
+ {
+ // template <typename InputIterator>
+ // void insert(iterator position, InputIterator first, InputIterator last);
+
+ string stringArray[10];
+
+ it = rbListString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);
+ eastl::advance(it, dist);
+
+ if(it == rbListString.end())
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+
+ const eastl_size_t count = (eastl_size_t)rng.RandLimit(10);
+
+ rbListString.insert(it, stringArray, stringArray + count);
+ EATEST_VERIFY(rbListString.size() == eastl::min(s + count, rbListString.capacity()));
+ }
+ else if(op == 9)
+ {
+ // iterator erase(iterator position);
+
+ if(!rbListString.empty())
+ {
+ it = rbListString.begin();
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s);
+ eastl::advance(it, dist);
+ EATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));
+ rbListString.erase(it);
+
+ EATEST_VERIFY(rbListString.size() == (s - 1));
+ }
+ }
+ else if(op == 10)
+ {
+ // iterator erase(iterator first, iterator last);
+
+ if(!rbListString.empty())
+ {
+ RBListString::iterator it1 = rbListString.begin();
+ const eastl_size_t pos = rng.RandLimit((uint32_t)s / 4);
+ eastl::advance(it1, pos);
+ EATEST_VERIFY(rbListString.validate_iterator(it1) == (isf_valid | isf_current | isf_can_dereference));
+
+ RBListString::iterator it2 = it1;
+ const eastl_size_t dist = rng.RandLimit((uint32_t)s / 4);
+ eastl::advance(it2, dist);
+ EATEST_VERIFY(rbListString.validate_iterator(it2) == (isf_valid | isf_current | isf_can_dereference));
+
+ EATEST_VERIFY(s > (pos + dist));
+ rbListString.erase(it1, it2);
+ EATEST_VERIFY(rbListString.size() == (s - dist));
+ }
+ }
+ else if(op == 11)
+ {
+ // void resize(size_type n);
+ const eastl_size_t nSubOp = rng.RandLimit(100);
+
+ if(nSubOp == 1)
+ {
+ rbListString.resize(kOriginalCapacity);
+ EATEST_VERIFY(rbListString.size() == (RBListString::size_type)kOriginalCapacity);
+ }
+ else if(nSubOp == 2)
+ {
+ const eastl_size_t newSize = rng.RandLimit((uint32_t)s * 2) + 2;
+
+ rbListString.resize(newSize);
+ EATEST_VERIFY(rbListString.size() == newSize);
+ }
+ else if(nSubOp == 3)
+ {
+ rbListString.clear();
+ EATEST_VERIFY(rbListString.size() == 0);
+ }
+ }
+
+ EATEST_VERIFY(rbListString.validate());
+ }
+
+ // We make sure that after the above we still have some contents.
+ if(rbListString.size() < 8)
+ rbListString.resize(8);
+
+ EATEST_VERIFY(rbListString.validate());
+
+ // Test const functions
+ // const_iterator begin() const;
+ // const_iterator end() const;
+ // const_reverse_iterator rbegin() const;
+ // const_reverse_iterator rend() const;
+ // const_reference front() const;
+ // const_reference back() const;
+ // const_reference operator[](size_type n) const;
+ // const container_type& get_container() const;
+ const RBListString& rbVSConst = rbListString;
+
+ for(RBListString::const_iterator ic = rbVSConst.begin(); ic != rbVSConst.end(); ++ic)
+ {
+ EATEST_VERIFY(rbListString.validate_iterator(ic) == (isf_valid | isf_current | isf_can_dereference));
+ }
+
+ for(RBListString::const_reverse_iterator ric = rbVSConst.rbegin(); ric != rbVSConst.rend(); ++ric)
+ {
+ if(ric == rbVSConst.rbegin())
+ EATEST_VERIFY(rbListString.validate_iterator(ric.base()) == (isf_valid | isf_current));
+ else
+ EATEST_VERIFY(rbListString.validate_iterator(ric.base()) == (isf_valid | isf_current | isf_can_dereference));
+ }
+
+ EATEST_VERIFY(rbVSConst.front() == rbListString.front());
+ EATEST_VERIFY(rbVSConst.back() == rbListString.back());
+ EATEST_VERIFY(rbVSConst[0] == rbListString[0]);
+ EATEST_VERIFY(&rbVSConst.get_container() == &rbListString.get_container());
+
+
+ // Test additional constructors.
+ // ring_buffer(const this_type& x);
+ // explicit ring_buffer(const Container& x);
+ // this_type& operator=(const this_type& x);
+ // void swap(this_type& x);
+ RBListString rbListString2(rbListString);
+ RBListString rbListString3(rbListString.get_container());
+ RBListString rbListString4(rbListString.capacity() / 2);
+ RBListString rbListString5(rbListString.capacity() * 2);
+
+ EATEST_VERIFY(rbListString.validate());
+ EATEST_VERIFY(rbListString2.validate());
+ EATEST_VERIFY(rbListString3.validate());
+ EATEST_VERIFY(rbListString4.validate());
+ EATEST_VERIFY(rbListString5.validate());
+
+ EATEST_VERIFY(rbListString == rbListString2);
+ EATEST_VERIFY(rbListString3.get_container() == rbListString2.get_container());
+
+ rbListString3 = rbListString4;
+ EATEST_VERIFY(rbListString3.validate());
+
+ eastl::swap(rbListString2, rbListString4);
+ EATEST_VERIFY(rbListString2.validate());
+ EATEST_VERIFY(rbListString3.validate());
+ EATEST_VERIFY(rbListString4.validate());
+ EATEST_VERIFY(rbListString == rbListString4);
+ EATEST_VERIFY(rbListString2 == rbListString3);
+
+ // void ring_buffer<T, Container>::reserve(size_type n)
+ eastl_size_t cap = rbListString2.capacity();
+ rbListString2.reserve(cap += 2);
+ EATEST_VERIFY(rbListString2.validate());
+ EATEST_VERIFY(rbListString2.capacity() == cap);
+ rbListString2.reserve(cap -= 4); // This should act as a no-op if we are following convention.
+ EATEST_VERIFY(rbListString2.validate());
+
+
+ // template <typename InputIterator>
+ // void assign(InputIterator first, InputIterator last);
+ string stringArray[10];
+ for(int q = 0; q < 10; q++)
+ stringArray[q] = '0' + (char)q;
+
+ rbListString5.assign(stringArray, stringArray + 10);
+ EATEST_VERIFY(rbListString5.validate());
+ EATEST_VERIFY(rbListString5.size() == 10);
+ EATEST_VERIFY(rbListString5.front() == "0");
+ EATEST_VERIFY(rbListString5.back() == "9");
+
+
+ // ring_buffer(this_type&& x);
+ // ring_buffer(this_type&& x, const allocator_type& allocator);
+ // this_type& operator=(this_type&& x);
+
+ RBListString rbListStringM1(eastl::move(rbListString5));
+ EATEST_VERIFY(rbListStringM1.validate() && rbListString5.validate());
+ EATEST_VERIFY((rbListStringM1.size() == 10) && (rbListString5.size() == 0));
+
+ RBListString rbListStringM2(eastl::move(rbListStringM1), RBListString::allocator_type());
+ EATEST_VERIFY(rbListStringM2.validate() && rbListStringM1.validate());
+ EATEST_VERIFY((rbListStringM2.size() == 10) && (rbListStringM1.size() == 0));
+
+ rbListStringM1 = eastl::move(rbListStringM2);
+ EATEST_VERIFY(rbListStringM1.validate() && rbListStringM2.validate());
+ EATEST_VERIFY((rbListStringM1.size() == 10) && (rbListStringM2.size() == 0));
+ }
+
+
+
+ {
+ // ring_buffer(std::initializer_list<value_type> ilist, const allocator_type& allocator = allocator_type());
+ // this_type& operator=(std::initializer_list<value_type> ilist);
+ // void insert(iterator position, std::initializer_list<value_type> ilist);
+ #if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)
+ ring_buffer<int> intBuffer = { 0, 1, 2 };
+ EATEST_VERIFY(VerifySequence(intBuffer.begin(), intBuffer.end(), int(), "ring_buffer std::initializer_list", 0, 1, 2, -1));
+
+ intBuffer = { 16, 17, 18 };
+ EATEST_VERIFY(VerifySequence(intBuffer.begin(), intBuffer.end(), int(), "ring_buffer std::initializer_list", 16, 17, 18, -1));
+
+ // We need to increase the capacity in order to insert new items because the ctor above set the capacity to be only enough to hold the initial list.
+ intBuffer.reserve(intBuffer.capacity() + 2);
+ intBuffer.insert(intBuffer.begin(), { 14, 15 });
+ EATEST_VERIFY(VerifySequence(intBuffer.begin(), intBuffer.end(), int(), "ring_buffer std::initializer_list", 14, 15, 16, 17, 18, -1));
+ #endif
+ }
+
+ {
+ // Regression for user-reported problem.
+ typedef eastl::fixed_vector<float, 8> GamepadData_t;
+ typedef eastl::ring_buffer<GamepadData_t> GamepadDataDelayBuffer_t;
+ typedef eastl::fixed_vector<GamepadDataDelayBuffer_t, 32> GamepadDataDelayBufferTable_t;
+
+ GamepadDataDelayBufferTable_t mDelayTable;
+ mDelayTable.resize(32);
+ for(eastl_size_t i = 0; i < mDelayTable.size(); i++)
+ mDelayTable[i].reserve(16);
+
+ GamepadData_t data(8, 1.f);
+ mDelayTable[0].push_back(data);
+ mDelayTable[0].push_back(data);
+ mDelayTable[0].push_back(data);
+ mDelayTable[0].push_back(data);
+
+ EATEST_VERIFY(mDelayTable[0].size() == 4);
+ GamepadData_t dataFront = mDelayTable[0].front();
+ EATEST_VERIFY((dataFront.size() == 8) && (dataFront[0] == 1.f));
+ mDelayTable[0].pop_front();
+ }
+
+ {
+ // Regression for bug with iterator subtraction
+ typedef eastl::ring_buffer<int> IntBuffer_t;
+ IntBuffer_t intBuffer = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ IntBuffer_t::iterator it = intBuffer.begin();
+
+ EATEST_VERIFY(*it == 0);
+ it += 4;
+ EATEST_VERIFY(*it == 4);
+ it--;
+ EATEST_VERIFY(*it == 3);
+ it -= 2;
+ EATEST_VERIFY(*it == 1);
+
+ intBuffer.push_back(8);
+ intBuffer.push_back(9);
+ intBuffer.push_back(10);
+ intBuffer.push_back(11);
+
+ EATEST_VERIFY(*it == 10);
+ it -= 3;
+ EATEST_VERIFY(*it == 7); // Test looping around the end of the underlying container
+ it -= 5;
+ EATEST_VERIFY(*it == 11); // Test wrapping around begin to end of the ring_buffer
+ it -= 2;
+ EATEST_VERIFY(*it == 9); // It is important to test going back to the beginning of the underlying container.
+
+ }
+
+ // fixed_ring_buffer<T,N> tests
+ // ring_buffer<T, fixed_vector<T,N>> tests
+ {
+ {
+ // (MAX_ELEMENTS - 1) accommodates the ring_buffer sentinel
+ const int MAX_ELEMENTS = 8;
+ eastl::ring_buffer<int, eastl::fixed_vector<int, MAX_ELEMENTS, false>> rb(MAX_ELEMENTS - 1);
+
+ for (int i = 0; i < MAX_ELEMENTS - 1; i++)
+ rb.push_back(i);
+
+ auto it = rb.begin();
+ for (int i = 0; i < MAX_ELEMENTS - 1; i++)
+ { EATEST_VERIFY(*it++ == i); }
+ }
+
+ #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
+ {
+ const int MAX_ELEMENTS = 25;
+ eastl::fixed_ring_buffer<int, MAX_ELEMENTS> rb(MAX_ELEMENTS);
+
+ for(int i = 0; i < MAX_ELEMENTS; i++)
+ rb.push_back(i);
+
+ auto it = rb.begin();
+ for(int i = 0; i < MAX_ELEMENTS; i++)
+ { EATEST_VERIFY(*it++ == i); }
+ }
+ #endif
+
+ #if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
+ {
+ const int MAX_ELEMENTS = 8;
+ eastl::fixed_ring_buffer<int, MAX_ELEMENTS> rb = {0, 1, 2, 3, 4, 5, 6, 7};
+
+ auto it = rb.begin();
+ for(int i = 0; i < MAX_ELEMENTS; i++)
+ { EATEST_VERIFY(*it++ == i); }
+ }
+
+ {
+ struct LocalStruct {};
+ fixed_ring_buffer<LocalStruct, 8> rb = {{{}, {}, {}}};
+ EATEST_VERIFY(rb.size() == 3);
+ }
+ #endif
+ }
+
+ {
+ const auto MAX_ELEMENTS = EASTL_MAX_STACK_USAGE;
+
+ // create a container simulating LARGE state that exceeds
+ // our maximum stack size macro. This forces our ring_buffer implementation
+ // to allocate the container in the heap instead of holding it on the stack.
+ // This test ensures that allocation is NOT serviced by the default global heap.
+ // Instead it is serviced by the allocator of the ring_buffers underlying container.
+ struct PaddedVector : public eastl::vector<int, MallocAllocator>
+ {
+ char mPadding[EASTL_MAX_STACK_USAGE];
+ };
+
+ MallocAllocator::reset_all();
+ CountingAllocator::resetCount();
+
+ {
+ CountingAllocator countingAlloc;
+ AutoDefaultAllocator _(&countingAlloc);
+
+ eastl::ring_buffer<int, PaddedVector> intBuffer(1);
+ for (int i = 0; i < MAX_ELEMENTS; i++)
+ intBuffer.push_back(i);
+
+ #if !EASTL_OPENSOURCE
+ const auto cacheAllocationCount = gEASTLTest_TotalAllocationCount;
+ #endif
+ const auto cacheMallocatorCount = MallocAllocator::mAllocCountAll;
+ const auto forceReAllocSize = intBuffer.size() * 2;
+
+ intBuffer.resize(forceReAllocSize);
+
+ #if !EASTL_OPENSOURCE
+ VERIFY(cacheAllocationCount == gEASTLTest_TotalAllocationCount);
+ #endif
+ VERIFY(cacheMallocatorCount < MallocAllocator::mAllocCountAll);
+ VERIFY(CountingAllocator::neverUsed());
+ }
+ }
+
+ return nErrorCount;
+}
+
+
+
+
+
+
+
+
+