summaryrefslogtreecommitdiff
path: root/qpid/cpp
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-11-01 00:38:58 +0000
committerAlan Conway <aconway@apache.org>2007-11-01 00:38:58 +0000
commit6ff9cc1db2af388c9fe00c140f555f7c30c5df6d (patch)
tree0b8e872f26627b5ebdcc882238e9ad256785cd22 /qpid/cpp
parent04cc6a2f5225e8894b4a8173b5a6ffd59a00184d (diff)
downloadqpid-python-6ff9cc1db2af388c9fe00c140f555f7c30c5df6d.tar.gz
Preparation for session thread safety overhaul:
- simplified SessionState, responsibility for protocol states now in Handlers - qpid::RefCounted, qpid::intrusive_ptr reference counting support. - build boost unit tests as single exe, speeds up testing. - fixed leak in AsynchIOAcceptor.cpp git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@590869 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp')
-rw-r--r--qpid/cpp/src/Makefile.am1
-rw-r--r--qpid/cpp/src/qpid/RefCounted.h73
-rw-r--r--qpid/cpp/src/qpid/broker/SessionHandler.cpp9
-rw-r--r--qpid/cpp/src/qpid/broker/SessionHandler.h1
-rw-r--r--qpid/cpp/src/qpid/broker/SessionManager.cpp1
-rw-r--r--qpid/cpp/src/qpid/client/SessionCore.cpp4
-rw-r--r--qpid/cpp/src/qpid/framing/SessionState.cpp21
-rw-r--r--qpid/cpp/src/qpid/framing/SessionState.h25
-rw-r--r--qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp2
-rw-r--r--qpid/cpp/src/qpid/sys/AtomicCount.h2
-rw-r--r--qpid/cpp/src/tests/.valgrind.supp (renamed from qpid/cpp/src/tests/.valgrind.supp-default)10
-rw-r--r--qpid/cpp/src/tests/.valgrindrc (renamed from qpid/cpp/src/tests/.valgrindrc-default)0
-rw-r--r--qpid/cpp/src/tests/Blob.cpp5
-rw-r--r--qpid/cpp/src/tests/Cluster.cpp4
-rw-r--r--qpid/cpp/src/tests/Cpg.cpp9
-rw-r--r--qpid/cpp/src/tests/FieldTable.cpp5
-rw-r--r--qpid/cpp/src/tests/FieldValue.cpp3
-rw-r--r--qpid/cpp/src/tests/Frame.cpp6
-rw-r--r--qpid/cpp/src/tests/Makefile.am82
-rw-r--r--qpid/cpp/src/tests/RefCounted.cpp72
-rw-r--r--qpid/cpp/src/tests/Serializer.cpp6
-rw-r--r--qpid/cpp/src/tests/SessionState.cpp11
-rw-r--r--qpid/cpp/src/tests/Shlib.cpp4
-rw-r--r--qpid/cpp/src/tests/Url.cpp6
-rw-r--r--qpid/cpp/src/tests/Uuid.cpp4
-rw-r--r--qpid/cpp/src/tests/cluster_client.cpp7
-rw-r--r--qpid/cpp/src/tests/logging.cpp11
-rwxr-xr-xqpid/cpp/src/tests/quick_perftest2
-rwxr-xr-xqpid/cpp/src/tests/run_test16
-rwxr-xr-xqpid/cpp/src/tests/test_env41
-rw-r--r--qpid/cpp/src/tests/unit_test.cpp22
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.