Test cases: Enable Interrupt* test, add suspend test

This commit is contained in:
Chen Congwu 2009-06-26 14:01:02 +08:00 committed by Patrick Ohly
parent e16e778f38
commit b3296d6241
3 changed files with 207 additions and 50 deletions

View file

@ -338,8 +338,7 @@ public:
EvolutionSyncClient(server, false, activeSources),
m_logbase(logbase),
m_options(options),
m_started(false),
m_aborted(false)
m_started(false)
{}
protected:
@ -363,18 +362,29 @@ public:
if (!m_started) {
m_started = true;
if (m_options.m_startCallback(*this, m_options)) {
m_aborted = true;
m_options.m_isAborted = true;
}
}
}
virtual bool checkForAbort() { return m_aborted; }
virtual bool checkForAbort() { return m_options.m_isAborted; }
virtual bool checkForSuspend() {return m_options.m_isSuspended;}
virtual boost::shared_ptr<TransportAgent> createTransportAgent()
{
boost::shared_ptr<TransportAgent>wrapper = m_options.m_transport;
boost::shared_ptr<TransportAgent>agent =EvolutionSyncClient::createTransportAgent();
if (!wrapper.get())
return agent;
dynamic_cast<TransportWrapper*>(wrapper.get())->setAgent(agent);
dynamic_cast<TransportWrapper*>(wrapper.get())->setSyncOptions(&m_options);
return wrapper;
}
private:
const string m_logbase;
SyncOptions m_options;
bool m_started;
bool m_aborted;
} client(server, activeSources, logbase, options);
SyncReport report;

View file

