From 15c3f85149bfcf60a70662a4c9ca9763d40e4e72 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Thu, 17 Jan 2008 20:50:18 +0000 Subject: Intrusive list template qpid::IList and unit tests. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@612976 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/tests/IList.cpp | 223 +++++++++++++++++++++++++++++++++++++++++++++ cpp/src/tests/Makefile.am | 3 +- cpp/src/tests/test_tools.h | 42 ++++++--- 3 files changed, 256 insertions(+), 12 deletions(-) create mode 100644 cpp/src/tests/IList.cpp (limited to 'cpp/src/tests') diff --git a/cpp/src/tests/IList.cpp b/cpp/src/tests/IList.cpp new file mode 100644 index 0000000000..ed36228828 --- /dev/null +++ b/cpp/src/tests/IList.cpp @@ -0,0 +1,223 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * 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 "unit_test.h" +#include "test_tools.h" +#include "qpid/IList.h" +#include +#include + +using namespace qpid; +using namespace std; +using boost::assign::list_of; + +// Comparison, op== for ILists and sequences of intrusive_ptr +// in qpid namespace to satisfy template lookup rules +namespace qpid { +template bool operator==(const IList& a, const S& b) { return seqEqual(a, b); } +template std::ostream& operator<<(std::ostream& o, const IList& l) { return seqPrint(o, l); } +} + +QPID_AUTO_TEST_SUITE(IListTestSuite) + +template bool operator==(const T& v, const intrusive_ptr& p) { return v==*p; } + +struct TestNode { + static int instances; + char id; + TestNode(char i) : id(i) { ++instances; } + ~TestNode() { --instances; } + bool operator==(const TestNode& x) const { return this == &x; } + bool operator==(const TestNode* x) const { return this == x; } +}; +int TestNode::instances = 0; +ostream& operator<<(ostream& o, const TestNode& n) { return o << n.id; } + +struct SingleNode : public TestNode, public IListNode<> { SingleNode(char i) : TestNode(i) {} }; +typedef IList TestList; + +struct Fixture { + intrusive_ptr a, b, c, d; + Fixture() : a(new SingleNode('a')), + b(new SingleNode('b')), + c(new SingleNode('c')), + d(new SingleNode('d')) + { + BOOST_CHECK_EQUAL(4, TestNode::instances); + } +}; + +BOOST_AUTO_TEST_CASE(TestFixture) { + { Fixture f; } + BOOST_CHECK_EQUAL(0, TestNode::instances); +} + +BOOST_FIXTURE_TEST_CASE(TestSingleList, Fixture) { + TestList l; + BOOST_CHECK_EQUAL(0u, l.size()); + BOOST_CHECK(l.empty()); + + l.push_back(*a); + BOOST_CHECK_EQUAL(1u, l.size()); + BOOST_CHECK(!l.empty()); + BOOST_CHECK_EQUAL(l, list_of(a)); + + TestList::iterator i = l.begin(); + BOOST_CHECK_EQUAL(*i, *a); + + l.push_back(*b); + BOOST_CHECK_EQUAL(2u, l.size()); + BOOST_CHECK_EQUAL(l, list_of(a)(b)); + BOOST_CHECK_EQUAL(*i, *a); // Iterator not invalidated + BOOST_CHECK_EQUAL(l.front(), *a); + BOOST_CHECK_EQUAL(l.back(), *b); + + l.push_front(*c); + BOOST_CHECK_EQUAL(3u, l.size()); + BOOST_CHECK_EQUAL(l, list_of(c)(a)(b)); + BOOST_CHECK_EQUAL(*i, *a); // Iterator not invalidated + + l.insert(i, *d); + BOOST_CHECK_EQUAL(4u, l.size()); + BOOST_CHECK_EQUAL(l, list_of(c)(d)(a)(b)); + BOOST_CHECK_EQUAL(*i, *a); + + a = 0; // Not deleted yet, still in list. + BOOST_CHECK_EQUAL(4, SingleNode::instances); + l.erase(i); + BOOST_CHECK_EQUAL(3, SingleNode::instances); + BOOST_CHECK_EQUAL(l, list_of(c)(d)(b)); + + l.pop_front(); + l.pop_back(); + c = 0; b = 0; + BOOST_CHECK_EQUAL(1, SingleNode::instances); + BOOST_CHECK_EQUAL(l, list_of(d)); + + l.pop_back(); + BOOST_CHECK_EQUAL(0u, l.size()); + BOOST_CHECK(l.empty()); +} + +BOOST_FIXTURE_TEST_CASE(TestIterator, Fixture) { + { + TestList l; + l.push_back(*a); + l.push_back(*b); + l.push_back(*c); + + TestList::iterator i = l.begin(); + BOOST_CHECK_EQUAL(*i, *a); + i++; + BOOST_CHECK_EQUAL(*i, *b); + i++; + BOOST_CHECK_EQUAL(*i, *c); + i++; + BOOST_CHECK(i == l.end()); + i--; + BOOST_CHECK_EQUAL(*i, *c); + i--; + BOOST_CHECK_EQUAL(*i, *b); + i--; + BOOST_CHECK_EQUAL(*i, *a); + } + a = b = c = d = 0; + BOOST_CHECK_EQUAL(0, TestNode::instances); +} + + +BOOST_FIXTURE_TEST_CASE(testOwnership, Fixture) { + { + TestList l2; + l2.push_back(*a); + l2.push_back(*b); + l2.push_back(*c); + l2.push_back(*d); + a = b = c = d = 0; + BOOST_CHECK_EQUAL(4, SingleNode::instances); + } + BOOST_CHECK_EQUAL(0, SingleNode::instances); +} + +struct MultiNode : public TestNode, public IListNode<0>, public IListNode<1>, public IListNode<2> { + MultiNode(char c) : TestNode(c) {} +}; + +struct MultiFixture { + IList l0; + IList l1; + IList l2; + + intrusive_ptr a, b, c; + + MultiFixture() : a(new MultiNode('a')), + b(new MultiNode('b')), + c(new MultiNode('c')) + { + BOOST_CHECK_EQUAL(3, MultiNode::instances); + } + + void push_back_all(intrusive_ptr p) { + l0.push_back(*p); + l1.push_back(*p); + l2.push_back(*p); + } +}; + +BOOST_FIXTURE_TEST_CASE(TestMultiIList, MultiFixture) { + BOOST_CHECK_EQUAL(a->id, 'a'); + push_back_all(a); + push_back_all(b); + push_back_all(c); + + BOOST_CHECK_EQUAL(3, MultiNode::instances); + + l0.pop_front(); + l1.pop_back(); + IList::iterator i = l2.begin(); + i++; + l2.erase(i); + BOOST_CHECK_EQUAL(3, MultiNode::instances); + BOOST_CHECK_EQUAL(l0, list_of(b)(c)); + BOOST_CHECK_EQUAL(l1, list_of(a)(b)); + BOOST_CHECK_EQUAL(l2, list_of(a)(c)); + + l1.pop_front(); + l2.clear(); + BOOST_CHECK_EQUAL(l0, list_of(b)(c)); + BOOST_CHECK_EQUAL(l1, list_of(b)); + BOOST_CHECK(l2.empty()); + a = 0; + BOOST_CHECK_EQUAL(2, MultiNode::instances); // a gone + + l0.pop_back(); + l1.pop_front(); + BOOST_CHECK_EQUAL(l0, list_of(b)); + BOOST_CHECK(l1.empty()); + BOOST_CHECK(l2.empty()); + BOOST_CHECK_EQUAL(2, MultiNode::instances); // c gone + c = 0; + + l0.clear(); + b = 0; + BOOST_CHECK_EQUAL(0, MultiNode::instances); // all gone +} + +QPID_AUTO_TEST_SUITE_END() + diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am index 87960145a4..5291891510 100644 --- a/cpp/src/tests/Makefile.am +++ b/cpp/src/tests/Makefile.am @@ -35,7 +35,8 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \ SessionState.cpp Blob.cpp logging.cpp \ Url.cpp Uuid.cpp \ Shlib.cpp FieldValue.cpp FieldTable.cpp Array.cpp \ - InlineVector.cpp + InlineVector.cpp \ + IList.cpp check_LTLIBRARIES += libshlibtest.la libshlibtest_la_LDFLAGS = -module -rpath $(abs_builddir) diff --git a/cpp/src/tests/test_tools.h b/cpp/src/tests/test_tools.h index e564b9a473..2de4b6fbc1 100644 --- a/cpp/src/tests/test_tools.h +++ b/cpp/src/tests/test_tools.h @@ -22,21 +22,41 @@ #include #include #include +#include #include +#include + +// Print a sequence +template std::ostream& seqPrint(std::ostream& o, const T& seq) { + std::copy(seq.begin(), seq.end(), std::ostream_iterator(o, " ")); + return o; +} + +// Compare sequences +template +bool seqEqual(const T& a, const U& b) { + typename T::const_iterator i = a.begin(); + typename U::const_iterator j = b.begin(); + while (i != a.end() && j != b.end() && *i == *j) { ++i; ++j; } + return (i == a.end()) && (j == b.end()); +} + +// ostream and == operators so we can compare vectors and boost::assign::list_of +// with BOOST_CHECK_EQUALS +namespace std { // In namespace std so boost can find them. + +template +ostream& operator<<(ostream& o, const vector& v) { return seqPrint(o, v); } + +template +ostream& operator<<(ostream& o, const boost::assign_detail::generic_list& l) { return seqPrint(o, l); } + +template +bool operator == (const vector& a, const boost::assign_detail::generic_list& b) { return seqEqual(a, b); } -/** Stream operator so BOOST_CHECK_EQUALS works on vectors. */ -namespace std { template -ostream& operator <<(ostream& o, const vector& v) { - o << " {"; - typename vector::const_iterator i = v.begin(); - if (i != v.end()) - o << *i++; - while (i != v.end()) - o << ", " << *i++; - return o << "}"; +bool operator == (const boost::assign_detail::generic_list& b, const vector& a) { return seqEqual(a, b); } } -} // namespace std /** NB: order of parameters is regex first, in line with * CHECK(expected, actual) convention. -- cgit v1.2.1