2 * Copyright (C) 2008 Funambol, Inc.
3 * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
4 * Copyright (C) 2009 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) version 3.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #ifndef INCL_TESTSYNCCLIENT
23 #define INCL_TESTSYNCCLIENT
29 #include <boost/function.hpp>
30 #include <boost/shared_ptr.hpp>
32 class EvolutionSyncClient;
33 class EvolutionSyncSource;
34 class TransportWrapper;
35 typedef EvolutionSyncSource SyncSource;
38 #include <TransportAgent.h>
42 #ifdef ENABLE_INTEGRATION_TESTS
44 #include <cppunit/TestSuite.h>
45 #include <cppunit/TestAssert.h>
46 #include <cppunit/TestFixture.h>
49 * This class encapsulates logging and checking of a SyncReport.
50 * When constructed with default parameters, no checking will be done.
51 * Otherwise the sync report has to contain exactly the expected result.
52 * When multiple sync sources are active, @b all of them have to behave
53 * alike (which is how the tests are constructed).
55 * No item is ever supposed to fail.
57 class CheckSyncReport {
59 CheckSyncReport(int clAdded = -1, int clUpdated = -1, int clDeleted = -1,
60 int srAdded = -1, int srUpdated = -1, int srDeleted = -1,
61 bool mstSucceed = true, SyncMode mode = SYNC_NONE) :
63 clientUpdated(clUpdated),
64 clientDeleted(clDeleted),
66 serverUpdated(srUpdated),
67 serverDeleted(srDeleted),
68 mustSucceed(mstSucceed),
72 virtual ~CheckSyncReport() {}
74 int clientAdded, clientUpdated, clientDeleted,
75 serverAdded, serverUpdated, serverDeleted;
80 * checks that the sync completed as expected and throws
81 * CPPUnit exceptions if something is wrong
83 * @param res return code from SyncClient::sync()
84 * @param report the sync report stored in the SyncClient
86 virtual void check(SyncMLStatus status, SyncReport &report) const;
90 * parameters for running a sync
93 /** sync mode chosen by client */
96 * has to be called after a successful or unsuccessful sync,
97 * will dump the report and (optionally) check the result;
98 * beware, the later may throw exceptions inside CPPUNIT macros
100 CheckSyncReport m_checkReport;
102 /** maximum message size supported by client */
104 /** maximum object size supported by client */
106 /** enabled large object support */
108 /** enabled WBXML (default) */
115 typedef boost::function<bool (EvolutionSyncClient &,
116 SyncOptions &)> Callback_t;
118 * Callback to be invoked after setting up local sources, but
119 * before running the engine. May throw exception to indicate
120 * error and return true to stop sync without error.
122 Callback_t m_startCallback;
124 boost::shared_ptr<SyncEvolution::TransportAgent> m_transport;
126 SyncOptions(SyncMode syncMode = SYNC_NONE,
127 const CheckSyncReport &checkReport = CheckSyncReport(),
128 long maxMsgSize = 128 * 1024, // 128KB = large enough that normal tests should run with a minimal number of messages
129 long maxObjSize = 1 * 1024 * 1024 * 1024, // 1GB = basically unlimited...
130 bool loSupport = false,
131 bool isWBXML = defaultWBXML(),
132 Callback_t startCallback = EmptyCallback,
133 boost::shared_ptr<SyncEvolution::TransportAgent> transport =
134 boost::shared_ptr<SyncEvolution::TransportAgent>()) :
135 m_syncMode(syncMode),
136 m_checkReport(checkReport),
137 m_maxMsgSize(maxMsgSize),
138 m_maxObjSize(maxObjSize),
139 m_loSupport(loSupport),
141 m_isSuspended(false),
143 m_startCallback(startCallback),
144 m_transport (transport)
147 SyncOptions &setSyncMode(SyncMode syncMode) { m_syncMode = syncMode; return *this; }
148 SyncOptions &setCheckReport(const CheckSyncReport &checkReport) { m_checkReport = checkReport; return *this; }
149 SyncOptions &setMaxMsgSize(long maxMsgSize) { m_maxMsgSize = maxMsgSize; return *this; }
150 SyncOptions &setMaxObjSize(long maxObjSize) { m_maxObjSize = maxObjSize; return *this; }
151 SyncOptions &setLOSupport(bool loSupport) { m_loSupport = loSupport; return *this; }
152 SyncOptions &setWBXML(bool isWBXML) { m_isWBXML = isWBXML; return *this; }
153 SyncOptions &setStartCallback(const Callback_t &callback) { m_startCallback = callback; return *this; }
154 SyncOptions &setTransportAgent(const boost::shared_ptr<SyncEvolution::TransportAgent> transport)
155 {m_transport = transport; return *this;}
157 static bool EmptyCallback(EvolutionSyncClient &,
158 SyncOptions &) { return false; }
160 /** if CLIENT_TEST_XML=1, then XML, otherwise WBXML */
161 static bool defaultWBXML();
168 * This is the interface expected by the testing framework for sync
169 * clients. It defines several methods that a derived class must
170 * implement if it wants to use that framework. Note that this class
171 * itself is not derived from SyncClient. This gives a user of this
172 * framework the freedom to implement it in two different ways:
173 * - implement a class derived from both SyncClient and ClientTest
174 * - add testing of an existing subclass of SyncClient by implementing
175 * a ClientTest which uses that subclass
177 * The client is expected to support change tracking for multiple
178 * servers. Although the framework always always tests against the
179 * same server, for most tests it is necessary to access the database
180 * without affecting the next synchronization with the server. This is
181 * done by asking the client for two different sync sources via
182 * Config::createSourceA and Config::createSourceB which have to
183 * create them in a suitable way - pretty much as if the client was
184 * synchronized against different server. A third, different change
185 * tracking is needed for real synchronizations of the data.
187 * Furthermore the client is expected to support multiple data sources
188 * of the same kind, f.i. two different address books. This is used to
189 * test full client A <-> server <-> client B synchronizations in some
190 * tests or to check server modifications done by client A with a
191 * synchronization against client B. In those tests client A is mapped
192 * to the first data source and client B to the second one.
194 * Finally the SyncSource API is used in slightly different ways which
195 * go beyond what is normally expected from a SyncSource implementation:
196 * - beginSync() may be called without setting a sync mode:
197 * when SyncSource::getSyncMode() returns SYNC_NONE the source is
198 * expected to make itself ready to iterate over all, new, updated and
200 * - items may be added via SyncSource::addItem() with a type of "raw":
201 * this implies that the type is the one used for items in the
202 * ClientTest::Config below
204 * Handling configuration and creating classes is entirely done by the
205 * subclass of ClientTest, the frameworks makes no assumptions
206 * about how this is done. Instead it queries the ClientTest for
207 * properties (like available sync sources) and then creates several
212 ClientTest(int serverSleepSec = 0, const std::string &serverLog= "");
213 virtual ~ClientTest();
216 * This function registers tests using this instance of ClientTest for
217 * later use during a test run.
219 * The instance must remain valid until after the tests were
220 * run. To run them use a separate test runner, like the one from
221 * client-test-main.cpp.
223 virtual void registerTests();
228 * Creates an instance of LocalTests (default implementation) or a
229 * class derived from it. LocalTests provides tests which cover
230 * the SyncSource interface and can be executed without a SyncML
231 * server. It also contains utility functions for working with
234 * A ClientTest implementation can, but doesn't have to extend
235 * these tests by instantiating a derived class here.
237 virtual LocalTests *createLocalTests(const std::string &name, int sourceParam, ClientTest::Config &co);
240 * Creates an instance of SyncTests (default) or a class derived
241 * from it. SyncTests provides tests which cover the actual
242 * interaction with a SyncML server.
244 * A ClientTest implementation can, but doesn't have to extend
245 * these tests by instantiating a derived class here.
247 virtual SyncTests *createSyncTests(const std::string &name, std::vector<int> sourceIndices, bool isClientA = true);
250 * utility function for dumping items which are C strings with blank lines as separator
252 static int dump(ClientTest &client, SyncSource &source, const char *file);
255 * utility function for splitting file into items with blank lines as separator
257 * @retval realfile If <file>.<server>.tem exists, then it is used instead
258 * of the generic version. The caller gets the name of the
259 * file that was opened here.
261 static void getItems(const char *file, std::list<std::string> &items, std::string &realfile);
264 * utility function for importing items with blank lines as separator
266 static int import(ClientTest &client, SyncSource &source, const char *file, std::string &realfile);
269 * utility function for comparing vCard and iCal files with the external
270 * synccompare.pl Perl script
272 static bool compare(ClientTest &client, const char *fileA, const char *fileB);
277 * A derived class can use this call to get default test
278 * cases, but still has to add callbacks which create sources
279 * and execute a sync session.
281 * Some of the test cases are compiled into the library, other
282 * depend on the auxiliary files from the "test" directory.
283 * Currently supported types:
284 * - vcard30 = vCard 3.0 contacts
285 * - vcard21 = vCard 2.1 contacts
286 * - ical20 = iCal 2.0 events
287 * - vcal10 = vCal 1.0 events
288 * - itodo20 = iCal 2.0 tasks
290 static void getTestData(const char *type, Config &config);
293 * Information about a data source. For the sake of simplicity all
294 * items pointed to are owned by the ClientTest and must
295 * remain valid throughout a test session. Not setting a pointer
296 * is okay, but it will disable all tests that need the
301 * The name is used in test names and has to be set.
303 const char *sourceName;
306 * A default URI to be used when creating a client config.
311 * A member function of a subclass which is called to create a
312 * sync source referencing the data. This is used in tests of
313 * the SyncSource API itself as well as in tests which need to
314 * modify or check the data sources used during synchronization.
316 * The test framework will call beginSync() and then some of
317 * the functions it wants to test. After a successful test it
318 * will call endSync() which is then expected to store all
319 * changes persistently. Creating a sync source again
320 * with the same call should not report any
321 * new/updated/deleted items until such changes are made via
322 * another sync source.
324 * The instance will be deleted by the caller. Because this
325 * may be in the error case or in an exception handler,
326 * the sync source's desctructor should not thow exceptions.
328 * @param client the same instance to which this config belongs
329 * @param source index of the data source (from 0 to ClientTest::getNumSources() - 1)
330 * @param isSourceA true if the requested SyncSource is the first one accessing that
331 * data, otherwise the second
333 typedef SyncSource *(*createsource_t)(ClientTest &client, int source, bool isSourceA);
336 * Creates a sync source which references the primary database;
337 * it may report the same changes as the sync source used during
340 createsource_t createSourceA;
343 * A second sync source also referencing the primary data
344 * source, but configured so that it tracks changes
345 * independently from the the primary sync source.
347 * In local tests the usage is like this:
348 * - add item via first SyncSource
349 * - iterate over new items in second SyncSource
350 * - check that it lists the added item
352 * In tests with a server the usage is:
353 * - do a synchronization with the server
354 * - iterate over items in second SyncSource
355 * - check that the total number and number of
356 * added/updated/deleted items is as expected
358 createsource_t createSourceB;
361 * The framework can generate vCard and vCalendar/iCalendar items
362 * automatically by copying a template item and modifying certain
365 * This is the template for these automatically generated items.
366 * It must contain the string <<REVISION>> which will be replaced
367 * with the revision parameter of the createItem() method.
369 const char *templateItem;
372 * This is a colon (:) separated list of properties which need
373 * to be modified in templateItem.
375 const char *uniqueProperties;
378 * the number of items to create during stress tests
383 * This is a single property in templateItem which can be extended
384 * to increase the size of generated items.
386 const char *sizeProperty;
389 * Type to be set when importing any of the items into the
390 * corresponding sync sources. Use "" if sync source doesn't
391 * need this information.
393 const char *itemType;
396 * A very simple item that is inserted during basic tests. Ideally
397 * it only contains properties supported by all servers.
399 const char *insertItem;
402 * A slightly modified version of insertItem. If the source has UIDs
403 * embedded into the item data, then both must have the same UID.
404 * Again all servers should better support these modified properties.
406 const char *updateItem;
409 * A more heavily modified version of insertItem. Same UID if necessary,
410 * but can test changes to items only supported by more advanced
413 const char *complexUpdateItem;
416 * To test merge conflicts two different updates of insertItem are
417 * needed. This is the first such update.
419 const char *mergeItem1;
422 * The second merge update item. To avoid true conflicts it should
423 * update different properties than mergeItem1, but even then servers
424 * usually have problems perfectly merging items. Therefore the
425 * test is run without expecting a certain merge result.
427 const char *mergeItem2;
430 * These two items are related: one is main one, the other is
431 * a subordinate one. The semantic is that the main item is
432 * complete on it its own, while the other normally should only
433 * be used in combination with the main one.
435 * Because SyncML cannot express such dependencies between items,
436 * a SyncSource has to be able to insert, updated and remove
437 * both items independently. However, operations which violate
438 * the semantic of the related items (like deleting the parent, but
439 * not the child) may have unspecified results (like also deleting
440 * the child). See LINKED_ITEMS_RELAXED_SEMANTIC.
442 * One example for main and subordinate items are a recurring
443 * iCalendar 2.0 event and a detached recurrence.
445 const char *parentItem, *childItem;
448 * define to 0 to disable tests which slightly violate the
449 * semantic of linked items by inserting children
450 * before/without their parent
452 #ifndef LINKED_ITEMS_RELAXED_SEMANTIC
453 # define LINKED_ITEMS_RELAXED_SEMANTIC 1
457 * setting this to false disables tests which depend
458 * on the source's support for linked item semantic
459 * (testLinkedItemsInsertParentTwice, testLinkedItemsInsertChildTwice)
461 bool sourceKnowsItemSemantic;
464 * called to dump all items into a file, required by tests which need
467 * ClientTest::dump can be used: it will simply dump all items of the source
468 * with a blank line as separator.
470 * @param source sync source A already created and with beginSync() called
471 * @param file a file name
472 * @return error code, 0 for success
474 int (*dump)(ClientTest &client, SyncSource &source, const char *file);
477 * import test items: which these are is determined entirely by
478 * the implementor, but tests work best if several complex items are
481 * ClientTest::import can be used if the file contains items separated by
484 * @param source sync source A already created and with beginSync() called
485 * @param file the name of the file to import
486 * @retval realfile the name of the file that was really imported;
487 * this may depend on the current server that is being tested
488 * @return error code, 0 for success
490 int (*import)(ClientTest &client, SyncSource &source, const char *file, std::string &realfile);
493 * a function which compares two files with items in the format used by "dump"
495 * @param fileA first file name
496 * @param fileB second file name
497 * @return true if the content of the files is considered equal
499 bool (*compare)(ClientTest &client, const char *fileA, const char *fileB);
502 * a file with test cases in the format expected by import and compare
504 const char *testcases;
507 * the item type normally used by the source (not used by the tests
508 * themselves; client-test.cpp uses it to initialize source configs)
513 * TRUE if the source supports recovery from an interrupted
514 * synchronization. Enables the Client::Sync::*::Retry group
521 * Data sources are enumbered from 0 to n-1 for the purpose of
522 * testing. This call returns n.
524 virtual int getNumSources() = 0;
527 * Called to fill the given test source config with information
528 * about a sync source identified by its index. It's okay to only
529 * fill in the available pieces of information and set everything
532 virtual void getSourceConfig(int source, Config &config) = 0;
535 * The instance to use as second client. Returning NULL disables
536 * all checks which require a second client. The returned pointer
537 * must remain valid throughout the life time of the tests.
539 * The second client must be configured to access the same server
540 * and have data sources which match the ones from the primary
543 virtual ClientTest *getClientB() = 0;
546 * Execute a synchronization with the selected sync sources
547 * and the selected synchronization options. The log file
548 * in LOG has been set up already for the synchronization run
549 * and should not be changed by the client.
551 * @param activeSources a -1 terminated array of sync source indices
552 * @param logbase basename for logging: can be used for directory or as file (by adding .log suffix)
553 * @param options sync options to be used
554 * @return return code of SyncClient::sync()
556 virtual SyncMLStatus doSync(
557 const int *activeSources,
558 const std::string &logbase,
559 const SyncOptions &options) = 0;
563 * This is called after successful sync() calls (res == 0) as well
564 * as after unsuccessful ones (res != 1). The default implementation
565 * sleeps for the number of seconds specified when constructing this
566 * instance and copies the server log if one was named.
568 * @param res result of sync()
569 * @param logname base name of the current sync log (without ".client.[AB].log" suffix)
571 virtual void postSync(int res, const std::string &logname);
575 * time to sleep in postSync()
577 int serverSleepSeconds;
580 * server log file which is copied by postSync() and then
581 * truncated (Unix only, Windows does not allow such access
584 std::string serverLogFileName;
588 * really a CppUnit::TestFactory, but declared as void * to avoid
589 * dependencies on the CPPUnit header files: created by
590 * registerTests() and remains valid until the client is deleted
596 * helper class to encapsulate ClientTest::Config::createsource_t
597 * pointer and the corresponding parameters
601 CreateSource(ClientTest::Config::createsource_t createSourceParam, ClientTest &clientParam, int sourceParam, bool isSourceAParam) :
602 createSource(createSourceParam),
605 isSourceA(isSourceAParam) {}
607 SyncSource *operator() () {
608 CPPUNIT_ASSERT(createSource);
609 return createSource(client, source, isSourceA);
612 const ClientTest::Config::createsource_t createSource;
615 const bool isSourceA;
620 * local test of one sync source and utility functions also used by
623 class LocalTests : public CppUnit::TestSuite, public CppUnit::TestFixture {
625 /** the client we are testing */
628 /** number of the source we are testing in that client */
631 /** configuration that corresponds to source */
632 const ClientTest::Config config;
634 /** helper funclets to create sources */
635 CreateSource createSourceA, createSourceB;
637 LocalTests(const std::string &name, ClientTest &cl, int sourceParam, ClientTest::Config &co) :
638 CppUnit::TestSuite(name),
642 createSourceA(co.createSourceA, cl, sourceParam, true),
643 createSourceB(co.createSourceB, cl, sourceParam, false)
647 * adds the supported tests to the instance itself;
648 * this is the function that a derived class can override
649 * to add additional tests
651 virtual void addTests();
654 * opens source and inserts the given item; can be called
655 * regardless whether the data source already contains items or not
657 * @param relaxed if true, then disable some of the additional checks after adding the item
658 * @return the LUID of the inserted item
660 virtual std::string insert(CreateSource createSource, const char *data, const char *dataType, bool relaxed = false);
663 * assumes that exactly one element is currently inserted and updates it with the given item
665 * @param check if true, then reopen the source and verify that the reported items are as expected
667 virtual void update(CreateSource createSource, const char *data, const char *dataType, bool check = true);
670 * updates one item identified by its LUID with the given item
672 * The type of the item is cleared, as in insert() above.
674 virtual void update(CreateSource createSource, const char *data, const char *dataType, const std::string &luid);
676 /** deletes all items locally via sync source */
677 virtual void deleteAll(CreateSource createSource);
680 * takes two databases, exports them,
681 * then compares them using synccompare
683 * @param refFile existing file with source reference items, NULL uses a dump of sync source A instead
684 * @param copy a sync source which contains the copied items, begin/endSync will be called
685 * @param raiseAssert raise assertion if comparison yields differences (defaults to true)
686 * @return true if the two databases are equal
688 virtual bool compareDatabases(const char *refFile, SyncSource ©, bool raiseAssert = true);
691 * insert artificial items, number of them determined by TEST_EVOLUTION_NUM_ITEMS
692 * unless passed explicitly
694 * @param createSource a factory for the sync source that is to be used
695 * @param startIndex IDs are generated starting with this value
696 * @param numItems number of items to be inserted if non-null, otherwise TEST_EVOLUTION_NUM_ITEMS is used
697 * @param size minimum size for new items
698 * @return number of items inserted
700 virtual std::list<std::string> insertManyItems(CreateSource createSource, int startIndex = 1, int numItems = 0, int size = -1);
703 * create an artificial item for the current database
705 * @param item item number: items with different number should be
706 * recognized as different by SyncML servers
707 * @param revision differentiates items with the same item number (= updates of an older item)
708 * @param size if > 0, then create items at least that large (in bytes)
709 * @return created item
711 std::string createItem(int item, const std::string &revision, int size);
712 std::string createItem(int item, int revision, int size) {
714 sprintf(buffer, "%d", revision);
715 return createItem(item, std::string(buffer), size);
718 /* for more information on the different tests see their implementation */
720 virtual void testOpen();
721 virtual void testIterateTwice();
722 virtual void testSimpleInsert();
723 virtual void testLocalDeleteAll();
724 virtual void testComplexInsert();
725 virtual void testLocalUpdate();
726 virtual void testChanges();
727 virtual void testImport();
728 virtual void testImportDelete();
729 virtual void testManyChanges();
730 virtual void testLinkedItemsParent();
731 virtual void testLinkedItemsChild();
732 virtual void testLinkedItemsParentChild();
733 virtual void testLinkedItemsChildParent();
734 virtual void testLinkedItemsChildChangesParent();
735 virtual void testLinkedItemsRemoveParentFirst();
736 virtual void testLinkedItemsRemoveNormal();
737 virtual void testLinkedItemsInsertParentTwice();
738 virtual void testLinkedItemsInsertChildTwice();
739 virtual void testLinkedItemsParentUpdate();
740 virtual void testLinkedItemsUpdateChild();
741 virtual void testLinkedItemsInsertBothUpdateChild();
742 virtual void testLinkedItemsInsertBothUpdateParent();
754 * utility function which counts items of a certain kind known to the sync source
755 * @param source valid source ready to iterate; NULL triggers an assert
756 * @param itemType determines which iterator functions are used
757 * @return number of valid items iterated over
759 int countItemsOfType(SyncSource *source, itemType type);
761 typedef std::list<std::string> UIDList;
763 * generates list of UIDs in the specified kind of items
765 UIDList listItemsOfType(SyncSource *source, itemType type);
768 * Tests synchronization with one or more sync sources enabled.
769 * When testing multiple sources at once only the first config
770 * is checked to see which tests can be executed.
772 class SyncTests : public CppUnit::TestSuite, public CppUnit::TestFixture {
774 /** the client we are testing */
777 SyncTests(const std::string &name, ClientTest &cl, std::vector<int> sourceIndices, bool isClientA = true);
780 /** adds the supported tests to the instance itself */
781 virtual void addTests();
784 /** list with all local test classes for manipulating the sources and their index in the client */
785 std::vector< std::pair<int, LocalTests *> > sources;
786 typedef std::vector< std::pair<int, LocalTests *> >::iterator source_it;
789 * Stack of log file prefixes which are to be appended to the base name,
790 * which already contains the current test name. Add a new prefix by
791 * instantiating SyncPrefix. Its destructor takes care of popping
794 std::list<std::string> logPrefixes;
799 SyncPrefix(const std::string &prefix, SyncTests &tests) :
801 tests.logPrefixes.push_back(prefix);
804 m_tests.logPrefixes.pop_back();
807 friend class SyncPrefix;
809 /** the indices from sources, terminated by -1 (for sync()) */
812 /** utility functions for second client */
813 SyncTests *accessClientB;
816 DELETE_ALL_SYNC, /**< make sure client and server are in sync,
819 DELETE_ALL_REFRESH /**< delete locally, refresh server */
823 * Compare databases second client with either reference file(s)
824 * or first client. The reference file(s) must follow the naming
825 * scheme <reFileBase><source name>.dat
827 virtual bool compareDatabases(const char *refFileBase = NULL,
828 bool raiseAssert = true);
830 /** deletes all items locally and on server */
831 virtual void deleteAll(DeleteAllMode mode = DELETE_ALL_SYNC);
833 /** get both clients in sync with empty server, then copy one item from client A to B */
834 virtual void doCopy();
837 * replicate server database locally: same as SYNC_REFRESH_FROM_SERVER,
838 * but done with explicit local delete and then a SYNC_SLOW because some
839 * servers do no support SYNC_REFRESH_FROM_SERVER
841 virtual void refreshClient(SyncOptions options = SyncOptions());
843 /* for more information on the different tests see their implementation */
845 // do a two-way sync without additional checks,
846 // may or may not actually be done in two-way mode
847 virtual void testTwoWaySync() {
848 doSync(SyncOptions(SYNC_TWO_WAY));
851 // do a slow sync without additional checks
852 virtual void testSlowSync() {
853 doSync(SyncOptions(SYNC_SLOW,
854 CheckSyncReport(-1,-1,-1, -1,-1,-1, true, SYNC_SLOW)));
856 // do a refresh from server sync without additional checks
857 virtual void testRefreshFromServerSync() {
858 doSync(SyncOptions(SYNC_REFRESH_FROM_SERVER,
859 CheckSyncReport(-1,-1,-1, -1,-1,-1, true, SYNC_REFRESH_FROM_SERVER)));
862 // do a refresh from client sync without additional checks
863 virtual void testRefreshFromClientSync() {
864 doSync(SyncOptions(SYNC_REFRESH_FROM_CLIENT,
865 CheckSyncReport(-1,-1,-1, -1,-1,-1, true, SYNC_REFRESH_FROM_CLIENT)));
868 // delete all items, locally and on server using two-way sync
869 virtual void testDeleteAllSync() {
870 deleteAll(DELETE_ALL_SYNC);
873 virtual void testDeleteAllRefresh();
874 virtual void testRefreshFromClientSemantic();
875 virtual void testRefreshFromServerSemantic();
876 virtual void testRefreshStatus();
878 // test that a two-way sync copies an item from one address book into the other
884 virtual void testUpdate();
885 virtual void testComplexUpdate();
886 virtual void testDelete();
887 virtual void testMerge();
888 virtual void testTwinning();
889 virtual void testOneWayFromServer();
890 virtual void testOneWayFromClient();
891 bool doConversionCallback(bool *success,
892 EvolutionSyncClient &client,
893 SyncOptions &options);
894 virtual void testConversion();
895 virtual void testItems();
896 virtual void testItemsXML();
897 virtual void testAddUpdate();
899 // test copying with maxMsg and no large object support
901 doVarSizes(true, false);
903 // test copying with maxMsg and large object support
904 void testLargeObject() {
905 doVarSizes(true, true);
908 virtual void testManyItems();
910 virtual void doInterruptResume(int changes,
911 boost::shared_ptr<TransportWrapper> wrapper);
914 CLIENT_REMOVE = (1<<1),
915 CLIENT_UPDATE = (1<<2),
917 SERVER_REMOVE = (1<<4),
918 SERVER_UPDATE = (1<<5)
920 virtual void testInterruptResumeClientAdd();
921 virtual void testInterruptResumeClientRemove();
922 virtual void testInterruptResumeClientUpdate();
923 virtual void testInterruptResumeServerAdd();
924 virtual void testInterruptResumeServerRemove();
925 virtual void testInterruptResumeServerUpdate();
926 virtual void testInterruptResumeFull();
928 virtual void testUserSuspendClientAdd();
929 virtual void testUserSuspendClientRemove();
930 virtual void testUserSuspendClientUpdate();
931 virtual void testUserSuspendServerAdd();
932 virtual void testUserSuspendServerRemove();
933 virtual void testUserSuspendServerUpdate();
934 virtual void testUserSuspendFull();
938 * implements testMaxMsg(), testLargeObject(), testLargeObjectEncoded()
939 * using a sequence of items with varying sizes
941 virtual void doVarSizes(bool withMaxMsgSize,
942 bool withLargeObject);
945 * executes a sync with the given options,
946 * checks the result and (optionally) the sync report
948 virtual void doSync(const SyncOptions &options);
949 virtual void doSync(const char *logPrefix,
950 const SyncOptions &options) {
951 SyncPrefix prefix(logPrefix, *this);
957 * A transport wraper wraps a real transport impl and gives user
958 * possibility to do additional work before/after transport operation.
959 * We use TransportFaultInjector to emulate a network failure;
960 * We use UserSuspendInjector to emulate a user suspend after receving
963 class TransportWrapper : public SyncEvolution::TransportAgent {
965 int m_interruptAtMessage, m_messageCount;
966 boost::shared_ptr<SyncEvolution::TransportAgent> m_wrappedAgent;
968 SyncOptions *m_options;
972 m_interruptAtMessage = -1;
973 m_wrappedAgent = boost::shared_ptr<SyncEvolution::TransportAgent>();
977 ~TransportWrapper() {
980 virtual int getMessageCount() { return m_messageCount; }
982 virtual void setURL(const std::string &url) { m_wrappedAgent->setURL(url); }
983 virtual void setProxy(const std::string &proxy) { m_wrappedAgent->setProxy(proxy); }
984 virtual void setProxyAuth(const std::string &user,
985 const std::string &password) { m_wrappedAgent->setProxyAuth(user, password); }
986 virtual void setSSL(const std::string &cacerts,
988 bool verifyHost) { m_wrappedAgent->setSSL(cacerts, verifyServer, verifyHost); }
989 virtual void setContentType(const std::string &type) { m_wrappedAgent->setContentType(type); }
990 virtual void setUserAgent(const::string &agent) { m_wrappedAgent->setUserAgent(agent); }
991 virtual void setAgent(boost::shared_ptr<SyncEvolution::TransportAgent> agent) {m_wrappedAgent = agent;}
992 virtual void setSyncOptions(SyncOptions *options) {m_options = options;}
993 virtual void setInterruptAtMessage (int interrupt) {m_interruptAtMessage = interrupt;}
994 virtual void cancel() { m_wrappedAgent->cancel(); }
995 virtual void reset() {
997 m_interruptAtMessage = -1;
1001 virtual Status wait() { return m_status; }
1004 /** assert equality, include string in message if unequal */
1005 #define CLIENT_TEST_EQUAL( _prefix, \
1008 CPPUNIT_ASSERT_EQUAL_MESSAGE( std::string(_prefix) + ": " + #_expected + " == " + #_actual, \
1012 /** execute _x and then check the status of the _source pointer */
1013 #define SOURCE_ASSERT_NO_FAILURE(_source, _x) \
1015 CPPUNIT_ASSERT_NO_THROW(_x); \
1016 CPPUNIT_ASSERT((_source) && !(_source)->hasFailed()); \
1019 /** check _x for true and then the status of the _source pointer */
1020 #define SOURCE_ASSERT(_source, _x) \
1022 CPPUNIT_ASSERT(_x); \
1023 CPPUNIT_ASSERT((_source) && !(_source)->hasFailed()); \
1026 /** check that _x evaluates to a specific value and then the status of the _source pointer */
1027 #define SOURCE_ASSERT_EQUAL(_source, _value, _x) \
1029 CPPUNIT_ASSERT_EQUAL(_value, _x); \
1030 CPPUNIT_ASSERT((_source) && !(_source)->hasFailed()); \
1033 /** same as SOURCE_ASSERT() with a specific failure message */
1034 #define SOURCE_ASSERT_MESSAGE(_message, _source, _x) \
1036 CPPUNIT_ASSERT_MESSAGE((_message), (_x)); \
1037 CPPUNIT_ASSERT((_source) && !(_source)->hasFailed()); \
1042 * convenience macro for adding a test name like a function,
1043 * to be used inside addTests() of an instance of that class
1045 * @param _class class which contains the function
1046 * @param _function a function without parameters in that class
1048 #define ADD_TEST(_class, _function) \
1049 ADD_TEST_TO_SUITE(this, _class, _function)
1051 #define ADD_TEST_TO_SUITE(_suite, _class, _function) \
1052 _suite->addTest(FilterTest(new CppUnit::TestCaller<_class>(_suite->getName() + "::" #_function, &_class::_function, *this)))
1054 #endif // ENABLE_INTEGRATION_TESTS
1055 #endif // INCL_TESTSYNCCLIENT