@ -1676,9 +1676,7 @@ void SyncTests::addTests() {
}
}
// TODO: enable interrupted sync tests again
if (false &&
config.retrySync &&
if (config.retrySync &&
config.insertItem &&
config.updateItem &&
accessClientB &&
@ -1694,6 +1692,24 @@ void SyncTests::addTests() {
ADD_TEST_TO_SUITE(retryTests, SyncTests, testInterruptResumeFull);
addTest(retryTests);
}
if (config.retrySync &&
config.insertItem &&
config.updateItem &&
accessClientB &&
config.dump &&
config.compare) {
CppUnit::TestSuite *suspendTests = new CppUnit::TestSuite(getName() + "::Suspend");
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendClientAdd);
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendClientRemove);
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendClientUpdate);
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendServerAdd);
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendServerRemove);
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendServerUpdate);
ADD_TEST_TO_SUITE(suspendTests, SyncTests, testUserSuspendFull);
addTest(suspendTests);
}
}
}
@ -2663,29 +2679,15 @@ void SyncTests::doVarSizes(bool withMaxMsgSize,
compareDatabases();
}
// TODO: this class needs to be used by TestClient::sync() to interrupt message transmission
class TransportFaultInjector : public TransportAgent {
int m_interruptAtMessage, m_messageCount;
TransportAgent *m_wrappedAgent;
Status m_status;
class TransportFaultInjector : public TransportWrapper{
public:
TransportFaultInjector(int interruptAtMessage) {
m_messageCount = 0;
m_interruptAtMessage = interruptAtMessage;
m_wrappedAgent = NULL;
m_status = INACTIVE;
TransportFaultInjector()
:TransportWrapper() {
}
~TransportFaultInjector() {
}
int getMessageCount() { return m_messageCount; }
virtual void setURL(const std::string &url) { m_wrappedAgent->setURL(url); }
virtual void setProxy(const std::string &proxy) { m_wrappedAgent->setProxy(proxy); }
virtual void setProxyAuth(const std::string &user,
const std::string &password) { m_wrappedAgent->setProxyAuth(user, password); }
virtual void setContentType(const std::string &type) { m_wrappedAgent->setContentType(type); }
virtual void setUserAgent(const::string &agent) { m_wrappedAgent->setUserAgent(agent); }
virtual void send(const char *data, size_t len)
{
if (m_interruptAtMessage == m_messageCount) {
@ -2696,9 +2698,6 @@ public:
m_messageCount > m_interruptAtMessage) {
throw string("TransportFaultInjector: interrupt before send");
}
if (m_interruptAtMessage == m_messageCount) {
// TODO: force message receive error m_wrappedAgent->setMaxMsgSize(1);
}
m_wrappedAgent->send(data, len);
@ -2714,8 +2713,6 @@ public:
}
}
virtual void cancel() { m_wrappedAgent->cancel(); }
virtual Status wait() { return m_status; }
virtual void getReply(const char *&data, size_t &len, std::string &contentType) {
if (m_status == FAILED) {
data = "";
@ -2726,6 +2723,43 @@ public:
}
};
/**
* Emulates a user suspend just after receving response
* from server.
*/
class UserSuspendInjector : public TransportWrapper{
public:
UserSuspendInjector()
:TransportWrapper() {
}
~UserSuspendInjector() {
}
virtual void send(const char *data, size_t len)
{
m_wrappedAgent->send(data, len);
m_status = m_wrappedAgent->wait();
}
virtual void getReply(const char *&data, size_t &len, std::string &contentType) {
if (m_status == FAILED) {
data = "";
len = 0;
} else {
if (m_interruptAtMessage == m_messageCount) {
SE_LOG_DEBUG(NULL, NULL, "UserSuspendInjector: user suspend after getting reply #%d", m_messageCount);
}
m_messageCount++;
if (m_interruptAtMessage >= 0 &&
m_messageCount > m_interruptAtMessage) {
m_options->m_isSuspended = true;
}
m_wrappedAgent->getReply(data, len, contentType);
}
}
};
/**
* This function covers different error scenarios that can occur
* during real synchronization. To pass, clients must either force a
@ -2774,11 +2808,14 @@ public:
* >= 0 to execute one uninterrupted run and then interrupt at that
* message.
*/
void SyncTests::doInterruptResume(int changes)
void SyncTests::doInterruptResume(int changes,
boost::shared_ptr<TransportWrapper> wrapper)
{
int interruptAtMessage = -1;
const char *t = getenv("CLIENT_TEST_INTERRUPT_AT");
int requestedInterruptAt = t ? atoi(t) : -1;
const char *s = getenv("CLIENT_TEST_INTERRUPT_SLEEP");
int sleep_t = s ? atoi(s) : 0;
size_t i;
std::string refFileBase = getCurrentTest() + ".ref.";
bool equal = true;
@ -2859,18 +2896,18 @@ void SyncTests::doInterruptResume(int changes)
}
// Now do an interrupted sync between B and server.
// The wrapper is a factory and the created transport
// all in one class, allocated on the stack. The
// explicit delete of the TransportAgent is suppressed
// The explicit delete of the TransportAgent is suppressed
// by overloading the delete operator.
int wasInterrupted;
{
TransportFaultInjector faultInjector(interruptAtMessage);
wrapper->reset();
wrapper->setInterruptAtMessage(interruptAtMessage);
accessClientB->doSync("changesFromB",
SyncOptions(SYNC_TWO_WAY,
CheckSyncReport(-1, -1, -1, -1, -1, -1, false)));
CheckSyncReport(-1, -1, -1, -1,
-1, -1, false)).setTransportAgent(wrapper));
wasInterrupted = interruptAtMessage != -1 &&
faultInjector.getMessageCount() <= interruptAtMessage;
wrapper->getMessageCount() <= interruptAtMessage;
}
if (interruptAtMessage != -1) {
@ -2879,7 +2916,9 @@ void SyncTests::doInterruptResume(int changes)
break;
}
// continue
// continue, wait until server timeout
if(sleep_t)
sleep (sleep_t);
accessClientB->doSync("retryB", SyncOptions(SYNC_TWO_WAY));
}
@ -2938,40 +2977,77 @@ void SyncTests::doInterruptResume(int changes)
void SyncTests::testInterruptResumeClientAdd()
{
doInterruptResume(CLIENT_ADD);
doInterruptResume(CLIENT_ADD, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testInterruptResumeClientRemove()
{
doInterruptResume(CLIENT_REMOVE);
doInterruptResume(CLIENT_REMOVE, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testInterruptResumeClientUpdate()
{
doInterruptResume(CLIENT_UPDATE);
doInterruptResume(CLIENT_UPDATE, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testInterruptResumeServerAdd()
{
doInterruptResume(SERVER_ADD);
doInterruptResume(SERVER_ADD, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testInterruptResumeServerRemove()
{
doInterruptResume(SERVER_REMOVE);
doInterruptResume(SERVER_REMOVE, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testInterruptResumeServerUpdate()
{
doInterruptResume(SERVER_UPDATE);
doInterruptResume(SERVER_UPDATE, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testInterruptResumeFull()
{
doInterruptResume(CLIENT_ADD|CLIENT_REMOVE|CLIENT_UPDATE|
SERVER_ADD|SERVER_REMOVE|SERVER_UPDATE);
SERVER_ADD|SERVER_REMOVE|SERVER_UPDATE, boost::shared_ptr<TransportWrapper> (new TransportFaultInjector()));
}
void SyncTests::testUserSuspendClientAdd()
{
doInterruptResume(CLIENT_ADD, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::testUserSuspendClientRemove()
{
doInterruptResume(CLIENT_REMOVE, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::testUserSuspendClientUpdate()
{
doInterruptResume(CLIENT_UPDATE, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::testUserSuspendServerAdd()
{
doInterruptResume(SERVER_ADD, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::testUserSuspendServerRemove()
{
doInterruptResume(SERVER_REMOVE, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::testUserSuspendServerUpdate()
{
doInterruptResume(SERVER_UPDATE, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::testUserSuspendFull()
{
doInterruptResume(CLIENT_ADD|CLIENT_REMOVE|CLIENT_UPDATE|
SERVER_ADD|SERVER_REMOVE|SERVER_UPDATE, boost::shared_ptr<TransportWrapper> (new UserSuspendInjector()));
}
void SyncTests::doSync(const SyncOptions &options)
{
int res = 0;

View file

@ -27,12 +27,15 @@
#include <list>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
class EvolutionSyncClient;
class EvolutionSyncSource;
class TransportWrapper;
typedef EvolutionSyncSource SyncSource;
#include <SyncML.h>
#include <TransportAgent.h>
#ifdef ENABLE_INTEGRATION_TESTS
@ -93,6 +96,7 @@ struct SyncOptions {
* beware, the later may throw exceptions inside CPPUNIT macros
*/
CheckSyncReport m_checkReport;
/** maximum message size supported by client */
long m_maxMsgSize;
/** maximum object size supported by client */
@ -102,6 +106,10 @@ struct SyncOptions {
/** enabled WBXML (default) */
bool m_isWBXML;
bool m_isSuspended;
bool m_isAborted;
typedef boost::function<bool (EvolutionSyncClient &,
SyncOptions &)> Callback_t;
/**
@ -110,21 +118,28 @@ struct SyncOptions {
* error and return true to stop sync without error.
*/
Callback_t m_startCallback;
boost::shared_ptr<SyncEvolution::TransportAgent> m_transport;
SyncOptions(SyncMode syncMode = SYNC_NONE,
const CheckSyncReport &checkReport = CheckSyncReport(),
long maxMsgSize = 128 * 1024, // 128KB = large enough that normal tests should run with a minimal number of messages
long maxObjSize = 1 * 1024 * 1024 * 1024, // 1GB = basically unlimited...
bool loSupport = false,
bool isWBXML = defaultWBXML(),
Callback_t startCallback = EmptyCallback) :
Callback_t startCallback = EmptyCallback,
boost::shared_ptr<SyncEvolution::TransportAgent> transport =
boost::shared_ptr<SyncEvolution::TransportAgent>()) :
m_syncMode(syncMode),
m_checkReport(checkReport),
m_maxMsgSize(maxMsgSize),
m_maxObjSize(maxObjSize),
m_loSupport(loSupport),
m_isWBXML(isWBXML),
m_startCallback(startCallback)
m_isSuspended(false),
m_isAborted(false),
m_startCallback(startCallback),
m_transport (transport)
{}
SyncOptions &setSyncMode(SyncMode syncMode) { m_syncMode = syncMode; return *this; }
@ -134,6 +149,8 @@ struct SyncOptions {
SyncOptions &setLOSupport(bool loSupport) { m_loSupport = loSupport; return *this; }
SyncOptions &setWBXML(bool isWBXML) { m_isWBXML = isWBXML; return *this; }
SyncOptions &setStartCallback(const Callback_t &callback) { m_startCallback = callback; return *this; }
SyncOptions &setTransportAgent(const boost::shared_ptr<SyncEvolution::TransportAgent> transport)
{m_transport = transport; return *this;}
static bool EmptyCallback(EvolutionSyncClient &,
SyncOptions &) { return false; }
@ -882,7 +899,8 @@ protected:
virtual void testManyItems();
virtual void doInterruptResume(int changes);
virtual void doInterruptResume(int changes,
boost::shared_ptr<TransportWrapper> wrapper);
enum {
CLIENT_ADD = (1<<0),
CLIENT_REMOVE = (1<<1),
@ -899,6 +917,15 @@ protected:
virtual void testInterruptResumeServerUpdate();
virtual void testInterruptResumeFull();
virtual void testUserSuspendClientAdd();
virtual void testUserSuspendClientRemove();
virtual void testUserSuspendClientUpdate();
virtual void testUserSuspendServerAdd();
virtual void testUserSuspendServerRemove();
virtual void testUserSuspendServerUpdate();
virtual void testUserSuspendFull();
/**
* implements testMaxMsg(), testLargeObject(), testLargeObjectEncoded()
* using a sequence of items with varying sizes
@ -918,6 +945,50 @@ protected:
}
};
/*
* A transport wraper wraps a real transport impl and gives user
* possibility to do additional work before/after transport operation.
* We use TransportFaultInjector to emulate a network failure;
* We use UserSuspendInjector to emulate a user suspend after receving
* a response.
*/
class TransportWrapper : public SyncEvolution::TransportAgent {
protected:
int m_interruptAtMessage, m_messageCount;
boost::shared_ptr<SyncEvolution::TransportAgent> m_wrappedAgent;
Status m_status;
SyncOptions *m_options;
public:
TransportWrapper() {
m_messageCount = 0;
m_interruptAtMessage = -1;
m_wrappedAgent = boost::shared_ptr<SyncEvolution::TransportAgent>();
m_status = INACTIVE;
m_options = NULL;
}
~TransportWrapper() {
}
virtual int getMessageCount() { return m_messageCount; }
virtual void setURL(const std::string &url) { m_wrappedAgent->setURL(url); }
virtual void setProxy(const std::string &proxy) { m_wrappedAgent->setProxy(proxy); }
virtual void setProxyAuth(const std::string &user,
const std::string &password) { m_wrappedAgent->setProxyAuth(user, password); }
virtual void setContentType(const std::string &type) { m_wrappedAgent->setContentType(type); }
virtual void setUserAgent(const::string &agent) { m_wrappedAgent->setUserAgent(agent); }
virtual void setAgent(boost::shared_ptr<SyncEvolution::TransportAgent> agent) {m_wrappedAgent = agent;}
virtual void setSyncOptions(SyncOptions *options) {m_options = options;}
virtual void setInterruptAtMessage (int interrupt) {m_interruptAtMessage = interrupt;}
virtual void cancel() { m_wrappedAgent->cancel(); }
virtual void reset() {
m_messageCount = 0;
m_interruptAtMessage = -1;
m_status = INACTIVE;
m_options = NULL;
}
virtual Status wait() { return m_status; }
};
/** assert equality, include string in message if unequal */
#define CLIENT_TEST_EQUAL( _prefix, \