ActiveSync: allow testing against Google

Google doesn't seem to support the Fetch operation, which is used
during testing to retrieve unchanged items. During syncing it will
only be needed when merging incoming data with an existing item, which
should not be necessary... except that testing shows that it is
necessary. The case where it is needed is:
- incremental sync (cache empty)
- calendar event series needs to be modified
- items from that series need to be fetched in preparation
  for updating it

To allow testing, several workarounds are necessary:
- request *all* data before doing a data dump in testImport (and friends),
  to ensure that the cache in the backend is fully populated
- use the cache in ActiveSyncCalendarSource instead of accessing
  the base class directly, because that would trigger a Fetch

Accessing the base class is still useful for Exchange+calendar,
because testing then avoids the cache (and thus can expose bugs
in it).

While at it, adapted the README. "database" needs to be set
explicitly, "client-test" only does it when creating configs.
This commit is contained in:
Patrick Ohly 2012-06-04 10:17:18 +02:00
parent c464394eda
commit 14889ede24
4 changed files with 79 additions and 23 deletions

View File

@ -142,7 +142,8 @@ namespace {
* operation. Using the cached information implies that we won't find bugs in
* the handling of that information.
*/
static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::string &file)
static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::string &file,
bool forceBaseReadItem)
{
ActiveSyncSource &eassource = static_cast<ActiveSyncSource &>(source);
ofstream out(file.c_str());
@ -161,7 +162,20 @@ static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::s
BOOST_FOREACH(const std::string &easid, easids) {
std::string item;
eassource.ActiveSyncSource::readItem(easid, item);
if (forceBaseReadItem) {
// This bypasses the more specialized
// ActiveSyncCalendarSource::readItem(), which helps
// reveal potential bugs in it. However, it depends on a
// working Fetch operation in the ActiveSync server, which
// Google doesn't seem to provide (404 error).
eassource.ActiveSyncSource::readItem(easid, item);
} else {
// Normal readItem() works with Google by using the cached
// item. However, the source must have done a beginSync()
// with empty sync key, because otherwise the cache is
// not guaranteed to be complete.
eassource.readItem(easid, item);
}
out << item << '\n';
if (!boost::ends_with(item, "\n")) {
out << '\n';
@ -201,7 +215,8 @@ static TestingSyncSource *createEASSource(const ClientTestConfig::createsource_t
// common settings for all kinds of data
static void updateConfigEAS(const RegisterSyncSourceTest */* me */,
ClientTestConfig &config)
ClientTestConfig &config,
EasItemType type)
{
// cannot run tests involving a second database:
// wrap orginal source creation, set default database for
@ -211,7 +226,12 @@ static void updateConfigEAS(const RegisterSyncSourceTest */* me */,
config.m_createSourceB = boost::bind(createEASSource, config.m_createSourceB,
_1, _2, _3, _4);
config.m_dump = DumpItems;
config.m_dump = boost::bind(DumpItems, _1, _2, _3,
type == EAS_ITEM_CONTACT ||
// need to read from our cache for Google Calendar,
// because it does not support Fetch
strcmp(getEnv("CLIENT_TEST_SERVER", ""), "googleeas")
);
config.m_sourceLUIDsAreVolatile = true;
// TODO: find out how ActiveSync/Exchange handle children without parent;
// at the moment, the child is stored as if it was a stand-alone event
@ -233,7 +253,7 @@ public:
// TODO: provide comprehensive set of vCard 3.0 contacts as they are understood by the ActiveSync library
// config.testcases = "testcases/eas_contact.vcf";
updateConfigEAS(this, config);
updateConfigEAS(this, config, EAS_ITEM_CONTACT);
}
} ActiveSyncContactTest;
@ -246,7 +266,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.m_type = "eas-events";
updateConfigEAS(this, config);
updateConfigEAS(this, config, EAS_ITEM_CALENDAR);
}
} ActiveSyncEventTest;
@ -259,7 +279,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.m_type = "eas-todos";
updateConfigEAS(this, config);
updateConfigEAS(this, config, EAS_ITEM_TODO);
}
} ActiveSyncTodoTest;
@ -272,7 +292,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.m_type = "eas-memos";
updateConfigEAS(this, config);
updateConfigEAS(this, config, EAS_ITEM_JOURNAL);
}
} ActiveSyncMemoTest;

