diff options
31 files changed, 299 insertions, 166 deletions
diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am index 521f2975a6..218b7fcd1d 100644 --- a/qpid/cpp/src/Makefile.am +++ b/qpid/cpp/src/Makefile.am @@ -225,6 +225,7 @@ nobase_include_HEADERS = \ qpid/Msg.h \ qpid/Options.h \ qpid/Plugin.h \ + qpid/RefCounted.h \ qpid/SharedObject.h \ qpid/Url.h \ qpid/memory.h \ diff --git a/qpid/cpp/src/qpid/RefCounted.h b/qpid/cpp/src/qpid/RefCounted.h new file mode 100644 index 0000000000..790076b463 --- /dev/null +++ b/qpid/cpp/src/qpid/RefCounted.h @@ -0,0 +1,73 @@ +#ifndef QPID_REFCOUNTED_H +#define QPID_REFCOUNTED_H + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "qpid/sys/AtomicCount.h" + +#include <boost/intrusive_ptr.hpp> + + +namespace qpid { + +/** Abstract interface for reference counted objects */ +class AbstractRefCounted { + public: + virtual void addRef() const=0; + virtual void release() const=0; + protected: + virtual ~AbstractRefCounted() {} +}; + +/** + * Reference-counted virtual base class. + */ +class RefCounted : public AbstractRefCounted +{ + public: + RefCounted() {} + virtual void addRef() const { ++count; } + virtual void release() const { if (--count==0) released(); } + + protected: + virtual ~RefCounted() {}; + // Copy/assign do not copy refcounts. + RefCounted(const RefCounted&) : AbstractRefCounted() {} + RefCounted& operator=(const RefCounted&) { return *this; } + virtual void released() const { delete this; } + + private: + mutable sys::AtomicCount count; +}; + +using boost::intrusive_ptr; + +} // namespace qpid + +// intrusive_ptr support. +namespace boost { +void intrusive_ptr_add_ref(const qpid::AbstractRefCounted* p) { p->addRef(); } +void intrusive_ptr_release(const qpid::AbstractRefCounted* p) { p->release(); } +} + + +#endif /*!QPID_REFCOUNTED_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionHandler.cpp b/qpid/cpp/src/qpid/broker/SessionHandler.cpp index 0dafcba7bd..f72c52c809 100644 --- a/qpid/cpp/src/qpid/broker/SessionHandler.cpp +++ b/qpid/cpp/src/qpid/broker/SessionHandler.cpp @@ -38,8 +38,7 @@ SessionHandler::SessionHandler(Connection& c, ChannelId ch) connection(c), channel(ch, &c.getOutput()), proxy(out), // Via my own handleOut() for L2 data. peerSession(channel), // Direct to channel for L2 commands. - ignoring(false), - resuming(false) {} + ignoring(false) {} SessionHandler::~SessionHandler() {} @@ -117,8 +116,7 @@ void SessionHandler::resume(const Uuid& id) { assertClosed("resume"); session = connection.broker.getSessionManager().resume(id); session->attach(*this); - resuming=true; - SequenceNumber seq = session->sendingAck(); + SequenceNumber seq = session->resuming(); peerSession.attached(session->getId(), session->getTimeout()); proxy.getSession().ack(seq, SequenceNumberSet()); } @@ -171,8 +169,7 @@ void SessionHandler::ack(uint32_t cumulativeSeenMark, const SequenceNumberSet& /*seenFrameSet*/) { assertAttached("ack"); - if (resuming) { - resuming=false; + if (session->getState() == SessionState::RESUMING) { session->receivedAck(cumulativeSeenMark); framing::SessionState::Replay replay=session->replay(); std::for_each(replay.begin(), replay.end(), diff --git a/qpid/cpp/src/qpid/broker/SessionHandler.h b/qpid/cpp/src/qpid/broker/SessionHandler.h index 800b886bbf..08584ecd47 100644 --- a/qpid/cpp/src/qpid/broker/SessionHandler.h +++ b/qpid/cpp/src/qpid/broker/SessionHandler.h @@ -94,7 +94,6 @@ class SessionHandler : public framing::FrameHandler::InOutHandler, framing::AMQP_ClientProxy proxy; framing::AMQP_ClientProxy::Session peerSession; bool ignoring; - bool resuming; std::auto_ptr<SessionState> session; sys::Semaphore suspension; }; diff --git a/qpid/cpp/src/qpid/broker/SessionManager.cpp b/qpid/cpp/src/qpid/broker/SessionManager.cpp index 5bdc572491..f12ebc6db1 100644 --- a/qpid/cpp/src/qpid/broker/SessionManager.cpp +++ b/qpid/cpp/src/qpid/broker/SessionManager.cpp @@ -56,6 +56,7 @@ std::auto_ptr<SessionState> SessionManager::open( void SessionManager::suspend(std::auto_ptr<SessionState> session) { Mutex::ScopedLock l(lock); active.erase(session->getId()); + session->suspend(); session->expiry = AbsTime(now(),session->getTimeout()*TIME_SEC); suspended.push_back(session.release()); // In expiry order eraseExpired(); diff --git a/qpid/cpp/src/qpid/client/SessionCore.cpp b/qpid/cpp/src/qpid/client/SessionCore.cpp index 30df574716..f7f0f52dba 100644 --- a/qpid/cpp/src/qpid/client/SessionCore.cpp +++ b/qpid/cpp/src/qpid/client/SessionCore.cpp @@ -52,6 +52,7 @@ inline void SessionCore::invariant() const { break; case RESUMING: assert(session); + assert(session->getState() == SessionState::RESUMING); assert(code==REPLY_SUCCESS); assert(connection); assert(channel.get()); @@ -142,6 +143,7 @@ void SessionCore::doSuspend(int code, const std::string& text) { if (state != CLOSED) { invariant(); detach(code, text); + session->suspend(); setState(SUSPENDED); } } @@ -200,7 +202,7 @@ void SessionCore::resume(shared_ptr<ConnectionImpl> c) { if (state==OPEN) doSuspend(REPLY_SUCCESS, OK); check(state==SUSPENDED, COMMAND_INVALID, QPID_MSG("Session cannot be resumed.")); - SequenceNumber sendAck=session->sendingAck(); + SequenceNumber sendAck=session->resuming(); attaching(c); proxy.resume(getId()); waitFor(OPEN); diff --git a/qpid/cpp/src/qpid/framing/SessionState.cpp b/qpid/cpp/src/qpid/framing/SessionState.cpp index 7e905bdf63..8056f4a523 100644 --- a/qpid/cpp/src/qpid/framing/SessionState.cpp +++ b/qpid/cpp/src/qpid/framing/SessionState.cpp @@ -33,6 +33,7 @@ namespace qpid { namespace framing { SessionState::SessionState(uint32_t ack, const Uuid& uuid) : + state(ATTACHED), id(uuid), lastReceived(-1), lastSent(-1), @@ -44,6 +45,7 @@ SessionState::SessionState(uint32_t ack, const Uuid& uuid) : {} SessionState::SessionState(const Uuid& uuid) : + state(ATTACHED), id(uuid), lastReceived(-1), lastSent(-1), @@ -63,6 +65,10 @@ bool isSessionCommand(const AMQFrame& f) { boost::optional<SequenceNumber> SessionState::received(const AMQFrame& f) { if (isSessionCommand(f)) return boost::none; + if (state==RESUMING) + throw CommandInvalidException( + QPID_MSG("Invalid frame: Resuming session, expected session-ack")); + assert(state = ATTACHED); ++lastReceived; QPID_LOG(trace, "Recv # "<< lastReceived << " " << id); if (ackInterval && lastReceived == sendAckAt) @@ -79,6 +85,7 @@ bool SessionState::sent(const AMQFrame& f) { ++lastSent; QPID_LOG(trace, "Sent # "<< lastSent << " " << id); return ackInterval && + (state!=RESUMING) && (lastSent == solicitAckAt) && sendingSolicit(); } @@ -90,6 +97,8 @@ SessionState::Replay SessionState::replay() { } void SessionState::receivedAck(SequenceNumber acked) { + if (state==RESUMING) state=ATTACHED; + assert(state==ATTACHED); if (lastSent < acked) throw InvalidArgumentException("Invalid sequence number in ack"); size_t keep = lastSent - acked; @@ -104,10 +113,22 @@ SequenceNumber SessionState::sendingAck() { } bool SessionState::sendingSolicit() { + assert(state == ATTACHED); if (ackSolicited) return false; solicitAckAt = lastSent + ackInterval; return ackInterval != 0; } +SequenceNumber SessionState::resuming() { + if (!resumable) + throw InternalErrorException("Session is not resumable"); + state = RESUMING; + return sendingAck(); +} + +void SessionState::suspend() { + state = SUSPENDED; +} + }} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/SessionState.h b/qpid/cpp/src/qpid/framing/SessionState.h index 5034de4e94..361c960db1 100644 --- a/qpid/cpp/src/qpid/framing/SessionState.h +++ b/qpid/cpp/src/qpid/framing/SessionState.h @@ -35,10 +35,7 @@ namespace framing { /** * Session state common to client and broker. - * - * Stores data needed to resume a session: replay frames, implements - * session ack/resume protcools. Stores handler chains for the session, - * handlers may themselves store state. + * Stores replay frames, implements session ack/resume protcools. * * A SessionState is always associated with an _open_ session (attached or * suspended) it is destroyed when the session is closed. @@ -49,6 +46,13 @@ class SessionState public: typedef std::vector<AMQFrame> Replay; + /** States of a session. */ + enum State { + SUSPENDED, ///< Suspended, detached from any channel. + RESUMING, ///< Resuming: waiting for initial ack from peer. + ATTACHED ///< Attached to channel and operating normally. + }; + /** *Create a newly opened active session. *@param ackInterval send/solicit an ack whenever N unacked frames @@ -56,8 +60,7 @@ class SessionState * * N=0 disables voluntary send/solict ack. */ - SessionState(uint32_t ackInterval, - const framing::Uuid& id=framing::Uuid(true)); + SessionState(uint32_t ackInterval, const framing::Uuid& id=framing::Uuid(true)); /** * Create a non-resumable session. Does not store session frames, @@ -66,6 +69,7 @@ class SessionState SessionState(const framing::Uuid& id=framing::Uuid(true)); const framing::Uuid& getId() const { return id; } + State getState() const { return state; } /** Received incoming L3 frame. * @return SequenceNumber if an ack should be sent, empty otherwise. @@ -88,6 +92,13 @@ class SessionState */ Replay replay(); + /** Suspend the session. */ + void suspend(); + + /** Start resume protocol for the session. + *@returns sequence number to ack immediately. */ + SequenceNumber resuming(); + /** About to send an unscheduled ack, e.g. to respond to a solicit-ack. * * Note: when received() returns a sequence number this function @@ -104,7 +115,9 @@ class SessionState bool sendingSolicit(); + State state; framing::Uuid id; + Unacked unackedOut; SequenceNumber lastReceived; SequenceNumber lastSent; diff --git a/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp b/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp index eccfb1465e..bdf3e3b8d3 100644 --- a/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp +++ b/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp @@ -173,7 +173,7 @@ void AsynchIOAcceptor::run(ConnectionInputHandlerFactory* fact) { d.run(); // Now wait for n-1 io threads to exit - for (int i=0; i>numIOThreads-1; ++i) { + for (int i=0; i<numIOThreads-1; ++i) { t[i].join(); } } diff --git a/qpid/cpp/src/qpid/sys/AtomicCount.h b/qpid/cpp/src/qpid/sys/AtomicCount.h index 63670cbf00..b542e37039 100644 --- a/qpid/cpp/src/qpid/sys/AtomicCount.h +++ b/qpid/cpp/src/qpid/sys/AtomicCount.h @@ -28,7 +28,7 @@ namespace sys { /** * Atomic counter. */ -class AtomicCount : boost::noncopyable { +class AtomicCount { public: typedef ScopedDecrement<AtomicCount> ScopedDecrement; typedef ScopedIncrement<AtomicCount> ScopedIncrement; diff --git a/qpid/cpp/src/tests/.valgrind.supp-default b/qpid/cpp/src/tests/.valgrind.supp index decac01aeb..f22a9462e9 100644 --- a/qpid/cpp/src/tests/.valgrind.supp-default +++ b/qpid/cpp/src/tests/.valgrind.supp @@ -34,16 +34,6 @@ fun:epoll_ctl } { - TODO: shutdown leak, not critical but better to fix it. Unjoined thread? - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.1 - fun:pthread_create@GLIBC_2.0 - fun:_ZN4qpid3sys16AsynchIOAcceptor3runEPNS0_29ConnectionInputHandlerFactoryE -} - -{ Bogus error appearing on Fedora 7. Memcheck:Cond fun:_dl_relocate_object diff --git a/qpid/cpp/src/tests/.valgrindrc-default b/qpid/cpp/src/tests/.valgrindrc index 4aba7661de..4aba7661de 100644 --- a/qpid/cpp/src/tests/.valgrindrc-default +++ b/qpid/cpp/src/tests/.valgrindrc diff --git a/qpid/cpp/src/tests/Blob.cpp b/qpid/cpp/src/tests/Blob.cpp index eeb2fa693b..708f6771be 100644 --- a/qpid/cpp/src/tests/Blob.cpp +++ b/qpid/cpp/src/tests/Blob.cpp @@ -18,9 +18,10 @@ */ #include "qpid/framing/Blob.h" -#define BOOST_AUTO_TEST_MAIN #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Blob); + using namespace std; using namespace qpid::framing; @@ -123,3 +124,5 @@ BOOST_AUTO_TEST_CASE(testClear) { BOOST_CHECK(b.empty()); BOOST_CHECK_EQUAL(0, Foo::instances); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Cluster.cpp b/qpid/cpp/src/tests/Cluster.cpp index ee13bdd72a..80ff6d9544 100644 --- a/qpid/cpp/src/tests/Cluster.cpp +++ b/qpid/cpp/src/tests/Cluster.cpp @@ -24,8 +24,8 @@ #include "qpid/framing/all_method_bodies.h" #include "qpid/cluster/ClassifierHandler.h" -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Cluster); #include <sys/wait.h> @@ -104,5 +104,5 @@ BOOST_AUTO_TEST_CASE(testClassifierHandlerWiring) { BOOST_CHECK_EQUAL(1u, wiring.count); BOOST_CHECK_EQUAL(1u, other.count); } - +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Cpg.cpp b/qpid/cpp/src/tests/Cpg.cpp index 7c0d6f7fd0..06c8aec9ef 100644 --- a/qpid/cpp/src/tests/Cpg.cpp +++ b/qpid/cpp/src/tests/Cpg.cpp @@ -16,12 +16,15 @@ * */ -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> -#include <boost/test/auto_unit_test.hpp> + #include "test_tools.h" #include "qpid/cluster/Cpg.h" #include "qpid/framing/AMQBody.h" + #include <boost/bind.hpp> +#include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Cpg); + #include <string> #include <iostream> #include <iterator> @@ -102,3 +105,5 @@ BOOST_AUTO_TEST_CASE(CpgBasic) { BOOST_CHECK_EQUAL(0, cb.configChanges[1]); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/FieldTable.cpp b/qpid/cpp/src/tests/FieldTable.cpp index 31e3b08cba..ee23360d9a 100644 --- a/qpid/cpp/src/tests/FieldTable.cpp +++ b/qpid/cpp/src/tests/FieldTable.cpp @@ -22,8 +22,8 @@ #include "qpid/framing/FieldTable.h" #include "qpid/framing/FieldValue.h" -#define BOOST_AUTO_TEST_MAIN #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(FieldTable); using namespace qpid::framing; @@ -80,5 +80,4 @@ BOOST_AUTO_TEST_CASE(testAssignment) BOOST_CHECK(IntegerValue(1234) == *d.get("B")); } - - +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/FieldValue.cpp b/qpid/cpp/src/tests/FieldValue.cpp index 311061b646..a852a07327 100644 --- a/qpid/cpp/src/tests/FieldValue.cpp +++ b/qpid/cpp/src/tests/FieldValue.cpp @@ -18,8 +18,8 @@ */ #include "qpid/framing/FieldValue.h" -#define BOOST_AUTO_TEST_MAIN #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(FieldValue); using namespace qpid::framing; @@ -86,3 +86,4 @@ BOOST_AUTO_TEST_CASE(testFieldTableValueEquals) } #endif +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Frame.cpp b/qpid/cpp/src/tests/Frame.cpp index f02564f5da..c0839b67d7 100644 --- a/qpid/cpp/src/tests/Frame.cpp +++ b/qpid/cpp/src/tests/Frame.cpp @@ -20,9 +20,9 @@ */ #include "qpid/framing/Frame.h" -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> -#include <boost/test/auto_unit_test.hpp> #include <boost/lexical_cast.hpp> +#include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Frame); using namespace std; using namespace qpid::framing; @@ -75,3 +75,5 @@ BOOST_AUTO_TEST_CASE(testLoop) { BOOST_REQUIRE(dynamic_cast<AccessRequestOkBody*>(g.getBody())->getTicket() == 42); } } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Makefile.am b/qpid/cpp/src/tests/Makefile.am index b954ae88f4..e6626eb1e8 100644 --- a/qpid/cpp/src/tests/Makefile.am +++ b/qpid/cpp/src/tests/Makefile.am @@ -17,63 +17,24 @@ EXTRA_DIST= CLEANFILES= # -# Unit test programs. +# Unit test program +# +# Unit tests are built as a single program to reduce valgrind overhead +# when running the tests. If you want to build a subset of the tests do +# rm unit_test; make unit_test unit_test_SOURCES="SelectedTest.cpp" # -TESTS+=SessionState -check_PROGRAMS+=SessionState -SessionState_SOURCES=SessionState.cpp -SessionState_LDADD=-lboost_unit_test_framework $(lib_common) - -TESTS+=Blob -check_PROGRAMS+=Blob -Blob_SOURCES=Blob.cpp -Blob_LDADD=-lboost_unit_test_framework $(lib_common) - -TESTS+=logging -check_PROGRAMS+=logging -logging_SOURCES=logging.cpp test_tools.h -logging_LDADD=-lboost_unit_test_framework -lboost_regex $(lib_common) - -TESTS+=Url -check_PROGRAMS+=Url -Url_SOURCES=Url.cpp test_tools.h -Url_LDADD=-lboost_unit_test_framework $(lib_common) - -TESTS+=Uuid -check_PROGRAMS+=Uuid -Uuid_SOURCES=Uuid.cpp test_tools.h -Uuid_LDADD=-lboost_unit_test_framework $(lib_common) +TESTS+=unit_test +check_PROGRAMS+=unit_test +unit_test_LDADD=-lboost_unit_test_framework -lboost_regex $(lib_common) +unit_test_SOURCES= unit_test.cpp \ + RefCounted.cpp SessionState.cpp Blob.cpp logging.cpp Url.cpp Uuid.cpp \ + Shlib.cpp FieldValue.cpp FieldTable.cpp check_LTLIBRARIES += libshlibtest.la libshlibtest_la_LDFLAGS = -module -rpath $(abs_builddir) libshlibtest_la_SOURCES = shlibtest.cpp -TESTS+=Shlib -check_PROGRAMS+=Shlib -Shlib_SOURCES=Shlib.cpp -Shlib_LDADD=-lboost_unit_test_framework $(lib_common) - -TESTS+=FieldValue -check_PROGRAMS+=FieldValue -FieldValue_SOURCES=FieldValue.cpp -FieldValue_LDADD=-lboost_unit_test_framework $(lib_common) - -TESTS+=FieldTable -check_PROGRAMS+=FieldTable -FieldTable_SOURCES=FieldTable.cpp -FieldTable_LDADD=-lboost_unit_test_framework $(lib_common) - -# TODO aconway 2007-08-07: Why aren't these tests run automatically? - -check_PROGRAMS+=ConcurrentQueue -ConcurrentQueue_SOURCES=ConcurrentQueue.cpp -ConcurrentQueue_LDADD=-lboost_test_exec_monitor $(lib_common) - -check_PROGRAMS+=Serializer -Serializer_SOURCES=Serializer.cpp -Serializer_LDADD=-lboost_unit_test_framework $(lib_common) - include cluster.mk # @@ -135,21 +96,21 @@ testprogs= \ check_PROGRAMS += $(testprogs) interop_runner -TESTS_ENVIRONMENT = VALGRIND=$(VALGRIND) srcdir=$(srcdir) $(srcdir)/run_test +TESTS_ENVIRONMENT = VALGRIND=$(VALGRIND) srcdir=$(srcdir) BOOST_TEST_SHOW_PROGRESS=yes $(srcdir)/run_test system_tests = client_test exception_test quick_perftest quick_topictest TESTS += run-unit-tests start_broker $(system_tests) python_tests stop_broker EXTRA_DIST += \ - test_env run_test vg_check \ + run_test vg_check \ run-unit-tests start_broker python_tests stop_broker \ quick_topictest \ quick_perftest \ topictest \ - .valgrind.supp-default \ - .valgrindrc-default \ + .valgrind.supp \ + .valgrindrc \ InProcessBroker.h \ - MessageUtils.h \ + MessageUtils.h \ MockChannel.h \ MockConnectionInputHandler.h \ TxMocks.h \ @@ -182,16 +143,7 @@ gen.mk: Makefile.am check-unit: $(MAKE) check TESTS=$(UNIT_TESTS) run-unit-tests -# Make sure valgrind files are generated. -all-am: .valgrind.supp .valgrindrc - -# Create a copy so that can be modified without risk of committing the changes. -.valgrindrc: .valgrindrc-default - cp $^ $@ -.valgrind.supp: .valgrind.supp-default - cp $^ $@ - -CLEANFILES+=valgrind.out *.log *.vglog .valgrindrc .valgrind.supp dummy_test $(unit_wrappers) +CLEANFILES+=valgrind.out *.log *.vglog dummy_test $(unit_wrappers) MAINTAINERCLEANFILES=gen.mk interop_runner_SOURCES = \ diff --git a/qpid/cpp/src/tests/RefCounted.cpp b/qpid/cpp/src/tests/RefCounted.cpp new file mode 100644 index 0000000000..1d453aedd1 --- /dev/null +++ b/qpid/cpp/src/tests/RefCounted.cpp @@ -0,0 +1,72 @@ +/* + * + * 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 "qpid/RefCounted.h" + +#include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(RefCounted); + +using namespace std; +using namespace qpid; + +struct DummyCounted : public AbstractRefCounted { + DummyCounted() : count(0) {} + mutable int count; + virtual void addRef() const { count++; } + virtual void release() const { count--; } +}; + +BOOST_AUTO_TEST_CASE(testIntrusivePtr) { + DummyCounted dummy; + BOOST_CHECK_EQUAL(0, dummy.count); + { + intrusive_ptr<DummyCounted> p(&dummy); + BOOST_CHECK_EQUAL(1, dummy.count); + { + intrusive_ptr<DummyCounted> q(p); + BOOST_CHECK_EQUAL(2, dummy.count); + intrusive_ptr<DummyCounted> r; + r=q; + BOOST_CHECK_EQUAL(3, dummy.count); + } + BOOST_CHECK_EQUAL(1, dummy.count); + } + BOOST_CHECK_EQUAL(0, dummy.count); +} + +struct CountMe : public RefCounted { + static int instances; + CountMe() { ++instances; } + ~CountMe() { --instances; } +}; + +int CountMe::instances=0; + +BOOST_AUTO_TEST_CASE(testRefCounted) { + BOOST_CHECK_EQUAL(0, CountMe::instances); + intrusive_ptr<CountMe> p(new CountMe()); + BOOST_CHECK_EQUAL(1, CountMe::instances); + intrusive_ptr<CountMe> q(p); + BOOST_CHECK_EQUAL(1, CountMe::instances); + q=0; + BOOST_CHECK_EQUAL(1, CountMe::instances); + p=0; + BOOST_CHECK_EQUAL(0, CountMe::instances); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Serializer.cpp b/qpid/cpp/src/tests/Serializer.cpp index 0135822275..0d52eef711 100644 --- a/qpid/cpp/src/tests/Serializer.cpp +++ b/qpid/cpp/src/tests/Serializer.cpp @@ -24,10 +24,10 @@ #include "qpid/sys/Mutex.h" #include "qpid/sys/Serializer.h" -#define BOOST_AUTO_TEST_MAIN -#include <boost/test/auto_unit_test.hpp> #include <boost/bind.hpp> #include <boost/utility/value_init.hpp> +#include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Serializer); #include <set> @@ -151,3 +151,5 @@ BOOST_AUTO_TEST_CASE(testExternalDispatch) { BOOST_CHECK_EQUAL(100u, tester.count); BOOST_CHECK(Thread::logId() != *tester.threads.begin()); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/SessionState.cpp b/qpid/cpp/src/tests/SessionState.cpp index 19a146c759..f021861cd4 100644 --- a/qpid/cpp/src/tests/SessionState.cpp +++ b/qpid/cpp/src/tests/SessionState.cpp @@ -18,9 +18,9 @@ #include "qpid/framing/SessionState.h" -#define BOOST_AUTO_TEST_MAIN -#include <boost/test/auto_unit_test.hpp> #include <boost/bind.hpp> +#include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(SessionState); using namespace std; using namespace qpid::framing; @@ -97,16 +97,21 @@ BOOST_AUTO_TEST_CASE(testReplay) { // Replay of all frames. SessionState session(100); sent(session, "abc"); + session.suspend(); session.resuming(); session.receivedAck(-1); BOOST_CHECK_EQUAL(replayChars(session.replay()), "abc"); // Replay with acks session.receivedAck(0); // ack a. + session.suspend(); + session.resuming(); session.receivedAck(1); // ack b. BOOST_CHECK_EQUAL(replayChars(session.replay()), "c"); // Replay after further frames. sent(session, "def"); + session.suspend(); + session.resuming(); session.receivedAck(3); BOOST_CHECK_EQUAL(replayChars(session.replay()), "ef"); @@ -135,3 +140,5 @@ BOOST_AUTO_TEST_CASE(testReceived) { BOOST_CHECK(!s3.received(f)); BOOST_CHECK_EQUAL(5u, *s3.received(f)); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Shlib.cpp b/qpid/cpp/src/tests/Shlib.cpp index 6420af915e..f394f7c795 100644 --- a/qpid/cpp/src/tests/Shlib.cpp +++ b/qpid/cpp/src/tests/Shlib.cpp @@ -22,8 +22,8 @@ #include "qpid/sys/Shlib.h" #include "qpid/Exception.h" -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Shlib); using namespace qpid::sys; typedef void (*CallMe)(int*); @@ -55,3 +55,5 @@ BOOST_AUTO_TEST_CASE(testAutoShlib) { BOOST_CHECK_EQUAL(42, unloaded); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Url.cpp b/qpid/cpp/src/tests/Url.cpp index faf802ba1e..a1ce2b8cf5 100644 --- a/qpid/cpp/src/tests/Url.cpp +++ b/qpid/cpp/src/tests/Url.cpp @@ -16,7 +16,7 @@ * */ -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> + #include <boost/test/auto_unit_test.hpp> #include "test_tools.h" #include "qpid/Url.h" @@ -26,6 +26,8 @@ using namespace std; using namespace qpid; using namespace boost::assign; +BOOST_AUTO_TEST_SUITE(Url); + BOOST_AUTO_TEST_CASE(testUrl_str) { Url url; url.push_back(TcpAddress("foo.com")); @@ -59,4 +61,4 @@ BOOST_AUTO_TEST_CASE(testUrl_parse) { } - +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/Uuid.cpp b/qpid/cpp/src/tests/Uuid.cpp index db9a012a3d..6926077d30 100644 --- a/qpid/cpp/src/tests/Uuid.cpp +++ b/qpid/cpp/src/tests/Uuid.cpp @@ -19,8 +19,8 @@ #include "qpid/framing/Uuid.h" #include "qpid/framing/Buffer.h" -#define BOOST_AUTO_TEST_MAIN #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(Uuid); #include <set> @@ -73,3 +73,5 @@ BOOST_AUTO_TEST_CASE(testUuidEncodeDecode) { BOOST_CHECK_EQUAL(string(sample.begin(), sample.end()), string(decoded.begin(), decoded.end())); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/cluster_client.cpp b/qpid/cpp/src/tests/cluster_client.cpp index 7620faa9fa..d3ce25540d 100644 --- a/qpid/cpp/src/tests/cluster_client.cpp +++ b/qpid/cpp/src/tests/cluster_client.cpp @@ -19,13 +19,14 @@ #include "qpid/client/Connection.h" #include "qpid/shared_ptr.h" -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> #include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(cluster_client); #include <fstream> #include <vector> #include <functional> + using namespace std; using namespace qpid; using namespace qpid::client; @@ -77,6 +78,4 @@ BOOST_AUTO_TEST_CASE(testWiringReplication) { } } - - - +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/logging.cpp b/qpid/cpp/src/tests/logging.cpp index 1042e60077..a4e131ec57 100644 --- a/qpid/cpp/src/tests/logging.cpp +++ b/qpid/cpp/src/tests/logging.cpp @@ -16,18 +16,21 @@ * */ -#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> -#include <boost/test/auto_unit_test.hpp> + #include "test_tools.h" #include "qpid/log/Logger.h" #include "qpid/log/Options.h" #include "qpid/memory.h" #include "qpid/Options.h" + #include <boost/test/floating_point_comparison.hpp> #include <boost/format.hpp> +#include <boost/test/auto_unit_test.hpp> +BOOST_AUTO_TEST_SUITE(logging); + #include <exception> -#include <time.h> #include <fstream> +#include <time.h> using namespace std; @@ -366,3 +369,5 @@ BOOST_AUTO_TEST_CASE(testLoggerConfigure) { log.close(); unlink("logging.tmp"); } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/qpid/cpp/src/tests/quick_perftest b/qpid/cpp/src/tests/quick_perftest index cbafc57872..085d2b2e81 100755 --- a/qpid/cpp/src/tests/quick_perftest +++ b/qpid/cpp/src/tests/quick_perftest @@ -1,2 +1,2 @@ #!/bin/sh -exec `dirname $0`/test_env ./perftest --listen --publish --count 1000 +exec `dirname $0`/run_test ./perftest --listen --publish --count 1000 diff --git a/qpid/cpp/src/tests/run_test b/qpid/cpp/src/tests/run_test index 615e8132f1..0f59509dab 100755 --- a/qpid/cpp/src/tests/run_test +++ b/qpid/cpp/src/tests/run_test @@ -21,18 +21,20 @@ export VALGRIND srcdir # Export QPID_PORT if qpidd.port exists. test -f qpidd.port && export QPID_PORT=`cat qpidd.port` +# Avoid silly libtool error messages if these are not defined +test -z "$LC_ALL" && export LC_ALL= +test -z "$LC_CTYPE" && export LC_CTYPE= +test -z "$LC_COLLATE" && export LC_COLLATE= +test -z "$LC_MESSAGES" && export LC_MESSAGES= + VG_LOG="$1.vglog" -TEST_LOG="$1.log" -rm -f $VG_LOG $TEST_LOG +rm -f $VG_LOG if grep -l "^# Generated by .*libtool" "$1" >/dev/null 2>&1; then # This is a libtool "executable". Valgrind it if VALGRIND specified. test -n "$VALGRIND" && VALGRIND="$VALGRIND --log-file-exactly=$VG_LOG --" # Hide output unless there's an error. - libtool --mode=execute $VALGRIND "$@" >$TEST_LOG 2>&1 || { - ERROR=$? - cat $TEST_LOG - } + libtool --mode=execute $VALGRIND "$@" 2>&1 || ERROR=$? test -n "$VALGRIND" && vg_check else # This is a non-libtool shell script, just execute it. @@ -42,7 +44,7 @@ fi if test -z "$ERROR"; then # Clean up logs if there was no error. - rm -f $VG_LOG $TEST_LOG + rm -f $VG_LOG exit 0 else exit $ERROR diff --git a/qpid/cpp/src/tests/test_env b/qpid/cpp/src/tests/test_env deleted file mode 100755 index 3fdfaa8a88..0000000000 --- a/qpid/cpp/src/tests/test_env +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# -# Run a test under valgrind. -# - -# Use VALGRIND if set, else look on path. -test -z "$VALGRIND" && VALGRIND=`which valgrind 2>/dev/null` -# No valgrind, just run the command -test -z "$VALGRIND" && { exec libtool --mode=execute "$@"; exit $?; } - -test "$VERBOSE" = yes && set -x -test -z "$vg_log" && vg_log=valgrind.out -rm -f $vg_log - -# Dump log file, print a message and exit non-0. -vg_failed() { - cat $vg_log 1>&2 - echo $1 1>&2 - exit 1 -} - -# Check for errors in valgrind output. -vg_check() -{ - # Ensure there is an ERROR SUMMARY line. - grep -E '^==[0-9]+== ERROR SUMMARY:' $vg_log > /dev/null || \ - vg_failed "No valgrind ERROR SUMMARY line in $$vg_failed." - # Ensure that the number of errors is 0. - grep -E '^==[0-9]+== ERROR SUMMARY: [^0] ' $vg_log > /dev/null && \ - vg_failed "Valgrind reported errors in $vg_out; see above." - # Check for leaks. - grep -E '^==[0-9]+== +.* lost: [^0]' $vg_log && \ - vg_failed "Found memory leaks (see log file, $vg_log); see above." - true -} - -# Output to file, only display if there is an error. -opts=--log-file-exactly=$vg_log - -libtool --mode=execute $VALGRIND $opts -- "$@" || fail=1 -vg_check && test -z "$fail" diff --git a/qpid/cpp/src/tests/unit_test.cpp b/qpid/cpp/src/tests/unit_test.cpp new file mode 100644 index 0000000000..aed6f6a4af --- /dev/null +++ b/qpid/cpp/src/tests/unit_test.cpp @@ -0,0 +1,22 @@ +/* + * + * 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. + * + */ + +#define BOOST_AUTO_TEST_MAIN // Must come before #include<boost/test/*> +#include <boost/test/auto_unit_test.hpp> + +// Defines test_main function to link with actual unit test code. |