Test cases: Enable Interrupt* test, add suspend test
This commit is contained in:
parent
e16e778f38
commit
b3296d6241
3 changed files with 207 additions and 50 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, \
|
||||
|
|
Loading…
Reference in a new issue