View File

@ -74,6 +74,10 @@ which must simulate two independent ActiveSync clients.
Configure "local" testing (backend is covered, no syncing involved):
./syncevolution --configure username=<EAS account ID> \
eas_event/backend=eas-events \
eas_event/database= \
eas_contact/backend=eas-contacts \
eas_contact/database= \
--template SyncEvolution target-config@client-test-exchange
On MeeGo:
@ -114,19 +118,22 @@ Sync Testing
syncevolution --configure \
syncURL=local://@exchange \
username=<EAS account ID> \
backend=evolution-calendar \
eds_event/backend=evolution-calendar \
eds_event/uri=calendar \
eds_event/uri=eas_event \
eds_event/database=SyncEvolution_Test_eds_event_1 \
eds_contact/backend=evolution-contacts \
eds_contact/uri=addressbook \
eds_contact/uri=eas_contact \
eds_contact/database=SyncEvolution_Test_eds_contact_1 \
--template SyncEvolution_Client exchange_1@client-test-1 eds_event eds_contact
syncevolution --configure \
syncURL=local://@exchange \
username=<EAS account ID>_B \
eds_event/backend=evolution-calendar \
eds_event/uri=calendar \
eds_event/uri=eas_event \
eds_event/database=SyncEvolution_Test_eds_event_2 \
eds_contact/backend=evolution-contacts \
eds_contact/uri=addressbook \
eds_contact/uri=eas_contact \
eds_contact/database=SyncEvolution_Test_eds_contact_2 \
--template SyncEvolution_Client exchange_2@client-test-2 eds_event eds_contact
- Create calendars named as follows in Evolution:
SyncEvolution_Test_eds_event_1
@ -140,3 +147,11 @@ target-config@exchange with different usernames in each sync
config. This is necessary because change tracking depends on that
username.
Google via ActiveSync
=====================
- Use "googleeas" instead of "exchange", because ActiveSyncSourceRegister.cpp
needs to know that it is talking to Google, to work around the lack of
Fetch command support.

View File

@ -280,7 +280,12 @@ public:
}
}
void reset(TestingSyncSource *source = NULL)
enum Flags {
SLOW, /**< erase anchor, start accessing database from scratch */
INCREMENTAL /**< allow source to do incremental data read */
};
void reset(TestingSyncSource *source = NULL, Flags flags = INCREMENTAL)
{
if (get() && m_active) {
stopAccess();
@ -291,7 +296,7 @@ public:
base_t::reset(source);
}
if (source) {
startAccess();
startAccess(flags);
}
}
@ -299,7 +304,7 @@ public:
* done automatically as part of reset(), only to be called
* after an explicit stopAccess()
*/
void startAccess()
void startAccess(Flags flags = INCREMENTAL)
{
CT_ASSERT(get());
CT_ASSERT(!m_active);
@ -311,6 +316,9 @@ public:
CT_ASSERT_NO_THROW(get()->open());
string node = get()->getTrackingNode()->getName();
string anchor = m_anchors[node];
if (flags == SLOW) {
anchor = "";
}
get()->beginSync(anchor, "");
if (isServerMode()) {
CT_ASSERT_NO_THROW(get()->enableServerMode());
@ -1282,9 +1290,13 @@ void LocalTests::testImport() {
backupStorage(config, client);
CT_ASSERT_NO_THROW(source.reset());
// export again and compare against original file
// export again and compare against original file,
// without relying on change tracking (because
// Google ActiveSync has problems with Fetch,
// which would be needed for a data dump when
// using the incremental approach)
TestingSyncSourcePtr copy;
SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceA()));
SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceA(), TestingSyncSourcePtr::SLOW));
bool equal = compareDatabases(testcases.c_str(), *copy.get(), false);
CT_ASSERT_NO_THROW(source.reset());
@ -1371,7 +1383,7 @@ void LocalTests::testRemoveProperties() {
// compare
TestingSyncSourcePtr copy;
SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceA()));
SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceA(), TestingSyncSourcePtr::SLOW));
bool equal = compareDatabases(updated.c_str(), *copy.get(), false);
CT_ASSERT_NO_THROW(source.reset());

View File

@ -84,7 +84,9 @@ my $full_timezones = $ENV{CLIENT_TEST_FULL_TIMEZONES}; # do not simplify VTIMEZO
my $exchange = $server =~ /exchange/; # Exchange via ActiveSync
my $egroupware = $server =~ /egroupware/;
my $funambol = $server =~ /funambol/;
my $google = $server =~ /google/;
my $googlesyncml = $server eq "google";
my $googlecaldav = $server eq "googlecalendar";
my $googleeas = $server eq "googleeas";
my $google_valarm = $ENV{CLIENT_TEST_GOOGLE_VALARM};
my $yahoo = $server =~ /yahoo/;
my $davical = $server =~ /davical/;
@ -363,7 +365,7 @@ sub NormalizeItem {
# > LY
s/^(\w+)([^:\n]*);X-EVOLUTION-ENDDATE=[0-9TZ]*/$1$2/mg;
if ($scheduleworld || $egroupware || $synthesis || $addressbook || $funambol ||$google || $mobical || $memotoo) {
if ($scheduleworld || $egroupware || $synthesis || $addressbook || $funambol ||$googlesyncml || $googleeas || $mobical || $memotoo) {
# does not preserve X-EVOLUTION-UI-SLOT=
s/^(\w+)([^:\n]*);X-EVOLUTION-UI-SLOT=\d+/$1$2/mg;
}
@ -389,7 +391,7 @@ sub NormalizeItem {
s/^(TEL.*);TYPE=PREF/$1/mg;
}
if($google) {
if($googlesyncml) {
# ignore the PHOTO encoding data
s/^PHOTO(.*?): .*\n/^PHOTO$1: [...]\n/mg;
# FN propertiey is not correct
@ -398,7 +400,9 @@ sub NormalizeItem {
s!^TEL\;TYPE=CAR(.*)\n!TEL$1\n!mg;
# some properties are lost
s/^(X-EVOLUTION-FILE-AS|NICKNAME|BDAY|CATEGORIES|CALURI|FBURL|ROLE|URL|X-AIM|X-EVOLUTION-UI-SLOT|X-ANNIVERSARY|X-ASSISTANT|X-EVOLUTION-BLOG-URL|X-EVOLUTION-VIDEO-URL|X-GROUPWISE|X-ICQ|X-GADUGADU|X-JABBER|X-MSN|X-SIP|X-SKYPE|X-MANAGER|X-SPOUSE|X-MOZILLA-HTML|X-YAHOO)(;[^:;\n]*)*:.*\r?\n?//gm;
}
if ($googlecaldav) {
#several properties are not preserved by Google in icalendar2.0 format
s/^(SEQUENCE|X-EVOLUTION-ALARM-UID)(;[^:;\n]*)*:.*\r?\n?//gm;
@ -429,7 +433,7 @@ sub NormalizeItem {
s/^(X-RADICALE-NAME)(;[^:;\n]*)*:.*\r?\n?//gm;
}
if ($google || $yahoo) {
if ($googlecaldav || $yahoo) {
# default status is CONFIRMED
s/^STATUS:CONFIRMED\r?\n?//gm;
}
@ -650,6 +654,11 @@ sub NormalizeItem {
s/^DESCRIPTION:Reminder\n//m;
}
if ($googleeas) {
# unsupported properties
s/^(FN)(;[^:;\n]*)*:.*\r?\n?//gm;
}
# treat X-MOZILLA-HTML=FALSE as if the property didn't exist
s/^X-MOZILLA-HTML:FALSE\r?\n?//gm;