📄 clienttest.h
字号:
* Returning true enables tests which only work if the server is
* a Funambol server which supports the "b64" encoding of items
* on the transport level.
*/
virtual bool isB64Enabled() = 0;
/**
* Execute a synchronization with the selected sync sources
* and the selected synchronization options. The log file
* in LOG has been set up already for the synchronization run
* and should not be changed by the client.
*
* @param activeSources a -1 terminated array of sync source indices
* @param syncMode the synchronization mode to be used
* @param checkReport has to be called after a successful or unsuccessful sync,
* will dump the report and (optionally) check the result;
* beware, the later may throw exceptions inside CPPUNIT macros
* @param maxMsgSize >0: enable the maximum message size, else disable it
* @param maxObjSize same as maxMsgSize for maximum object size
* @param loSupport if TRUE, then the sync is expected to enable Large Object support
* @param encoding if non-empty, then let client library transform all items
* into this format (guaranteed to be not NULL)
*
* @return return code of SyncClient::sync()
*/
virtual int sync(
const int *activeSources,
SyncMode syncMode,
const CheckSyncReport &checkReport,
long maxMsgSize = 0,
long maxObjSize = 0,
bool loSupport = false,
const char *encoding = "") = 0;
/**
* This is called after successful sync() calls (res == 0) as well
* as after unsuccessful ones (res != 1). The default implementation
* sleeps for the number of seconds specified when constructing this
* instance and copies the server log if one was named.
*
* @param res result of sync()
* @param logname base name of the current sync log (without ".client.[AB].log" suffix)
*/
virtual void postSync(int res, const std::string &logname);
protected:
/**
* time to sleep in postSync()
*/
int serverSleepSeconds;
/**
* server log file which is copied by postSync() and then
* truncated (Unix only, Windows does not allow such access
* to an open file)
*/
std::string serverLogFileName;
private:
/**
* really a CppUnit::TestFactory, but declared as void * to avoid
* dependencies on the CPPUnit header files: created by
* registerTests() and remains valid until the client is deleted
*/
void *factory;
};
/**
* helper class to encapsulate ClientTest::Config::createsource_t
* pointer and the corresponding parameters
*/
class CreateSource {
public:
CreateSource(ClientTest::Config::createsource_t createSourceParam, ClientTest &clientParam, int sourceParam, bool isSourceAParam) :
createSource(createSourceParam),
client(clientParam),
source(sourceParam),
isSourceA(isSourceAParam) {}
SyncSource *operator() () {
CPPUNIT_ASSERT(createSource);
return createSource(client, source, isSourceA);
}
const ClientTest::Config::createsource_t createSource;
ClientTest &client;
const int source;
const bool isSourceA;
};
/**
* local test of one sync source and utility functions also used by
* sync tests
*/
class LocalTests : public CppUnit::TestSuite, public CppUnit::TestFixture {
public:
/** the client we are testing */
ClientTest &client;
/** number of the source we are testing in that client */
const int source;
/** configuration that corresponds to source */
const ClientTest::Config config;
/** helper funclets to create sources */
CreateSource createSourceA, createSourceB;
LocalTests(const std::string &name, ClientTest &cl, int sourceParam, ClientTest::Config &co) :
CppUnit::TestSuite(name),
client(cl),
source(sourceParam),
config(co),
createSourceA(co.createSourceA, cl, sourceParam, true),
createSourceB(co.createSourceB, cl, sourceParam, false)
{}
/**
* adds the supported tests to the instance itself;
* this is the function that a derived class can override
* to add additional tests
*/
virtual void addTests();
/**
* opens source and inserts the given item; can be called
* regardless whether the data source already contains items or not
*
* The type of the item is unset; it is assumed that the source
* can handle that.
*/
virtual void insert(CreateSource createSource, const char *data);
/**
* assumes that exactly one element is currently inserted and updates it with the given item
*
* The type of the item is cleared, as in insert() above.
*
* @param check if true, then reopen the source and verify that the reported items are as expected
*/
virtual void update(CreateSource createSource, const char *data, bool check = true);
/** deletes all items locally via sync source */
virtual void deleteAll(CreateSource createSource);
/**
* takes two databases, exports them,
* then compares them using synccompare
*
* @param refFile existing file with source reference items, NULL uses a dump of sync source A instead
* @param copy a sync source which contains the copied items, begin/endSync will be called
* @param raiseAssert raise assertion if comparison yields differences (defaults to true)
*/
virtual void compareDatabases(const char *refFile, SyncSource ©, bool raiseAssert = true);
/**
* insert artificial items, number of them determined by TEST_EVOLUTION_NUM_ITEMS
* unless passed explicitly
*
* @param createSource a factory for the sync source that is to be used
* @param startIndex IDs are generated starting with this value
* @param numItems number of items to be inserted if non-null, otherwise TEST_EVOLUTION_NUM_ITEMS is used
* @param size minimum size for new items
* @return number of items inserted
*/
virtual int insertManyItems(CreateSource createSource, int startIndex = 1, int numItems = 0, int size = -1);
/* for more information on the different tests see their implementation */
virtual void testOpen();
virtual void testIterateTwice();
virtual void testSimpleInsert();
virtual void testLocalDeleteAll();
virtual void testComplexInsert();
virtual void testLocalUpdate();
virtual void testChanges();
virtual void testImport();
virtual void testImportDelete();
virtual void testManyChanges();
};
enum itemType {
NEW_ITEMS,
UPDATED_ITEMS,
DELETED_ITEMS,
TOTAL_ITEMS
};
/**
* utility function which counts items of a certain kind known to the sync source
* @param source valid source ready to iterate; NULL triggers an assert
* @param itemType determines which iterator functions are used
* @return number of valid items iterated over
*/
int countItemsOfType(SyncSource *source, itemType type);
/**
* Tests synchronization with one or more sync sources enabled.
* When testing multiple sources at once only the first config
* is checked to see which tests can be executed.
*/
class SyncTests : public CppUnit::TestSuite, public CppUnit::TestFixture {
public:
/** the client we are testing */
ClientTest &client;
SyncTests(const std::string &name, ClientTest &cl, std::vector<int> sourceIndices, bool isClientA = true);
~SyncTests();
/** adds the supported tests to the instance itself */
virtual void addTests();
protected:
/** list with all local test classes for manipulating the sources and their index in the client */
std::vector< std::pair<int, LocalTests *> > sources;
typedef std::vector< std::pair<int, LocalTests *> >::iterator source_it;
/** the indices from sources, terminated by -1 (for sync()) */
int *sourceArray;
/** utility functions for second client */
SyncTests *accessClientB;
enum DeleteAllMode {
DELETE_ALL_SYNC, /**< make sure client and server are in sync,
delete locally,
sync again */
DELETE_ALL_REFRESH /**< delete locally, refresh server */
};
/** compare databases of first and second client */
virtual void compareDatabases();
/** deletes all items locally and on server */
virtual void deleteAll(DeleteAllMode mode = DELETE_ALL_SYNC);
/** get both clients in sync with empty server, then copy one item from client A to B */
virtual void doCopy();
/**
* replicate server database locally: same as SYNC_REFRESH_FROM_SERVER,
* but done with explicit local delete and then a SYNC_SLOW because some
* servers do no support SYNC_REFRESH_FROM_SERVER
*/
virtual void refreshClient();
/* for more information on the different tests see their implementation */
// do a two-way sync without additional checks
virtual void testTwoWaySync() {
sync(SYNC_TWO_WAY);
}
// do a slow sync without additional checks
virtual void testSlowSync() {
sync(SYNC_SLOW);
}
// do a refresh from server sync without additional checks
virtual void testRefreshFromServerSync() {
sync(SYNC_REFRESH_FROM_SERVER);
}
// do a refresh from client sync without additional checks
virtual void testRefreshFromClientSync() {
sync(SYNC_REFRESH_FROM_CLIENT);
}
// delete all items, locally and on server using two-way sync
virtual void testDeleteAllSync() {
deleteAll(DELETE_ALL_SYNC);
}
virtual void testDeleteAllRefresh();
virtual void testRefreshSemantic();
virtual void testRefreshStatus();
// test that a two-way sync copies an item from one address book into the other
void testCopy() {
doCopy();
compareDatabases();
}
virtual void testUpdate();
virtual void testComplexUpdate();
virtual void testDelete();
virtual void testMerge();
virtual void testTwinning();
virtual void testOneWayFromServer();
virtual void testOneWayFromClient();
virtual void testItems();
virtual void testAddUpdate();
// test copying with maxMsg and no large object support
void testMaxMsg() {
doVarSizes(true, false, NULL);
}
// test copying with maxMsg and large object support
void testLargeObject() {
doVarSizes(true, true, NULL);
}
// test copying with maxMsg and large object support using explicit "bin" encoding
void testLargeObjectBin() {
doVarSizes(true, true, "bin");
}
// test copying with maxMsg and large object support using B64 encoding
void testLargeObjectEncoded() {
doVarSizes(true, true, "b64");
}
virtual void testManyItems();
/**
* implements testMaxMsg(), testLargeObject(), testLargeObjectEncoded()
* using a sequence of items with varying sizes
*/
virtual void doVarSizes(bool withMaxMsgSize,
bool withLargeObject,
const char *encoding);
/**
* executes a sync with the given options,
* checks the result and (optionally) the sync report
*/
virtual void sync(SyncMode syncMode,
const std::string &logprefix = "",
CheckSyncReport checkReport = CheckSyncReport(),
long maxMsgSize = 0,
long maxObjSize = 0,
bool loSupport = false,
const char *encoding = "");
};
/** assert equality, include string in message if unequal */
#define CLIENT_TEST_EQUAL( _prefix, \
_expected, \
_actual ) \
CPPUNIT_ASSERT_EQUAL_MESSAGE( std::string(_prefix) + ": " + #_expected + " == " + #_actual, \
_expected, \
_actual )
/** execute _x and then check the status of the _source pointer */
#define SOURCE_ASSERT_NO_FAILURE(_source, _x) \
{ \
CPPUNIT_ASSERT_NO_THROW(_x); \
CPPUNIT_ASSERT((_source) && (!(_source)->getReport() || (_source)->getReport()->getState() != SOURCE_ERROR)); \
}
/** check _x for true and then the status of the _source pointer */
#define SOURCE_ASSERT(_source, _x) \
{ \
CPPUNIT_ASSERT(_x); \
CPPUNIT_ASSERT((_source) && (!(_source)->getReport() || (_source)->getReport()->getState() != SOURCE_ERROR)); \
}
/** check that _x evaluates to a specific value and then the status of the _source pointer */
#define SOURCE_ASSERT_EQUAL(_source, _value, _x) \
{ \
CPPUNIT_ASSERT_EQUAL(_value, _x); \
CPPUNIT_ASSERT((_source) && (!(_source)->getReport() || (_source)->getReport()->getState() != SOURCE_ERROR)); \
}
/** same as SOURCE_ASSERT() with a specific failure message */
#define SOURCE_ASSERT_MESSAGE(_message, _source, _x) \
{ \
CPPUNIT_ASSERT_MESSAGE((_message), (_x)); \
CPPUNIT_ASSERT((_source) && (!(_source)->getReport() || (_source)->getReport()->getState() != SOURCE_ERROR)); \
}
/**
* convenience macro for adding a test name like a function,
* to be used inside addTests() of an instance of that class
*
* @param _class class which contains the function
* @param _function a function without parameters in that class
*/
#define ADD_TEST(_class, _function) \
addTest(new CppUnit::TestCaller<_class>(getName() + "::" #_function, &_class::_function, *this))
#endif // ENABLE_INTEGRATION_TESTS
/** @} */
/** @endcond */
#endif // INCL_TESTSYNCCLIENT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -