Merge branch 'FREMANTLE-1-2-0' into HARMATTAN-1-2-0

Conflicts:
	debian/changelog
	debian/control
	debian/rules
This commit is contained in:
Ove Kåven 2011-11-21 01:53:53 +01:00
commit b2d6d21491
81 changed files with 3009 additions and 1279 deletions

301
NEWS
View file

@ -1,3 +1,304 @@
SyncEvolution 1.1.1 -> 1.2, 13.10.2011
======================================
The major new feature of the 1.2 release is support for non-SyncML
protocols in general and CalDAV/CardDAV in particular. ActiveSync
support is in development and will be in 1.3. These protocols are
implemented as backends which are combined with other backends by
SyncEvolution in a so called "local sync". The GTK sync-ui does not
yet support configuring non-SyncML protocols. See the README.rst and
man page for more information on how to use the new feature via the
command line.
Properties not supported by SyncML servers can now be preserved
locally in two-way synchronization (BMC #15030). This depends on
information about what properties a SyncML server supports ("CtCap"),
which is typically not provided by servers. SyncEvolution contains a
copy of that information for Google Contacts (BMC #15029).
Akonadi backend and KWallet support were merged. They are not included
yet in syncevolution.org binaries. To use them compile from source.
The configuration format was updated to solve a conceptual problem
inherited with the legacy property names: the "type" property had
multiple, sometimes conflicting roles. For example, setting the
preferred data format for sync with one peer might have changed the
backend selection for some other peer (BMC #1023). Now
"backend/databaseFormat/syncFormat/forceSyncFormat" replace
"type". "type" is still accepted by the command line as alias.
Upgrading from releases before 1.2:
Old configurations can still be read. But writing, as it happens
during a sync, must migrate the configuration first. Release 1.2
automatically migrates configurations. The old configurations
will still be available (see "syncevolution --print-configs") but must
be renamed manually to use them again under their original names with
older SyncEvolution releases.
Other changes:
* Using the --sync-property and --source-property command line options is
optional, just specifying the property assignment is enough.
* syncevo-http-server was enhanced considerably. See http://syncevolution.org/wiki/http-server-howto
* support NetworkManager API >= 0.9 (BMC #19470)
* syncevolution.org binaries: now compatible with Debian Testing/libnotify.so.4 (BMC #22668)
libnotify is not linked directly into syncevo-dbus-server in the
syncevolution.org binaries. Instead libnotify.so.1 till .so.4
(current Debian Testing) are opened opened dynamically and the
necessary functions are looked up via dlsym(). Not finding the
libraries or the functions silently disables this notification
mechanism.
* Sync mode is recorded when running in SyncML server mode (BMC #2786).
* syncevo-dbus-server automatically stops when some of its libraries
are updated and restarts if auto-syncing is on (BMC #14955).
* Added code for Buteo, mKCal and QtContacts in MeeGo.
Buteo and mKCal were removed again from MeeGo, so the code
is obsolete. The QtContacts backend may be still be useful
to access items via that API, but for syncing on MeeGo
the normal EDS backend is used since MeeGo reverted back
to EDS as PIM storage.
* "databasePassword" source property: lookup failure in keyring (BMC #22937)
The databasePassword also wasn't looked up at all when doing item operations
via the command line.
When configuring sources for an HTTP server, the config name typically
is just the context (@foo). When using the config in the HTTP server,
the config name is the peer inside that context (client@foo). Because
the GNOME keyring lookup keys for the "databasePassword" (more
specifically, the object name) contained the full config name which
was different in both cases, looking up the saved password failed.
The solution is to normalize the config name (to accomodate for
different ways of spelling it) and use only the context, with @ as
before. This will break existing setups where the object name in the
keyring (incorrectly) includes the full config name. In that case just
configure the source again to set the password anew.
* Evolution Calendar: fixed detached recurrence support (BMC #22940)
When manipulating a meeting series with more than one detached
recurrence certain sequences of operations could incorrectly fail
with "UID already exists".
* iCalendar 2.0: must set VALUE in EXDATE (part of BMC #22940)
EXDATE has a VALUE parameter, which wasn't defined in the XML
profile. Didn't seem to matter at all in practice, but wasn't
standard-compliant.
* GTK sync-ui: wrap sync service descriptions (BMC #7199)
Descriptions of different sync services are not fully visible unless
word-wrapping gets enabled.
* CalDAV/CardDAV + local storage: avoid empty properties
The main motivation for this change is that a recent Apple Calendar
server rejects vCards with empty BDAY property. Another reason is that
keeping the data as small as possible is desirable by itself.
Sending an empty property serves as a hint for the peer that the
property is supported. This is not necessary when storing an item in a
backend. Therefore this commit disables empty properties for all
backends which do not themselves set the m_backendRule Synthesis info
value.
* Google Contacts: ensure that first/middle/name are set when storing in EDS (BMC #20864)
Evolution and the MeeGo UX assume that first/middle/last name are set.
That is not the case when a contact is created in the Google Contacts
web interface. Such contacts are sent by Google without the N
property.
SyncEvolution now tries to recreate the name components from the FN
string, by splitting at word boundaries and assuming "<first>
<middle> <last>" or "<last>, <first>" format. Obviously this
heuristic fails for some locales.
* Evolution Calendar: fixed error handling for broken TZIDs
* Sony Ericsson: use ISO-8859-1 for all devices (BMC #14414)
Passing invalid UTF-8 strings into libecal caused glib to
abort syncevo-dbus-server.
* auto sync: show all failed syncs except for temporary network errors (BMC #21888)
Notifications were meant to be shown for all errors except temporary
ones. This has never been implemented correctly since the feature was
introduced: instead of hiding known temporary errors, all errors except
500 (fatal error) were suppressed.
* vCard: inline local photo data (BMC #19661)
Some platforms (Maemo, MeeGo) store photos in separate files. Now SyncEvolution
efficiently includes that photo data in the generated vCard right before sending
it to a peer; previously it sent a useless local file:// URI. The Maemo port
has a less efficient workaround for that which now should be obsolete.
* syncevo-dbus-server: online status wrong without Network Manager or ConnMan (BMC #21543)
When neither Network Manager nor ConnMan are running, network presence was "not
online". This prevented running automatic syncs.
For developers:
* modified backend API
- ClientTestConfig modernized
- InsertItemResult::m_merged turned from boolean to enum
* testing and compilation changes; for example, the minimum version of
libsynthesis is now checked at configure time instead of failing at
runtime due to missing features in the Synthesis engine
SyncEvolution 1.1.99.7 -> 1.2, 13.10.2011
=========================================
Some more bug fixes and testing improvements.
* fixed potential invalid memory access in add<->add conflict handling
* fixed memory leak in workaround for EDS bug
* CalDAV/CardDAV: handle ETags without quotation marks (eGroupware)
* updated README: warning about sync direction moved to --sync option
SyncEvolution 1.1.99.6 -> 1.1.99.7, 15.09.2011
==============================================
Mostly bug fixes again. Some are a bit more intrusive, thus another
pre-release.
* syncevolution.org binaries: now compatible with Debian Testing/libnotify.so.4 (BMC #22668)
libnotify is not linked directly into syncevo-dbus-server in the
syncevolution.org binaries. Instead libnotify.so.1 till .so.4
(current Debian Testing) are opened opened dynamically and the
necessary functions are looked up via dlsym(). Not finding the
libraries or the functions silently disables this notification
mechanism.
* calendar sync: better handling for add<->add conflicts (partly fixes BMC #22783)
When both sides of a sync have added the same event, the sync must
determine which one is more recent instead of blindly overwriting
always the same side. Such conflicts are typically rare except for
enterprise scenarios where meeting invitiations are processed
automatically by a groupware (Exchange, Google Calendar/Mail, ...)
and then the attendee status is updated on one side.
SyncEvolution now does the necessary age comparison and preserves the more
recent data for most properties. In some properties the data from both
sides is preserved by concatenating the text (description, location, ...).
It remains to be seen whether that is really desirable. Also, sync statistics
are slightly off: the incoming item is counted as "added" even though it
gets turned into an update.
* item operations: authentication problem for WebDAV when using keyring (BMC #21311)
The password still wasn't looked up in the keyring when using
--import/export/delete-items.
* "databasePassword" source property: lookup failure in keyring (BMC #22937)
The databasePassword also wasn't looked up at all when doing item operations
via the command line.
When configuring sources for an HTTP server, the config name typically
is just the context (@foo). When using the config in the HTTP server,
the config name is the peer inside that context (client@foo). Because
the GNOME keyring lookup keys for the "databasePassword" (more
specifically, the object name) contained the full config name which
was different in both cases, looking up the saved password failed.
The solution is to normalize the config name (to accomodate for
different ways of spelling it) and use only the context, with @ as
before. This will break existing setups where the object name in the
keyring (incorrectly) includes the full config name. In that case just
configure the source again to set the password anew.
* Evolution Calendar: fixed detached recurrence support (BMC #22940)
When manipulating a meeting series with more than one detached
recurrence certain sequences of operations could incorrectly fail
with "UID already exists".
* iCalendar 2.0: must set VALUE in EXDATE (part of BMC #22940)
EXDATE has a VALUE parameter, which wasn't defined in the XML
profile. Didn't seem to matter at all in practice, but wasn't
standard-compliant.
* GTK sync-ui: wrap sync service descriptions (BMC #7199)
Descriptions of different sync services are not fully visible unless
word-wrapping gets enabled.
* source configs: don't check "backend" unless it is needed
When using a config which has sources with a backend type set which is
not currently available, an error was thrown even if those sources
weren't even part of the current operation (for example, syncing
another source which is currently supported).
* config migration: avoid name conflicts and auto syncing of old configs (BMC #22691)
When (auto-)migrating a config, it was possible that a name for the
peer, say foo.old, was chosen for the renamed config although there
was already such a config, for example foo.old in ~/.sync4j. Besides
being confusing for users, this also led to a bug in the code where it
copied from the older config with the foo.old name.
The main problem fixed is the disabling of auto syncing
in the old config. Otherwise it was still used by syncevo-dbus-server
for syncing, which triggered another auto-migration, ad infinitum...
* auto syncing: must check whether enabled when looking at unknown URLs (part of BMC #22691)
"syncURL = insert your URL here" with "autoSync = 0" did lead to auto
sync attempts although it wasn't enabled. A check for "auto syncing
enabled" was missing for the "unknown transport" case.
* CalDAV/CardDAV + local storage: avoid empty properties
The main motivation for this change is that a recent Apple Calendar
server rejects vCards with empty BDAY property. Another reason is that
keeping the data as small as possible is desirable by itself.
Sending an empty property serves as a hint for the peer that the
property is supported. This is not necessary when storing an item in a
backend. Therefore this commit disables empty properties for all
backends which do not themselves set the m_backendRule Synthesis info
value.
* Apple CardDAV: apply PHOTO import/export scripts by default
A recent Apple Calendar server (correctly) rejects the invalid
PHOTO;TYPE=unknown: property in a vCard. This internal representation
must be cleared before serializing the field list.
* for developers: modified backend API
- ClientTestConfig modernized
- InsertItemResult::m_merged turned from boolean to enum
* testing and compilation changes; for example, the minimum version of
libsynthesis is now checked at configure time instead of failing at
runtime due to missing features in the Synthesis engine
SyncEvolution 1.1.99.5 -> 1.1.99.6, 17.08.2011
==============================================

View file

@ -274,6 +274,15 @@ a list of valid values.
for a `refresh-from-server` or `refresh-from-client` sync which
clears all data at one end and copies all items from the other.
**Warning:** in local sync (CalDAV/CardDAV/ActiveSync, ...) and
direct sync with a phone, the sync is started by the side which acts
as server. Therefore the ``from-server`` variants
(``one-way-from-server``, ``refresh-from-server``) transfer data
from the sync config into the target config (see "Synchronization
beyond SyncML" below) resp. to a phone. The ``from-client`` variants
transfer in the other direction, even if the target config happens
to access data on a remote server.
--print-servers|--print-configs|--print-peers
Prints the names of all configured peers to stdout. There is no
difference between these options, the are just aliases.
@ -661,13 +670,6 @@ source in the target config. The ``sync`` property in the sync config
defines the direction of the data flow. It can be set temporarily when
starting a synchronzation with the sync config.
**Warning:** in local sync, the sync config side acts as
server. Therefore the ``from-server`` variants
(``one-way-from-server``, ``refresh-from-server``) transfer data
from the sync config into the target config. The ``from-client``
variants transfer in the other direction, even if the target config
happens to access data on a remote server.
**Warning:** because the client in the local sync starts the sync,
``preventSlowSync=0`` must be set in the target config to have an effect.

View file

@ -8,7 +8,7 @@ dnl Invoke autogen.sh to produce a configure script.
#
# Starting with the 1.1 release cycle, the rpm-style
# .99 pseudo-version number is used to mark a pre-release.
AC_INIT([syncevolution], [1.1.99.6])
AC_INIT([syncevolution], [1.2])
# STABLE_VERSION=1.0.1+
AC_SUBST(STABLE_VERSION)
@ -20,6 +20,10 @@ AC_SUBST(STABLE_VERSION)
# SyncEvolution >= 1.1.99.5: release mode by default
define([STABLE_RELEASE], [yes])
# Minimum version of libsynthesis as defined in its
# configure script and thus .pc files:
define([SYNTHESIS_MIN_VERSION], [3.4.0.16.4])
# Line above is patched by gen-autotools.sh. Handle
# both "yes" and "no".
define([STABLE_RELEASE_HELP], ifelse(STABLE_RELEASE,yes,--disable-release-mode,--enable-release-mode))
@ -509,6 +513,17 @@ if test $enable_dbus_service = "yes"; then
AC_DEFINE(HAS_NOTIFY, 1, [define if libnotify could be used in dbus service])
fi
AC_ARG_ENABLE(notify-compatibility,
AS_HELP_STRING([--enable-notify-compatibility],
[increase compatibility with binary libnotify installations by loading libnotify.so.1..4 dynamically instead of linking against it]),
[enable_notify_compat="$enableval"],
[enable_notify_compat="no"]
)
if test "$enable_notify_compat" = "yes"; then
AC_DEFINE(NOTIFY_COMPATIBILITY, 1, [dynamically open libnotify])
LIBNOTIFY_LIBS="`echo $LIBNOTIFY_LIBS | sed -e 's/\(-lnotify\|[^ ]*libnotify.la\)/-ldl/'`"
fi
# Here we're using QtGui too because mlite fails to depend on it,
# despite using QAction.
PKG_CHECK_MODULES(MLITE, [mlite QtGui], HAVE_MLITE=yes, HAVE_MLITE=no)
@ -527,6 +542,8 @@ if test $enable_dbus_service = "yes"; then
fi
AC_DEFINE(DBUS_SERVICE, 1, [define if dbus service is enabled])
fi
AM_CONDITIONAL([NOTIFY_COMPATIBILITY], [test "$enable_notify_compat" = "yes"])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
AC_SUBST(DBUS_GLIB_CFLAGS)
@ -721,7 +738,7 @@ else
#SYNTHESIS_ENGINE="`echo $SYNTHESIS_LIBS | sed -e 's/-lsynthesisstubs/-lsynthesis/'`"
# can't use the SDK alone because of sysync::SySyncDebugPuts()
PKG_CHECK_MODULES([SYNTHESIS], [synthesis >= 3.4.0.16.1])
PKG_CHECK_MODULES([SYNTHESIS], [synthesis >= SYNTHESIS_MIN_VERSION])
SYNTHESIS_ENGINE="$SYNTHESIS_LIBS"
fi
@ -762,6 +779,13 @@ if test $SYNTHESIS_SRC != "no-synthesis-source"; then
if (set -x; mkdir -p $SYNTHESIS_SUBDIR && cd $SYNTHESIS_SUBDIR && eval "\$SHELL \"\$SYNTHESIS_CONFIGURE\" $ac_configure_args \"--srcdir=\$SYNTHESIS_SRC\" " ); then true; else
AC_MSG_ERROR( [configuring Synthesis library failed] )
fi
# do the version check with the .pc files prepared by the configure step above
export PKG_CONFIG_PATH=$SYNTHESIS_SUBDIR:$PKG_CONFIG_PATH
PKG_CHECK_MODULES([WITH_SYNTHESIS_SRC], [synthesis >= SYNTHESIS_MIN_VERSION],
[],
[AC_MSG_ERROR([need at least libsynthesis >= SYNTHESIS_MIN_VERSION; the latest libsynthesis for SyncEvolution is the one from http://meego.gitorious.org/meego-middleware/libsynthesis])])
fi
AC_SUBST(SYNTHESIS_CFLAGS)

8
debian/changelog vendored
View file

@ -1,3 +1,11 @@
syncevolution (1:1.2.0-4) unstable; urgency=low
* SyncEvolution 1.2 for Harmattan.
* Packaging updates for Fremantle merged into Harmattan tree
(that's the reason for the version number jump on Harmattan).
-- Ove Kaaven <ovek@arcticnet.no> Sun, 20 Nov 2011 19:19:24 +0100
syncevolution (1:1.1.99.6-2) unstable; urgency=low
* Removed static libraries.

View file

@ -24,13 +24,46 @@
#if HAS_NOTIFY
#include "NotificationBackendLibnotify.h"
#include "syncevo/util.h"
#include <stdlib.h>
#include <glib/gi18n.h>
#include <boost/algorithm/string/predicate.hpp>
#ifdef NOTIFY_COMPATIBILITY
# include <dlfcn.h>
#endif
SE_BEGIN_CXX
#ifdef NOTIFY_COMPATIBILITY
/**
* set to real old C notify_notification_new() (with widget pointer) or new one (without);
* because of the x86/AMD64 calling conventions, calling the newer function with
* one extra parameter is okay
*/
gboolean (*notify_init)(const char *app_name);
GList *(*notify_get_server_caps)(void);
NotifyNotification *(*notify_notification_new)(const char *summary, const char *body, const char *icon, void *widget);
void (*notify_notification_add_action)(NotifyNotification *notification,
const char *action,
const char *label,
NotifyActionCallback callback,
gpointer user_data,
GFreeFunc free_func);
void (*notify_notification_clear_actions)(NotifyNotification *notification);
gboolean (*notify_notification_close)(NotifyNotification *notification,
GError **error);
gboolean (*notify_notification_show)(NotifyNotification *notification,
GError **error);
static bool NotFound(const char *func)
{
SE_LOG_DEBUG(NULL, NULL, "%s: not found", func);
return false;
}
#endif
NotificationBackendLibnotify::NotificationBackendLibnotify()
: m_initialized(false),
m_acceptsActions(false),
@ -64,6 +97,36 @@ bool NotificationBackendLibnotify::init()
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#ifdef NOTIFY_COMPATIBILITY
void *dlhandle = NULL;
int i;
for (i = 1; i <= 4; i++) {
dlhandle = dlopen(StringPrintf("libnotify.so.%d", i).c_str(), RTLD_LAZY|RTLD_GLOBAL);
if (!dlhandle) {
SE_LOG_DEBUG(NULL, NULL, "failed to load libnotify.so.%d: %s", i, dlerror());
} else {
break;
}
}
if (!dlhandle) {
return false;
}
#define LOOKUP(_x) ((_x = reinterpret_cast<typeof(_x)>(dlsym(dlhandle, #_x))) || \
NotFound(#_x))
if (!LOOKUP(notify_init) ||
!LOOKUP(notify_get_server_caps) ||
!LOOKUP(notify_notification_new) ||
!LOOKUP(notify_notification_add_action) ||
!LOOKUP(notify_notification_clear_actions) ||
!LOOKUP(notify_notification_close) ||
!LOOKUP(notify_notification_show)) {
return false;
}
SE_LOG_DEBUG(NULL, NULL, "using libnotify.so.%d", i);
#endif
m_initialized = notify_init("SyncEvolution");
if(m_initialized) {
GList *list = notify_get_server_caps();
@ -94,7 +157,7 @@ void NotificationBackendLibnotify::publish(
#ifndef NOTIFY_CHECK_VERSION
# define NOTIFY_CHECK_VERSION(_x,_y,_z) 0
#endif
#if !NOTIFY_CHECK_VERSION(0,7,0)
#if !NOTIFY_CHECK_VERSION(0,7,0) || defined(NOTIFY_COMPATIBILITY)
m_notification = notify_notification_new(summary.c_str(), body.c_str(), NULL, NULL);
#else
m_notification = notify_notification_new(summary.c_str(), body.c_str(), NULL);

View file

@ -101,7 +101,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "apple-contacts:text/x-vcard";
config.m_type = "apple-contacts:text/x-vcard";
}
} vCard21Test;
@ -111,7 +111,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "apple-contacts:text/vcard";
config.m_type = "apple-contacts:text/vcard";
}
} vCard30Test;

View file

@ -348,7 +348,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "kde-calendar";
config.m_type = "kde-calendar";
}
} iCal20Test;
@ -358,7 +358,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "kde-tasks";
config.m_type = "kde-tasks";
}
} iTodo20Test;
@ -368,7 +368,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "KDE Memos"; // use an alias here to test that
config.m_type = "KDE Memos"; // use an alias here to test that
}
} memoTest;

View file

@ -198,7 +198,7 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
ItemCreateJob *createJob = new ItemCreateJob(item, m_collection);
if (!createJob->exec()) {
throwError(string("storing new item ") + luid);
return InsertItemResult("", "", false);
return InsertItemResult("", "", ITEM_OKAY);
}
item = createJob->item();
} else {
@ -215,7 +215,7 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
// TODO: check that the item has not been updated in the meantime
if (!modifyJob->exec()) {
throwError(string("updating item ") + luid);
return InsertItemResult("", "", false);
return InsertItemResult("", "", ITEM_OKAY);
}
item = modifyJob->item();
}
@ -225,7 +225,7 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
// above will take care of this
return InsertItemResult(QByteArray::number(item.id()).constData(),
QByteArray::number(item.revision()).constData(),
false);
ITEM_OKAY);
}
void AkonadiSyncSource::removeItem(const string &luid)

View file

@ -14,7 +14,7 @@ if ! test "$KDEPIM_CFLAGS"; then
fi
fi
if ! test "$KDEPIM_LIBS"; then
KDEPIM_LIBS="-L`kde4-config --prefix`/lib`kde4-config --libsuffix` -lakonadi-kde"
KDEPIM_LIBS="-L`kde4-config --prefix`/lib`kde4-config --libsuffix` -lakonadi-kde -lQtDBus -lQtCore -lkdeui -lkdecore"
fi
AC_LANG_PUSH(C++)
old_CPPFLAGS="$CPPFLAGS"

View file

@ -56,6 +56,32 @@ class unrefECalObjectList {
}
};
bool EvolutionCalendarSource::LUIDs::containsLUID(const ItemID &id) const
{
const_iterator it = findUID(id.m_uid);
return it != end() &&
it->second.find(id.m_rid) != it->second.end();
}
void EvolutionCalendarSource::LUIDs::insertLUID(const ItemID &id)
{
(*this)[id.m_uid].insert(id.m_rid);
}
void EvolutionCalendarSource::LUIDs::eraseLUID(const ItemID &id)
{
iterator it = find(id.m_uid);
if (it != end()) {
set<string>::iterator it2 = it->second.find(id.m_rid);
if (it2 != it->second.end()) {
it->second.erase(it2);
if (it->second.empty()) {
erase(it);
}
}
}
}
static int granularity()
{
// This long delay is necessary in combination
@ -254,7 +280,7 @@ void EvolutionCalendarSource::listAllItems(RevisionMap_t &revisions)
string luid = id.getLUID();
string modTime = getItemModTime(ecomp);
m_allLUIDs.insert(luid);
m_allLUIDs.insertLUID(id);
revisions[luid] = modTime;
nextItem = nextItem->next;
}
@ -274,7 +300,7 @@ void EvolutionCalendarSource::readItem(const string &luid, std::string &item, bo
EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(const string &luid, const std::string &item, bool raw)
{
bool update = !luid.empty();
bool merged = false;
InsertItemResultState state = ITEM_OKAY;
bool detached = false;
string newluid = luid;
string data = item;
@ -389,14 +415,14 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
// gets used twice during a sync (examples: add + add, delete + add),
// which should never happen.
newluid = id.getLUID();
if (m_allLUIDs.find(newluid) != m_allLUIDs.end()) {
merged = true;
if (m_allLUIDs.containsLUID(id)) {
state = ITEM_NEEDS_MERGE;
} else {
// if this is a detached recurrence, then we
// must use e_cal_modify_object() below if
// the parent already exists
// the parent or any other child already exists
if (!id.m_rid.empty() &&
m_allLUIDs.find(ItemID::getLUID(id.m_uid, "")) != m_allLUIDs.end()) {
m_allLUIDs.containsUID(id.m_uid)) {
detached = true;
} else {
// Creating the parent while children are already in
@ -420,7 +446,7 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
ItemID newid(!id.m_uid.empty() ? id.m_uid : uid, id.m_rid);
newluid = newid.getLUID();
modTime = getItemModTime(newid);
m_allLUIDs.insert(newluid);
m_allLUIDs.insertLUID(newid);
} else {
throwError("storing new item", gerror);
}
@ -438,7 +464,7 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
}
}
if (update || merged || detached) {
if (update || state != ITEM_NEEDS_MERGE || detached) {
ItemID id(newluid);
bool isParent = id.m_rid.empty();
@ -475,11 +501,13 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
// Therefore we have to use CALOBJ_MOD_ALL, but that removes
// children.
bool hasChildren = false;
BOOST_FOREACH(ItemID existingId, m_allLUIDs) {
if (existingId.m_uid == id.m_uid &&
existingId.m_rid.size()) {
hasChildren = true;
break;
LUIDs::const_iterator it = m_allLUIDs.find(id.m_uid);
if (it != m_allLUIDs.end()) {
BOOST_FOREACH(const string &rid, it->second) {
if (!rid.empty()) {
hasChildren = true;
break;
}
}
}
@ -526,17 +554,17 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
modTime = getItemModTime(newid);
}
return InsertItemResult(newluid, modTime, merged);
return InsertItemResult(newluid, modTime, state);
}
EvolutionCalendarSource::ICalComps_t EvolutionCalendarSource::removeEvents(const string &uid, bool returnOnlyChildren)
{
ICalComps_t events;
BOOST_FOREACH(const string &luid, m_allLUIDs) {
ItemID id(luid);
if (id.m_uid == uid) {
LUIDs::const_iterator it = m_allLUIDs.find(uid);
if (it != m_allLUIDs.end()) {
BOOST_FOREACH(const string &rid, it->second) {
ItemID id(uid, rid);
icalcomponent *icomp = retrieveItem(id);
if (icomp) {
if (id.m_rid.empty() && returnOnlyChildren) {
@ -582,11 +610,21 @@ void EvolutionCalendarSource::removeItem(const string &luid)
ICalComps_t children = removeEvents(id.m_uid, true);
// recreate children
bool first = true;
BOOST_FOREACH(boost::shared_ptr< eptr<icalcomponent> > &icalcomp, children) {
char *uid;
if (first) {
char *uid;
if (!e_cal_create_object(m_calendar, *icalcomp, &uid, &gerror)) {
throwError(string("recreating item ") + luid, gerror);
if (!e_cal_create_object(m_calendar, *icalcomp, &uid, &gerror)) {
throwError(string("recreating first item ") + luid, gerror);
}
first = false;
} else {
if (!e_cal_modify_object(m_calendar, *icalcomp,
CALOBJ_MOD_THIS,
&gerror)) {
throwError(string("recreating following item ") + luid, gerror);
}
}
}
} else if(!e_cal_remove_object_with_mod(m_calendar,
@ -603,7 +641,7 @@ void EvolutionCalendarSource::removeItem(const string &luid)
throwError(string("deleting item " ) + luid, gerror);
}
}
m_allLUIDs.erase(luid);
m_allLUIDs.eraseLUID(id);
if (!id.m_rid.empty()) {
// Removing the child may have modified the parent.
@ -642,8 +680,21 @@ icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
if (!comp) {
throwError(string("retrieving item: ") + id.getLUID());
}
eptr<icalcomponent> ptr(comp);
return comp;
/*
* EDS bug: if a parent doesn't exist while a child does, and we ask
* for the parent, we are sent the (first?) child. Detect this and
* turn it into a "not found" error.
*/
if (id.m_rid.empty()) {
struct icaltimetype rid = icalcomponent_get_recurrenceid(comp);
if (!icaltime_is_null_time(rid)) {
throwError(string("retrieving item: got child instead of parent: ") + id.m_uid);
}
}
return ptr.release();
}
string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)

View file

@ -179,7 +179,15 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
* implemented without the troublesome querying of the EDS
* backend.
*/
set<string> m_allLUIDs;
class LUIDs : public map< string, set<string> > {
public:
bool containsUID(const std::string &uid) const { return findUID(uid) != end(); }
const_iterator findUID(const std::string &uid) const { return find(uid); }
bool containsLUID(const ItemID &id) const;
void insertLUID(const ItemID &id);
void eraseLUID(const ItemID &id);
} m_allLUIDs;
/**
* A list of ref-counted smart pointers to icalcomponents.

View file

@ -317,7 +317,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "evolution-calendar";
config.m_type = "evolution-calendar";
}
} iCal20Test;
@ -327,7 +327,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "evolution-tasks";
config.m_type = "evolution-tasks";
}
} iTodo20Test;
@ -337,8 +337,8 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "virtual:text/x-vcalendar";
config.subConfigs = "eds_event,eds_task";
config.m_type = "virtual:text/x-vcalendar";
config.m_subConfigs = "eds_event,eds_task";
}
} superTest;
@ -349,7 +349,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "Evolution Memos"; // use an alias here to test that
config.m_type = "Evolution Memos"; // use an alias here to test that
}
} memoTest;

View file

@ -330,7 +330,7 @@ EvolutionContactSource::insertItem(const string &uid, const std::string &item, b
throwError("no UID for contact");
}
string newrev = getRevision(newuid);
return InsertItemResult(newuid, newrev, false);
return InsertItemResult(newuid, newrev, ITEM_OKAY);
} else {
throwError(uid.empty() ?
"storing new contact" :
@ -341,7 +341,7 @@ EvolutionContactSource::insertItem(const string &uid, const std::string &item, b
throwError(string("failure parsing vcard " ) + item);
}
// not reached!
return InsertItemResult("", "", false);
return InsertItemResult("", "", ITEM_OKAY);
}
void EvolutionContactSource::removeItem(const string &uid)

View file

@ -152,8 +152,8 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "evolution-contacts:text/vcard";
config.update = config.genericUpdate;
config.m_type = "evolution-contacts:text/vcard";
config.m_update = config.m_genericUpdate;
}
} vCard30Test;

View file

@ -122,7 +122,7 @@ EvolutionCalendarSource::InsertItemResult EvolutionMemoSource::insertItem(const
}
bool update = !luid.empty();
bool merged = false;
InsertItemResultState state = ITEM_OKAY;
string newluid = luid;
string modTime;
@ -170,28 +170,31 @@ EvolutionCalendarSource::InsertItemResult EvolutionMemoSource::insertItem(const
}
GError *gerror = NULL;
char *uid = NULL;
if (!update) {
if(!e_cal_create_object(m_calendar, subcomp, &uid, &gerror)) {
const char *uid = NULL;
if(!e_cal_create_object(m_calendar, subcomp, (char **)&uid, &gerror)) {
if (gerror->domain == E_CALENDAR_ERROR &&
gerror->code == E_CALENDAR_STATUS_OBJECT_ID_ALREADY_EXISTS) {
// Deal with error due to adding already existing item.
// Should never happen for plain text journal entries because
// they have no embedded ID, but who knows...
merged = true;
state = ITEM_NEEDS_MERGE;
uid = icalcomponent_get_uid(subcomp);
if (!uid) {
throwError("storing new memo item, no UID set", gerror);
}
g_clear_error(&gerror);
} else {
throwError( "storing new memo item", gerror );
}
} else {
ItemID id(uid, "");
newluid = id.getLUID();
}
ItemID id(uid, "");
newluid = id.getLUID();
if (state != ITEM_NEEDS_MERGE) {
modTime = getItemModTime(id);
}
}
if (update || merged) {
} else {
ItemID id(newluid);
// ensure that the component has the right UID
@ -207,7 +210,7 @@ EvolutionCalendarSource::InsertItemResult EvolutionMemoSource::insertItem(const
modTime = getItemModTime(newid);
}
return InsertItemResult(newluid, modTime, merged);
return InsertItemResult(newluid, modTime, state);
}
bool EvolutionMemoSource::isNativeType(const char *type)

View file

@ -233,7 +233,7 @@ TrackingSyncSource::InsertItemResult FileSyncSource::insertItem(const string &ui
return InsertItemResult(newuid,
getATimeString(filename),
false /* true if adding item was turned into update */);
ITEM_OKAY);
}

View file

@ -121,7 +121,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "file:text/vcard:3.0";
config.m_type = "file:text/vcard:3.0";
}
} VCard30Test;
@ -131,7 +131,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "file:text/calendar:2.0";
config.m_type = "file:text/calendar:2.0";
// A sync source which supports linked items (= recurring
// event with detached exception) is expected to handle
@ -143,7 +143,7 @@ public:
// Client::Source::file_event::testLinkedItemsInsertChildTwice
//
// Disable linked item testing to avoid this.
config.sourceKnowsItemSemantic = false;
config.m_sourceKnowsItemSemantic = false;
}
} ICal20Test;
@ -153,7 +153,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "file:text/calendar:2.0";
config.m_type = "file:text/calendar:2.0";
}
} ITodo20Test;
@ -163,8 +163,8 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "virtual:text/x-vcalendar";
config.subConfigs = "file_event,file_task";
config.m_type = "virtual:text/x-vcalendar";
config.m_subConfigs = "file_event,file_task";
}
} superTest;

View file

@ -93,10 +93,10 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "KCalExtended:text/calendar";
config.m_type = "KCalExtended:text/calendar";
// after fixing BMC #6061, mKCal is able to delete individual
// VEVENTs, without enforcing the "each child must have parent" rule
config.linkedItemsRelaxedSemantic = true;
config.m_linkedItemsRelaxedSemantic = true;
}
} iCal20Test;

View file

@ -73,6 +73,14 @@ std::string MaemoCalendarSource::getMimeVersion() const
}
}
void MaemoCalendarSource::getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments)
{
TrackingSyncSource::getSynthesisInfo(info, fragments);
info.m_backendRule = "MAEMO-CALENDAR";
info.m_afterReadScript += "$FIX_EXDATE_SCRIPT;\n";
}
void MaemoCalendarSource::open()
{
string id = getDatabaseID();
@ -211,7 +219,8 @@ TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const strin
{
int err;
CComponent *c;
bool r, u = false;
bool r;
InsertItemResultState u = ITEM_OKAY;
TrackingSyncSource::InsertItemResult result;
if (cal->getCalendarType() == BIRTHDAY_CALENDAR) {
@ -270,7 +279,7 @@ TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const strin
throwError(string("creating item "));
}
if (err == CALENDAR_ENTRY_DUPLICATED) {
u = true;
u = ITEM_MERGED;
}
}

View file

@ -56,6 +56,8 @@ class MaemoCalendarSource : public TrackingSyncSource, private boost::noncopyabl
virtual Databases getDatabases();
virtual std::string getMimeType() const;
virtual std::string getMimeVersion() const;
virtual void getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments);
/* implementation of TrackingSyncSource interface */
virtual void listAllItems(RevisionMap_t &revisions);

View file

@ -137,7 +137,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "maemo-events";
config.m_type = "maemo-events";
}
} iCal20Test;
@ -147,7 +147,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "maemo-tasks";
config.m_type = "maemo-tasks";
}
} iTodo20Test;
@ -157,7 +157,7 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "maemo-notes";
config.m_type = "maemo-notes";
}
} memoTest;

View file

@ -202,8 +202,8 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "qt-contacts:text/vcard";
config.testcases = "testcases/qt_contact.vcf";
config.m_type = "qt-contacts:text/vcard";
config.m_testcases = "testcases/qt_contact.vcf";
}
} vCard30Test;

View file

@ -99,8 +99,8 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = "sqlite-contacts:text/x-vcard";
config.testcases = "testcases/sqlite_vcard21.vcf";
config.m_type = "sqlite-contacts:text/x-vcard";
config.m_testcases = "testcases/sqlite_vcard21.vcf";
}
} VCard21Test;

View file

@ -25,6 +25,22 @@ static std::string SubIDName(const std::string &subid)
return subid.empty() ? "<master>" : subid;
}
/** remove X-SYNCEVOLUTION-EXDATE-DETACHED from VEVENT */
static void removeSyncEvolutionExdateDetached(icalcomponent *parent)
{
icalproperty *prop = icalcomponent_get_first_property(parent, ICAL_ANY_PROPERTY);
while (prop) {
icalproperty *next = icalcomponent_get_next_property(parent, ICAL_ANY_PROPERTY);
const char *xname = icalproperty_get_x_name(prop);
if (xname &&
!strcmp(xname, "X-SYNCEVOLUTION-EXDATE-DETACHED")) {
icalcomponent_remove_property(parent, prop);
icalproperty_free(prop);
}
prop = next;
}
}
CalDAVSource::CalDAVSource(const SyncSourceParams &params,
const boost::shared_ptr<Neon::Settings> &settings) :
WebDAVSource(params, settings)
@ -328,6 +344,10 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
comp = icalcomponent_get_next_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT)) {
std::string subid = Event::getSubID(comp);
EventCache::iterator it;
// remove X-SYNCEVOLUTION-EXDATE-DETACHED, could be added by
// the engine's read/modify/write cycle when resolving a
// conflict
removeSyncEvolutionExdateDetached(comp);
if (!luid.empty() &&
(it = m_cache.find(luid)) != m_cache.end()) {
// Additional sanity check: ensure that the expected UID is set.
@ -433,8 +453,9 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
Event &event = loadItem(*it->second);
event.m_etag = res.m_revision;
if (event.m_subids.find(subid) != event.m_subids.end()) {
// was already in that item but caller didn't seem to know
subres.m_merged = true;
// was already in that item but caller didn't seem to know,
// and now we replaced the data on the CalDAV server
subres.m_state = ITEM_REPLACED;
} else {
// add to merged item
event.m_subids.insert(subid);
@ -466,6 +487,7 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
icalproperty *lastmod = icalcomponent_get_first_property(firstcomp, ICAL_LASTMODIFIED_PROPERTY);
if (lastmod) {
lastmodtime = icaltime_from_timet(newEvent->m_lastmodtime, false);
lastmodtime.is_utc = 1;
icalproperty_set_lastmodified(lastmod, lastmodtime);
}
icalproperty *dtstamp = icalcomponent_get_first_property(firstcomp, ICAL_DTSTAMP_PROPERTY);
@ -496,10 +518,55 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
}
}
} else {
if (subid != knownSubID) {
SE_THROW("new CalDAV item does not have right RECURRENCE-ID");
if (!subid.empty() && subid != knownSubID) {
SE_THROW(StringPrintf("new CalDAV item does not have right RECURRENCE-ID: item %s != expected %s",
subid.c_str(), knownSubID.c_str()));
}
Event &event = loadItem(davLUID);
if (subid.empty() && subid != knownSubID) {
// fix incomplete iCalendar 2.0 item: should have had a RECURRENCE-ID
icalcomponent *newcomp =
icalcomponent_get_first_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT);
icalproperty *prop = icalcomponent_get_first_property(newcomp, ICAL_RECURRENCEID_PROPERTY);
if (prop) {
icalcomponent_remove_property(newcomp, prop);
icalproperty_free(prop);
}
// reconstruct RECURRENCE-ID with known value and TZID from start time of
// the parent event or (if not found) the current event
eptr<icalproperty> rid(icalproperty_new_recurrenceid(icaltime_from_string(knownSubID.c_str())),
"new rid");
icalproperty *dtstart = NULL;
icalcomponent *comp;
// look for parent first
for (comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
comp && !dtstart;
comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
if (!icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY)) {
dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
}
}
// fall back to current event
if (!dtstart) {
dtstart = icalcomponent_get_first_property(newcomp, ICAL_DTSTART_PROPERTY);
}
// ignore missing TZID
if (dtstart) {
icalparameter *tzid = icalproperty_get_first_parameter(dtstart, ICAL_TZID_PARAMETER);
if (tzid) {
icalproperty_set_parameter(rid, icalparameter_new_clone(tzid));
}
}
// finally add RECURRENCE-ID and fix newEvent's meta information
icalcomponent_add_property(newcomp, rid.release());
subid = knownSubID;
newEvent->m_subids.erase("");
newEvent->m_subids.insert(subid);
}
// no changes expected yet, copy previous attributes
subres.m_mainid = davLUID;
subres.m_uid = event.m_UID;
@ -547,13 +614,11 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
}
}
if (davLUID != luid) {
// caller didn't know final UID: if found, the tell him that
// we merged the item for him, if not, then don't complain about
// it not being found (like we do when the item should exist
// but doesn't)
// caller didn't know final UID: if found, then tell him to
// merge the data and try again
if (removeme) {
subres.m_merged = true;
icalcomponent_remove_component(event.m_calendar, removeme);
subres.m_state = ITEM_NEEDS_MERGE;
goto done;
} else {
event.m_subids.insert(subid);
}
@ -561,6 +626,7 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
if (removeme) {
// this is what we expect when the caller mentions the DAV LUID
icalcomponent_remove_component(event.m_calendar, removeme);
icalcomponent_free(removeme);
} else {
// caller confused?!
SE_THROW("event not found");
@ -583,7 +649,7 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
try {
SE_LOG_DEBUG(this, NULL, "updating VEVENT");
InsertItemResult res = insertItem(event.m_DAVluid, data, true);
if (res.m_merged ||
if (res.m_state != ITEM_OKAY ||
res.m_luid != event.m_DAVluid) {
// should not merge with anything, if so, our cache was invalid
SE_THROW("CalDAV item not updated as expected");
@ -615,12 +681,56 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
subres.m_merged = true;
subres.m_revision = event.m_etag;
#endif
} else if (ex.syncMLStatus() == 409 &&
strstr(ex.what(), "Can only store an event with a newer DTSTAMP")) {
SE_LOG_DEBUG(NULL, NULL, "resending VEVENT with updated SEQUENCE/LAST-MODIFIED/DTSTAMP to work around 409");
// Sometimes a PUT of two linked events updates one of them on the server
// (visible in modified SEQUENCE and LAST-MODIFIED values) and then
// fails with 409 because, presumably, the other item now has
// too low SEQUENCE/LAST-MODIFIED/DTSTAMP values.
//
// An attempt with splitting the PUT in advance worked for some cases,
// but then it still happened for others. So let's use brute force and
// try again once more after reading the updated event anew.
eptr<icalcomponent> fullcal = event.m_calendar;
loadItem(event);
event.m_sequence++;
lastmodtime = icaltime_from_timet(event.m_lastmodtime, false);
lastmodtime.is_utc = 1;
event.m_calendar = fullcal;
for (icalcomponent *comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
comp;
comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
if (!icaltime_is_null_time(lastmodtime)) {
icalproperty *dtstamp = icalcomponent_get_first_property(comp, ICAL_DTSTAMP_PROPERTY);
if (dtstamp) {
icalproperty_set_dtstamp(dtstamp, lastmodtime);
}
icalproperty *lastmod = icalcomponent_get_first_property(comp, ICAL_LASTMODIFIED_PROPERTY);
if (lastmod) {
icalproperty_set_lastmodified(lastmod, lastmodtime);
}
}
Event::setSequence(comp, event.m_sequence);
}
eptr<char> icalstr(ical_strdup(icalcomponent_as_ical_string(event.m_calendar)));
std::string data = icalstr.get();
InsertItemResult res = insertItem(event.m_DAVluid, data, true);
if (res.m_state != ITEM_OKAY ||
res.m_luid != event.m_DAVluid) {
// should not merge with anything, if so, our cache was invalid
SE_THROW("CalDAV item not updated as expected");
}
event.m_etag = res.m_revision;
subres.m_revision = event.m_etag;
} else {
throw;
}
}
}
done:
return subres;
}
@ -646,19 +756,57 @@ void CalDAVSource::readSubItem(const std::string &davLUID, const std::string &su
icalcomponent_add_component(calendar, clone.release());
}
bool found = false;
icalcomponent *parent = NULL;
for (icalcomponent *comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
comp;
comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
if (Event::getSubID(comp) == subid) {
eptr<icalcomponent> clone(icalcomponent_new_clone(comp), "VEVENT");
if (subid.empty()) {
parent = clone.get();
}
icalcomponent_add_component(calendar, clone.release());
found = true;
break;
}
}
if (!found) {
SE_THROW("event not found");
}
// tell engine and peers about EXDATEs implied by
// RECURRENCE-IDs in detached recurrences by creating
// X-SYNCEVOLUTION-EXDATE-DETACHED in the parent
if (parent && event.m_subids.size() > 1) {
// remove all old X-SYNCEVOLUTION-EXDATE-DETACHED (just in case)
removeSyncEvolutionExdateDetached(parent);
// now populate with RECURRENCE-IDs of detached recurrences
for (icalcomponent *comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
comp;
comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
icalproperty *prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY);
if (prop) {
eptr<char> rid(ical_strdup(icalproperty_get_value_as_string(prop)));
icalproperty *exdate = icalproperty_new_from_string(StringPrintf("X-SYNCEVOLUTION-EXDATE-DETACHED:%s", rid.get()).c_str());
if (exdate) {
icalparameter *tzid = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
if (tzid) {
icalproperty_add_parameter(exdate, icalparameter_new_clone(tzid));
}
#if 0
// not needed
if (icalproperty_get_recurrenceid(exdate).is_date) {
icalproperty_add_parameter(exdate, icalparameter_new_value(ICAL_VALUE_DATE));
}
#endif
icalcomponent_add_property(parent, exdate);
}
}
}
}
eptr<char> icalstr(ical_strdup(icalcomponent_as_ical_string(calendar)));
item = icalstr.get();
}
@ -720,10 +868,12 @@ std::string CalDAVSource::removeSubItem(const string &davLUID, const std::string
icalproperty *prop;
while ((prop = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY)) != NULL) {
icalcomponent_remove_property(comp, prop);
icalproperty_free(prop);
updated = true;
}
while ((prop = icalcomponent_get_first_property(comp, ICAL_EXDATE_PROPERTY)) != NULL) {
icalcomponent_remove_property(comp, prop);
icalproperty_free(prop);
updated = true;
}
}
@ -802,7 +952,7 @@ std::string CalDAVSource::removeSubItem(const string &davLUID, const std::string
} else {
res = insertItem(davLUID, icalstr.get(), true);
}
if (res.m_merged ||
if (res.m_state != ITEM_OKAY ||
res.m_luid != davLUID) {
SE_THROW("unexpected result of removing sub event");
}
@ -1012,6 +1162,7 @@ void CalDAVSource::Event::fixIncomingCalendar(icalcomponent *calendar)
// time.
bool ridInUTC = false;
const icaltimezone *zone = NULL;
icalcomponent *parent = NULL;
for (icalcomponent *comp = icalcomponent_get_first_component(calendar, ICAL_VEVENT_COMPONENT);
comp;
@ -1025,6 +1176,7 @@ void CalDAVSource::Event::fixIncomingCalendar(icalcomponent *calendar)
// is parent event? -> remember time zone unless it is UTC
static const struct icaltimetype null = { 0 };
if (!memcmp(&rid, &null, sizeof(null))) {
parent = comp;
struct icaltimetype dtstart = icalcomponent_get_dtstart(comp);
if (!icaltime_is_utc(dtstart)) {
zone = icaltime_get_timezone(dtstart);

View file

@ -44,6 +44,10 @@ class CalDAVSource : public WebDAVSource,
virtual std::string removeSubItem(const string &uid, const std::string &subid);
virtual void flushItem(const string &uid);
virtual std::string getSubDescription(const string &uid, const string &subid);
virtual void updateSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments) {
info.m_backendRule = "HAVE-SYNCEVOLUTION-EXDATE-DETACHED";
}
// implementation of SyncSourceLogging callback
virtual std::string getDescription(const string &luid);

View file

@ -1020,7 +1020,7 @@ TrackingSyncSource::InsertItemResult WebDAVSource::insertItem(const string &uid,
{
std::string new_uid;
std::string rev;
bool update = false; /* true if adding item was turned into update */
InsertItemResultState state = ITEM_OKAY;
Timespec deadline = createDeadline(); // no resending if left empty
m_session->startOperation("PUT", deadline);
@ -1087,7 +1087,7 @@ TrackingSyncSource::InsertItemResult WebDAVSource::insertItem(const string &uid,
SE_LOG_DEBUG(NULL, NULL, "new item mapped to %s", real_luid.c_str());
new_uid = real_luid;
// TODO: find a better way of detecting unexpected updates.
// update = true;
// state = ...
} else if (!rev.empty()) {
// Yahoo Contacts returns an etag, but no href. For items
// that were really created as requested, that's okay. But
@ -1114,7 +1114,7 @@ TrackingSyncSource::InsertItemResult WebDAVSource::insertItem(const string &uid,
new_uid.c_str(),
revisions.begin()->first.c_str());
new_uid = revisions.begin()->first;
update = true;
state = ITEM_REPLACED;
}
}
} else {
@ -1182,7 +1182,7 @@ TrackingSyncSource::InsertItemResult WebDAVSource::insertItem(const string &uid,
}
}
return InsertItemResult(new_uid, rev, update);
return InsertItemResult(new_uid, rev, state);
}
std::string WebDAVSource::ETag2Rev(const std::string &etag)
@ -1191,7 +1191,9 @@ std::string WebDAVSource::ETag2Rev(const std::string &etag)
if (boost::starts_with(res, "W/")) {
res.erase(0, 2);
}
if (res.size() >= 2) {
if (res.size() >= 2 &&
res[0] == '"' &&
res[res.size() - 1] == '"') {
res = res.substr(1, res.size() - 2);
}
return res;

View file

@ -229,13 +229,16 @@ public:
virtual void updateConfig(ClientTestConfig &config) const
{
config.type = m_type.c_str();
config.createSourceA = boost::bind(&WebDAVTest::createSource, this, _3);
config.createSourceB = boost::bind(&WebDAVTest::createSource, this, _3);
config.m_type = m_type.c_str();
if (m_type == "caldav") {
config.m_supportsReccurenceEXDates = true;
}
config.m_createSourceA = boost::bind(&WebDAVTest::createSource, this, _3);
config.m_createSourceB = boost::bind(&WebDAVTest::createSource, this, _3);
ConfigProps::const_iterator it = m_props.find(m_type + "/testcases");
if (it != m_props.end() ||
(it = m_props.find("testcases")) != m_props.end()) {
config.testcases = it->second.c_str();
config.m_testcases = it->second.c_str();
}
}

View file

@ -141,7 +141,7 @@ TrackingSyncSource::InsertItemResult XMLRPCSyncSource::insertItem(const string &
return InsertItemResult((*it).first,
xmlrpc_c::value_string((*it).second),
false);
ITEM_OKAY);
}

View file

@ -65,46 +65,6 @@ public:
virtual void addTests() {
LocalTests::addTests();
#ifdef ENABLE_MAEMO
if (config.createSourceA &&
config.createSourceB &&
config.templateItem &&
strstr(config.templateItem, "BEGIN:VCARD") &&
config.uniqueProperties) {
ADD_TEST(EvolutionLocalTests, testOssoDelete);
}
#endif
}
private:
// insert am item,
// overwrite it with an additional X-OSSO-CONTACT-STATE:DELETED as Maemoe address book does,
// iterate again and check that our own code deleted the item
void testOssoDelete() {
// get into clean state with one template item added
deleteAll(createSourceA);
insert(createSourceA, config.templateItem, config.itemType);
// add X-OSSO-CONTACT-STATE:DELETED
string item = config.templateItem;
const char *comma = strchr(config.uniqueProperties, ':');
size_t offset = item.find(config.uniqueProperties, 0,
comma ? comma - config.uniqueProperties : strlen(config.uniqueProperties));
CPPUNIT_ASSERT(offset != item.npos);
item.insert(offset, "X-OSSO-CONTACT-STATE:DELETED\n");
update(createSourceA, item.c_str(), false);
// opening and preparing the source should delete the item
std::auto_ptr<TestingSyncSource> source;
SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceA()));
SOURCE_ASSERT_NO_FAILURE(source.get(), source->open());
SOURCE_ASSERT_NO_FAILURE(source.get(), source->beginSync("", "") );
CPPUNIT_ASSERT_EQUAL(0, countItemsOfType(source.get(), SyncSourceChanges::ANY));
CPPUNIT_ASSERT_EQUAL(0, countItemsOfType(source.get(), SyncSourceChanges::NEW));
CPPUNIT_ASSERT_EQUAL(0, countItemsOfType(source.get(), SyncSourceChanges::UPDATED));
CPPUNIT_ASSERT_EQUAL(1, countItemsOfType(source.get(), SyncSourceChanges::DELETED));
}
};
@ -233,9 +193,9 @@ public:
ClientTest::Config conf;
BOOST_FOREACH (string source, sources) {
getSourceConfig (source, conf);
if (conf.subConfigs) {
if (!conf.m_subConfigs.empty()) {
vector<string> subs;
boost::split (subs, conf.subConfigs, boost::is_any_of(","));
boost::split (subs, conf.m_subConfigs, boost::is_any_of(","));
BOOST_FOREACH (string sub, subs) {
pushLocalSource2Config(sub);
}
@ -264,17 +224,17 @@ public:
BOOST_FOREACH(const RegisterSyncSourceTest *test, m_configs) {
ClientTest::Config testconfig;
getSourceConfig(test, testconfig);
CPPUNIT_ASSERT(testconfig.type);
CPPUNIT_ASSERT(!testconfig.m_type.empty());
boost::shared_ptr<SyncSourceConfig> sc = config->getSyncSourceConfig(testconfig.sourceName);
boost::shared_ptr<SyncSourceConfig> sc = config->getSyncSourceConfig(testconfig.m_sourceName);
if (!sc || !sc->exists()) {
// no configuration yet
config->setSourceDefaults(testconfig.sourceName);
sc = config->getSyncSourceConfig(testconfig.sourceName);
config->setSourceDefaults(testconfig.m_sourceName);
sc = config->getSyncSourceConfig(testconfig.m_sourceName);
CPPUNIT_ASSERT(sc);
sc->setURI(testconfig.uri);
if(from && testconfig.sourceNameServerTemplate){
boost::shared_ptr<SyncSourceConfig> scServerTemplate = from->getSyncSourceConfig(testconfig.sourceNameServerTemplate);
sc->setURI(testconfig.m_uri);
if(from && !testconfig.m_sourceNameServerTemplate.empty()) {
boost::shared_ptr<SyncSourceConfig> scServerTemplate = from->getSyncSourceConfig(testconfig.m_sourceNameServerTemplate);
sc->setURI(scServerTemplate->getURI());
}
}
@ -284,7 +244,7 @@ public:
sc->setDatabaseID(database);
sc->setUser(m_evoUser);
sc->setPassword(m_evoPassword);
sc->setBackend(SourceType(testconfig.type).m_backend);
sc->setBackend(SourceType(testconfig.m_type).m_backend);
}
config->flush();
}
@ -330,11 +290,10 @@ public:
}
static void getSourceConfig(const RegisterSyncSourceTest *test, Config &config) {
memset(&config, 0, sizeof(config));
ClientTest::getTestData(test->m_testCaseName.c_str(), config);
config.createSourceA = createSource;
config.createSourceB = createSource;
config.sourceName = test->m_configName.c_str();
config.m_createSourceA = createSource;
config.m_createSourceB = createSource;
config.m_sourceName = test->m_configName.c_str();
test->updateConfig(config);
}
@ -539,7 +498,7 @@ private:
getSourceConfig(test, testConfig);
PersistentSyncSourceConfig sourceConfig(params.m_name, params.m_nodes);
sourceConfig.setSourceType(SourceType(testConfig.type));
sourceConfig.setSourceType(SourceType(testConfig.m_type));
// downcasting here: anyone who registers his sources for testing
// must ensure that they are indeed TestingSyncSource instances

View file

@ -1969,6 +1969,7 @@ sync_config_widget_init (SyncConfigWidget *self)
self->description_label = gtk_label_new ("");
gtk_misc_set_alignment (GTK_MISC (self->description_label), 0.0, 0.5);
gtk_widget_set_size_request (self->description_label, 700, -1);
gtk_label_set_line_wrap (GTK_LABEL (self->description_label), TRUE);
gtk_box_pack_start (GTK_BOX (tmp_box), self->description_label, FALSE, FALSE, 0);
tmp_box = gtk_hbox_new (FALSE, 0);

View file

@ -6519,13 +6519,16 @@ void AutoSyncManager::initConfig(const string &configName)
//enable http and bt?
bool http = false, bt = false;
bool any = false;
if(autoSync.empty() || boost::iequals(autoSync, "0")
|| boost::iequals(autoSync, "f")) {
http = false;
bt = false;
any = false;
} else if(boost::iequals(autoSync, "1") || boost::iequals(autoSync, "t")) {
http = true;
bt = true;
any = true;
} else {
vector<string> options;
boost::split(options, autoSync, boost::is_any_of(","));
@ -6561,7 +6564,7 @@ void AutoSyncManager::initConfig(const string &configName)
}
if((transport == AutoSyncTask::NEEDS_HTTP && http) ||
(transport == AutoSyncTask::NEEDS_BT && bt) ||
(transport == AutoSyncTask::NEEDS_OTHER)) {
(transport == AutoSyncTask::NEEDS_OTHER && any)) {
AutoSyncTask syncTask(configName, duration, transport, url);
PeerMap::iterator it = m_peerMap.find(interval);
if(it != m_peerMap.end()) {

View file

@ -424,8 +424,7 @@ void Cmdline::makeObsolete(boost::shared_ptr<SyncConfig> &from)
{
string oldname = from->getRootPath();
string newname, suffix;
int counter = 0;
while (true) {
for (int counter = 0; true; counter++) {
ostringstream newsuffix;
newsuffix << ".old";
if (counter) {
@ -433,6 +432,16 @@ void Cmdline::makeObsolete(boost::shared_ptr<SyncConfig> &from)
}
suffix = newsuffix.str();
newname = oldname + suffix;
if (from->hasPeerProperties()) {
boost::shared_ptr<SyncConfig> renamed(new SyncConfig(from->getPeerName() + suffix));
if (renamed->exists()) {
// don't pick a config name which has the same peer name
// as some other, existing config
continue;
}
}
// now renaming should succeed, but let's check anyway
if (!rename(oldname.c_str(),
newname.c_str())) {
break;
@ -442,7 +451,6 @@ void Cmdline::makeObsolete(boost::shared_ptr<SyncConfig> &from)
newname.c_str(),
strerror(errno)));
}
counter++;
}
string newConfigName;
@ -518,12 +526,28 @@ void Cmdline::finishCopy(const boost::shared_ptr<SyncConfig> &from,
// config to hide that old config from normal UI users. Must
// do this without going through SyncConfig, because that
// would bump the version.
FileConfigNode node(from->getRootPath(), "config.ini", false);
BoolConfigProperty ready("ConsumerReady", "", "0");
if (ready.getPropertyValue(node)) {
ready.setProperty(node, false);
// Also disable auto-syncing in the migrated config.
StringConfigProperty autosync("autoSync", "", "");
{
FileConfigNode node(from->getRootPath(), "config.ini", false);
if (ready.getPropertyValue(node)) {
ready.setProperty(node, false);
}
if (!autosync.getProperty(node).empty()) {
autosync.setProperty(node, "0");
}
node.flush();
}
// same for very old configs
{
FileConfigNode node(from->getRootPath() + "/spds/syncml", "config.txt", false);
if (!autosync.getProperty(node).empty()) {
autosync.setProperty(node, "0");
}
node.flush();
}
node.flush();
// Set ConsumerReady for migrated SyncEvolution < 1.2
// configs, because in older releases all existing
@ -1141,6 +1165,22 @@ bool Cmdline::run() {
sysync::TSyError err;
#define CHECK_ERROR(_op) if (err) { SE_THROW_EXCEPTION_STATUS(StatusException, string(source->getName()) + ": " + (_op), SyncMLStatus(err)); }
// acquire passwords before doing anything (interactive password
// access not supported for the command line)
{
ConfigPropertyRegistry& registry = SyncConfig::getRegistry();
BOOST_FOREACH(const ConfigProperty *prop, registry) {
prop->checkPassword(*context, m_server, *context->getProperties());
}
}
{
ConfigPropertyRegistry &registry = SyncSourceConfig::getRegistry();
BOOST_FOREACH(const ConfigProperty *prop, registry) {
prop->checkPassword(*context, m_server, *context->getProperties(),
source->getName(), sourceNodes.getProperties());
}
}
source->open();
const SyncSource::Operations &ops = source->getOperations();
if (m_printItems) {
@ -1150,11 +1190,6 @@ bool Cmdline::run() {
source->throwError("reading items not supported");
}
ConfigPropertyRegistry& registry = SyncConfig::getRegistry();
BOOST_FOREACH(const ConfigProperty *prop, registry) {
prop->checkPassword(*context, m_server, *context->getProperties());
}
err = ops.m_startDataRead("", "");
CHECK_ERROR("reading items");
list<string> luids;
@ -2242,6 +2277,7 @@ class CmdlineTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testListSources);
CPPUNIT_TEST(testMigrate);
CPPUNIT_TEST(testMigrateContext);
CPPUNIT_TEST(testMigrateAutoSync);
CPPUNIT_TEST_SUITE_END();
public:
@ -3897,8 +3933,9 @@ protected:
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(newRoot, "scheduleworld.old");
boost::replace_all(createdConfig, "/scheduleworld/", "/scheduleworld.old/");
string renamedConfig = scanFiles(newRoot, "scheduleworld.old.1");
boost::replace_first(createdConfig, "ConsumerReady = 1", "ConsumerReady = 0");
boost::replace_all(createdConfig, "/scheduleworld/", "/scheduleworld.old.1/");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
@ -3939,6 +3976,7 @@ protected:
"peers/scheduleworld/config.ini");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(oldRoot + ".old.1");
boost::replace_first(createdConfig, "ConsumerReady = 1", "ConsumerReady = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
@ -3996,8 +4034,8 @@ protected:
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
renamedConfig = scanFiles(otherRoot, "scheduleworld.old");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old/");
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.3");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.3/");
boost::replace_all(expected, "ConsumerReady = 1", "ConsumerReady = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
@ -4012,11 +4050,11 @@ protected:
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
migratedConfig = scanFiles(otherRoot, "scheduleworld");
boost::replace_all(expected, "/scheduleworld.old/", "/scheduleworld/");
boost::replace_all(expected, "/scheduleworld.old.3/", "/scheduleworld/");
boost::replace_all(expected, "ConsumerReady = 0", "ConsumerReady = 1");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.1");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.1/");
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.4");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.4/");
boost::replace_all(expected, "ConsumerReady = 1", "ConsumerReady = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
@ -4042,10 +4080,10 @@ protected:
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
migratedConfig = scanFiles(otherRoot, "scheduleworld");
boost::replace_all(expected, "/scheduleworld.old.1/", "/scheduleworld/");
boost::replace_all(expected, "/scheduleworld.old.4/", "/scheduleworld/");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.2");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.2/");
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.5");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.5/");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
}
}
@ -4126,6 +4164,82 @@ protected:
}
}
void testMigrateAutoSync() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "templates");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
string oldRoot = m_testDir + "/.sync4j/evolution/scheduleworld";
string newRoot = m_testDir + "/syncevolution/default";
string oldConfig = "spds/syncml/config.txt:autoSync = 1\n";
oldConfig += OldScheduleWorldConfig();
{
// migrate old config
createFiles(oldRoot, oldConfig);
string createdConfig = scanFiles(oldRoot);
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
string migratedConfig = scanFiles(newRoot);
string expected = ScheduleWorldConfig();
boost::replace_first(expected, "# autoSync = 0", "autoSync = 1");
sortConfig(expected);
// migrating SyncEvolution < 1.2 configs sets
// ConsumerReady, to keep config visible in the updated
// sync-ui
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
// migrating "type" sets forceSyncFormat (always)
// and databaseFormat (if format was part of type, as for addressbook)
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(oldRoot + ".old");
// autoSync must have been unset
boost::replace_first(createdConfig, ":autoSync = 1", ":autoSync = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
{
// rewrite existing config with autoSync set
string createdConfig = scanFiles(newRoot, "scheduleworld");
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
string migratedConfig = scanFiles(newRoot, "scheduleworld");
string expected = ScheduleWorldConfig();
boost::replace_first(expected, "# autoSync = 0", "autoSync = 1");
sortConfig(expected);
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(newRoot, "scheduleworld.old.1");
// autoSync must have been unset
boost::replace_first(createdConfig, ":autoSync = 1", ":autoSync = 0");
// the scheduleworld config was consumer ready, the migrated one isn't
boost::replace_all(createdConfig, "ConsumerReady = 1", "ConsumerReady = 0");
boost::replace_all(createdConfig, "/scheduleworld/", "/scheduleworld.old.1/");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
}
const string m_testDir;
private:
@ -4518,7 +4632,7 @@ private:
size_t fileoff = fullpath.rfind('/');
mkdir_p(fullpath.substr(0, fileoff));
out.open(fullpath.c_str(),
append ? ios_base::out : (ios_base::out|ios_base::trunc));
append ? (ios_base::out|ios_base::ate|ios_base::app) : (ios_base::out|ios_base::trunc));
outname = newname;
}
out << line << endl;

View file

@ -107,21 +107,6 @@ public:
/** the run() call modified configurations (added, updated, removed) */
bool configWasModified() const { return m_configModified; }
/**
* Acts like a boolean, but in addition, can also tell whether the
* value was explicitly set.
*/
class Bool {
public:
Bool(bool val = false) : m_value(val), m_wasSet(false) {}
operator bool () const { return m_value; }
Bool & operator = (bool val) { m_value = val; m_wasSet = true; return *this; }
bool wasSet() const { return m_wasSet; }
private:
bool m_value;
bool m_wasSet;
};
Bool useDaemon() { return m_useDaemon; }
/** whether '--monitor' is set */

View file

@ -288,12 +288,15 @@ SyncSourceRaw::InsertItemResult MapSyncSource::insertItem(const std::string &lui
{
StringPair ids = splitLUID(luid);
SubSyncSource::SubItemResult res = m_sub->insertSubItem(ids.first, ids.second, item);
SubRevisionEntry &entry = m_revisions[res.m_mainid];
entry.m_uid = res.m_uid;
entry.m_revision = res.m_revision;
entry.m_subids.insert(res.m_subid);
// anything changed?
if (res.m_state != ITEM_NEEDS_MERGE) {
SubRevisionEntry &entry = m_revisions[res.m_mainid];
entry.m_uid = res.m_uid;
entry.m_revision = res.m_revision;
entry.m_subids.insert(res.m_subid);
}
return SyncSourceRaw::InsertItemResult(createLUID(res.m_mainid, res.m_subid),
res.m_revision, res.m_merged);
res.m_revision, res.m_state);
}
void MapSyncSource::readItem(const std::string &luid, std::string &item)

View file

@ -67,7 +67,7 @@ class SubSyncSource : virtual public SyncSourceBase
class SubItemResult {
public:
SubItemResult() :
m_merged(false)
m_state(ITEM_OKAY)
{}
/**
@ -79,25 +79,25 @@ class SubSyncSource : virtual public SyncSourceBase
* @param uid an arbitrary string, stored, but not used by MapSyncSource;
* used in the CalDAV backend to associate mainid (= resource path)
* with UID (= part of the item content, but with special semantic)
* @param merged set this to true if an existing sub item was updated instead of adding it
* @param state report about what was done with the data
*/
SubItemResult(const string &mainid,
const string &subid,
const string &revision,
const string &uid,
bool merged) :
InsertItemResultState state) :
m_mainid(mainid),
m_subid(subid),
m_revision(revision),
m_uid(uid),
m_merged(merged)
m_state(state)
{}
string m_mainid;
string m_subid;
string m_revision;
string m_uid;
bool m_merged;
InsertItemResultState m_state;
};
SubSyncSource() : m_parent(NULL) {}
@ -180,6 +180,12 @@ class SubSyncSource : virtual public SyncSourceBase
*/
virtual std::string getSubDescription(const string &mainid, const string &subid) = 0;
/**
* Called after MapSyncSource already populated the info structure.
*/
virtual void updateSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments) {}
private:
MapSyncSource *m_parent;
};
@ -266,6 +272,13 @@ class MapSyncSource :
virtual std::string getDescription(sysync::KeyH aItemKey) { return dynamic_cast<SyncSourceLogging &>(*m_sub).getDescription(aItemKey); }
virtual std::string getDescription(const string &luid);
protected:
virtual void getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments) {
TestingSyncSource::getSynthesisInfo(info, fragments);
m_sub->updateSynthesisInfo(info, fragments);
}
private:
boost::shared_ptr<SubSyncSource> m_sub;
/** escape / in uid with %2F, so that splitMainIDValue() and splitLUID() can use / as separator */

View file

@ -74,6 +74,8 @@ class Unref {
#endif // HAVE_GLIB
#ifdef ENABLE_ICAL
static void unref(icalcomponent *pointer) { icalcomponent_free(pointer); }
static void unref(icalproperty *pointer) { icalproperty_free(pointer); }
static void unref(icalparameter *pointer) { icalparameter_free(pointer); }
static void unref(icaltimezone *pointer) { icaltimezone_free(pointer, 1); }
#endif // ENABLE_ICAL
};

View file

@ -2558,7 +2558,11 @@ ConfigPasswordKey DatabasePasswordConfigProperty::getPasswordKey(const string &d
{
ConfigPasswordKey key;
key.user = sourcePropUser.getProperty(*sourceConfigNode);
key.object = serverName;
std::string configName = SyncConfig::normalizeConfigString(serverName, SyncConfig::NORMALIZE_LONG_FORMAT);
std::string peer, context;
SyncConfig::splitConfigString(configName, peer, context);
key.object = "@";
key.object += context;
key.object += " ";
key.object += sourceName;
key.object += " backend";

View file

@ -1915,16 +1915,16 @@ void SyncContext::startLoopThread()
#endif
}
SyncSource *SyncContext::findSource(const char *name)
SyncSource *SyncContext::findSource(const std::string &name)
{
if (!m_activeContext || !m_activeContext->m_sourceListPtr) {
return NULL;
}
const char *realname = strrchr(name, m_findSourceSeparator);
const char *realname = strrchr(name.c_str(), m_findSourceSeparator);
if (realname) {
realname++;
} else {
realname = name;
realname = name.c_str();
}
return (*m_activeContext->m_sourceListPtr)[realname];
}
@ -1950,11 +1950,11 @@ void SyncContext::initSources(SourceList &sourceList)
BOOST_FOREACH(const string &name, configuredSources) {
boost::shared_ptr<PersistentSyncSourceConfig> sc(getSyncSourceConfig(name));
SyncSourceNodes source = getSyncSourceNodes (name);
SourceType sourceType = SyncSource::getSourceType(source);
// is the source enabled?
string sync = sc->getSync();
bool enabled = sync != "disabled";
if (enabled) {
SourceType sourceType = SyncSource::getSourceType(source);
if (sourceType.m_backend == "virtual") {
//This is a virtual sync source, check and enable the referenced
//sub syncsources here
@ -1995,12 +1995,12 @@ void SyncContext::initSources(SourceList &sourceList)
boost::shared_ptr<PersistentSyncSourceConfig> sc(getSyncSourceConfig(name));
SyncSourceNodes source = getSyncSourceNodes (name);
SourceType sourceType = SyncSource::getSourceType(source);
// is the source enabled?
string sync = sc->getSync();
bool enabled = sync != "disabled";
if (enabled) {
SourceType sourceType = SyncSource::getSourceType(source);
if (sourceType.m_backend != "virtual") {
SyncSourceParams params(name,
source,
@ -3269,7 +3269,7 @@ SyncMLStatus SyncContext::doSync()
target;
target = m_engine.OpenSubkey(targets, sysync::KEYVAL_ID_NEXT, true)) {
s = m_engine.GetStrValue(target, "dbname");
SyncSource *source = findSource(s.c_str());
SyncSource *source = findSource(s);
if (source) {
m_engine.SetInt32Value(target, "enabled", 1);
int slow = 0;

View file

@ -452,7 +452,7 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
* @TODO: roll SourceList into SyncContext and
* make this non-static
*/
static SyncSource *findSource(const char *name);
static SyncSource *findSource(const std::string &name);
static const char m_findSourceSeparator = '@';
/**

View file

@ -541,6 +541,9 @@ void SyncSourceSerialize::getSynthesisInfo(SynthesisInfo &info,
{
string type = getMimeType();
// default remote rule (local-storage.xml): suppresses empty properties
info.m_backendRule = "LOCALSTORAGE";
if (type == "text/x-vcard") {
info.m_native = "vCard21";
info.m_fieldlist = "contacts";
@ -555,6 +558,14 @@ void SyncSourceSerialize::getSynthesisInfo(SynthesisInfo &info,
info.m_datatypes =
" <use datatype='vCard21' mode='rw'/>\n"
" <use datatype='vCard30' mode='rw' preferred='yes'/>\n";
// If a backend overwrites the m_beforeWriteScript, then it must
// include $VCARD_OUTGOING_PHOTO_VALUE_SCRIPT in its own script,
// otherwise it will be sent invalid, empty PHOTO;TYPE=unknown;VALUE=binary:
// properties.
info.m_beforeWriteScript = "$VCARD_OUTGOING_PHOTO_VALUE_SCRIPT;\n";
// Likewise for reading. This is needed to ensure proper merging
// of contact data.
info.m_afterReadScript = "$VCARD_INCOMING_PHOTO_VALUE_SCRIPT;\n";
} else if (type == "text/x-calendar" || type == "text/x-vcalendar") {
info.m_native = "vCalendar10";
info.m_fieldlist = "calendar";
@ -657,6 +668,19 @@ sysync::TSyError SyncSourceSerialize::insertItemAsKey(sysync::KeyH aItemKey, sys
InsertItemResult inserted =
insertItem(!aID ? "" : aID->item, data.get());
newID->item = StrAlloc(inserted.m_luid.c_str());
switch (inserted.m_state) {
case ITEM_OKAY:
break;
case ITEM_REPLACED:
res = sysync::DB_DataReplaced;
break;
case ITEM_MERGED:
res = sysync::DB_DataMerged;
break;
case ITEM_NEEDS_MERGE:
res = sysync::DB_Conflict;
break;
}
}
return res;

View file

@ -162,23 +162,23 @@ class TestingSyncSource;
* is okay, but it will disable all tests that need the
* information.
*/
struct ClientTestConfig{
struct ClientTestConfig {
/**
* The name is used in test names and has to be set.
*/
const char *sourceName;
std::string m_sourceName;
/**
* A default URI to be used when creating a client config.
*/
const char *uri;
std::string m_uri;
/**
* A corresponding source name in the default server template,
* this is used to copy corresponding uri set in the server template
* instead of the uri field above (which is the same for all servers).
*/
const char *sourceNameServerTemplate;
std::string m_sourceNameServerTemplate;
/**
* A member function of a subclass which is called to create a
@ -210,7 +210,7 @@ struct ClientTestConfig{
* it may report the same changes as the sync source used during
* sync tests.
*/
createsource_t createSourceA;
createsource_t m_createSourceA;
/**
* A second sync source also referencing the primary data
@ -228,7 +228,7 @@ struct ClientTestConfig{
* - check that the total number and number of
* added/updated/deleted items is as expected
*/
createsource_t createSourceB;
createsource_t m_createSourceB;
/**
* The framework can generate vCard and vCalendar/iCalendar items
@ -239,24 +239,19 @@ struct ClientTestConfig{
* It must contain the string <<REVISION>> which will be replaced
* with the revision parameter of the createItem() method.
*/
const char *templateItem;
std::string m_templateItem;
/**
* This is a colon (:) separated list of properties which need
* to be modified in templateItem.
*/
const char *uniqueProperties;
/**
* the number of items to create during stress tests
*/
int numItems;
std::string m_uniqueProperties;
/**
* This is a single property in templateItem which can be extended
* to increase the size of generated items.
*/
const char *sizeProperty;
std::string m_sizeProperty;
/**
* Type to be set when importing any of the items into the
@ -266,7 +261,7 @@ struct ClientTestConfig{
* Not currently used! All items are assumed to be in the raw,
* internal format (see SyncSourceRaw and SyncSourceSerialize).
*/
const char *itemType;
std::string m_itemType;
/**
* callback which is invoked with a specific item as paramter
@ -276,33 +271,33 @@ struct ClientTestConfig{
* @param update modify item content so that it can be
* used as an update of the old data
*/
string (*mangleItem)(const char *data, bool update);
boost::function<std::string (const std::string &, bool)> m_mangleItem;
/**
* A very simple item that is inserted during basic tests. Ideally
* it only contains properties supported by all servers.
*/
const char *insertItem;
std::string m_insertItem;
/**
* A slightly modified version of insertItem. If the source has UIDs
* embedded into the item data, then both must have the same UID.
* Again all servers should better support these modified properties.
*/
const char *updateItem;
std::string m_updateItem;
/**
* A more heavily modified version of insertItem. Same UID if necessary,
* but can test changes to items only supported by more advanced
* servers.
*/
const char *complexUpdateItem;
std::string m_complexUpdateItem;
/**
* To test merge conflicts two different updates of insertItem are
* needed. This is the first such update.
*/
const char *mergeItem1;
std::string m_mergeItem1;
/**
* The second merge update item. To avoid true conflicts it should
@ -310,13 +305,14 @@ struct ClientTestConfig{
* usually have problems perfectly merging items. Therefore the
* test is run without expecting a certain merge result.
*/
const char *mergeItem2;
std::string m_mergeItem2;
/**
* These two items are related: one is main one, the other is
* a subordinate one. The semantic is that the main item is
* complete on it its own, while the other normally should only
* be used in combination with the main one.
* The items in the inner vector are related: the first one the is
* main one, the other(s) is/are a subordinate ones. The semantic
* is that the main item is complete on it its own, while the
* other normally should only be used in combination with the main
* one.
*
* Because SyncML cannot express such dependencies between items,
* a SyncSource has to be able to insert, updated and remove
@ -328,26 +324,49 @@ struct ClientTestConfig{
* One example for main and subordinate items are a recurring
* iCalendar 2.0 event and a detached recurrence.
*/
const char *parentItem, *childItem;
typedef std::vector<std::string> LinkedItems_t;
/**
* The linked items may exist in different variations (outer vector).
*/
typedef std::vector<LinkedItems_t> MultipleLinkedItems_t;
MultipleLinkedItems_t m_linkedItems;
/**
* Backends atomic modification tests
*/
bool atomicModification;
Bool m_atomicModification;
/**
* set to false to disable tests which slightly violate the
* semantic of linked items by inserting children
* before/without their parent
*/
bool linkedItemsRelaxedSemantic;
Bool m_linkedItemsRelaxedSemantic;
/**
* setting this to false disables tests which depend
* on the source's support for linked item semantic
* (testLinkedItemsInsertParentTwice, testLinkedItemsInsertChildTwice)
*/
bool sourceKnowsItemSemantic;
Bool m_sourceKnowsItemSemantic;
/**
* Set this to true if the backend does not have IDs which are the
* same for all clients and across slow syncs. For example, when
* testing the ActiveSync backend this field needs to be true,
* because items are renumbered as 1:x with x = 1, 2, ... for each
* clients when a sync anchor is assigned to it.
*/
Bool m_sourceLUIDsAreVolatile;
/**
* Set this to true if the backend supports
* X-SYNCEVOLUTION-EXDATE-DETACHED, see CalDAVSource.cpp
* CalDAVSource::readSubItem().
*/
Bool m_supportsReccurenceEXDates;
/**
* called to dump all items into a file, required by tests which need
@ -360,7 +379,7 @@ struct ClientTestConfig{
* @param file a file name
* @return error code, 0 for success
*/
int (*dump)(ClientTest &client, TestingSyncSource &source, const char *file);
boost::function<int (ClientTest &, TestingSyncSource &, const std::string &)> m_dump;
/**
* import test items: which these are is determined entirely by
@ -376,8 +395,8 @@ struct ClientTestConfig{
* this may depend on the current server that is being tested
* @return error string, empty for success
*/
std::string (*import)(ClientTest &client, TestingSyncSource &source, const ClientTestConfig &config,
const char *file, std::string &realfile);
boost::function<std::string (ClientTest &, TestingSyncSource &, const ClientTestConfig &,
const std::string &, std::string &)> m_import;
/**
* a function which compares two files with items in the format used by "dump"
@ -386,7 +405,7 @@ struct ClientTestConfig{
* @param fileB second file name
* @return true if the content of the files is considered equal
*/
bool (*compare)(ClientTest &client, const char *fileA, const char *fileB);
boost::function<bool (ClientTest &, const std::string &, const std::string &)> m_compare;
/**
* A file with test cases in the format expected by import and compare.
@ -405,27 +424,27 @@ struct ClientTestConfig{
* That file then will be used in testItems instead of the base
* version. See the src/Makefile.am for rules that maintain such files.
*/
const char *testcases;
std::string m_testcases;
/**
* the item type normally used by the source (not used by the tests
* themselves; client-test.cpp uses it to initialize source configs)
*/
const char *type;
std::string m_type;
/**
* a list of sub configs separated via , if this is a super datastore
*/
const char *subConfigs;
std::string m_subConfigs;
/**
* TRUE if the source supports recovery from an interrupted
* synchronization. Enables the Client::Sync::*::Retry group
* of tests.
*/
bool retrySync;
bool suspendSync;
bool resendSync;
Bool m_retrySync;
Bool m_suspendSync;
Bool m_resendSync;
/**
* Set this to test if the source supports preserving local data extensions.
@ -438,8 +457,8 @@ struct ClientTestConfig{
* genericUpdate works for vCard and iCalendar by updating FN, N, resp. SUMMARY
* and can be used as implementation of update.
*/
void (*update)(std::string &item);
void (*genericUpdate)(std::string &item);
boost::function<void (std::string &)> m_update;
boost::function<void (std::string &)> m_genericUpdate;
};
/**
@ -1408,6 +1427,53 @@ class SyncSourceDelete : virtual public SyncSourceBase {
sysync::TSyError deleteItemSynthesis(sysync::cItemID aID);
};
enum InsertItemResultState {
/**
* item added or updated as requested
*/
ITEM_OKAY,
/**
* When a backend is asked to add an item and recognizes
* that the item matches an already existing item, it may
* replace that item instead of creating a duplicate. In this
* case it must return ITEM_REPLACED and set the luid/revision
* of that updated item.
*
* This can happen when such an item was added concurrently to
* the running sync or, more likely, was reported as new by
* the backend and the engine failed to find the match because
* it doesn't know about some special semantic, like iCalendar
* 2.0 UID).
*
* Note that depending on the age of the items, the older data
* will replace the more recent one when always using item
* replacement.
*/
ITEM_REPLACED,
/**
* Same as ITEM_REPLACED, except that the backend did some
* modifications to the data that was sent to it before
* storing it, like merging it with the existing item. The
* engine will treat the updated item as modified and send
* back the update to the peer as soon as possible. In server
* mode that will be in the same sync session, in a client in
* the next session (client cannot send changes after having
* received data from the server).
*/
ITEM_MERGED,
/**
* As before, a match against an existing item was detected.
* By returning this state and the luid of the matched item
* (revision not needed) the engine is instructed to do the
* necessary data comparison and merging itself. Useful when a
* backend can't do the necessary merging itself.
*/
ITEM_NEEDS_MERGE
};
/**
* an interface for reading and writing items in the internal
* format; see SyncSourceSerialize for an explanation
@ -1417,26 +1483,26 @@ class SyncSourceRaw : virtual public SyncSourceBase {
class InsertItemResult {
public:
InsertItemResult() :
m_merged(false)
m_state(ITEM_OKAY)
{}
/**
* @param luid the LUID after the operation; during an update the LUID must
* not be changed, so return the original one here
* @param revision the revision string after the operation; leave empty if not used
* @param merged set this to true if an existing item was updated instead of adding it
* @param state report about what was done with the data
*/
InsertItemResult(const string &luid,
const string &revision,
bool merged) :
InsertItemResultState state) :
m_luid(luid),
m_revision(revision),
m_merged(merged)
m_state(state)
{}
string m_luid;
string m_revision;
bool m_merged;
InsertItemResultState m_state;
};
/** same as SyncSourceSerialize::insertItem(), but with internal format */

View file

@ -140,14 +140,18 @@ std::string TrackingSyncSource::endSync(bool success)
TrackingSyncSource::InsertItemResult TrackingSyncSource::insertItem(const std::string &luid, const std::string &item)
{
InsertItemResult res = insertItem(luid, item, false);
updateRevision(*m_trackingNode, luid, res.m_luid, res.m_revision);
if (res.m_state != ITEM_NEEDS_MERGE) {
updateRevision(*m_trackingNode, luid, res.m_luid, res.m_revision);
}
return res;
}
TrackingSyncSource::InsertItemResult TrackingSyncSource::insertItemRaw(const std::string &luid, const std::string &item)
{
InsertItemResult res = insertItem(luid, item, true);
updateRevision(*m_trackingNode, luid, res.m_luid, res.m_revision);
if (res.m_state != ITEM_NEEDS_MERGE) {
updateRevision(*m_trackingNode, luid, res.m_luid, res.m_revision);
}
return res;
}

View file

@ -56,6 +56,20 @@
<!-- for events -->
<field name="EXDATES" array="yes" type="timestamp" compare="never"/>
<!-- EXDATEs for detached recurrences: meant to be used for the
RECURRENCE-IDs of all detached recurrences.
Can be ignored when dealing with only iCalendar 2.0 aware
peers, because these EXDATEs are implied for detached
recurrences and don't have to be specified explicitly. Can
be used to create additional EXDATEs for non-iCalendar 2.0
peers. For that, EXDATES_DETACHED must be populated by the
backend creating the parent event, because the engine
itself doesn't have the necessary
information. X-SYNCEVOLUTION-EXDATE-DETACHED can be used
for that in serialized calendar events. -->
<field name="EXDATES_DETACHED" array="yes" type="timestamp" compare="never"/>
<field name="ORIGSTART" array="no" type="timestamp" compare="never"/>
<field name="SEQNO" array="no" type="integer" compare="never"/>

View file

@ -378,12 +378,21 @@
with the EXDATE:value1,value2 format (correct in iCalendar 2.0):
as a workaround, accept all valid formats plus ; but
generate separate properties with one value each. -->
<property name="EXDATE" values="expandedlist" suppressempty="yes" onlyformode="standard" delayedparsing="1" valueseparator="," altvalueseparator=";">
<!-- The simplified version of EXDATE is needed by the Maemo Calendar backend
because the calendar storage doesn't parse EXDATE;TZID=...: -->
<property name="EXDATE" values="expandedlist" suppressempty="yes" onlyformode="standard" delayedparsing="1" valueseparator="," altvalueseparator=";" rule="SIMPLE-EXDATE">
<value field="EXDATES"/>
<position field="EXDATES" repeat="array" increment="1" minshow="0"/>
</property>
<property name="EXDATE" values="expandedlist" suppressempty="yes" onlyformode="standard" delayedparsing="1" valueseparator="," altvalueseparator=";" rule="other">
<value field="EXDATES"/>
<position field="EXDATES" repeat="array" increment="1" minshow="0"/>
<parameter name="TZID" default="no" show="yes">
<value field="EXDATES" conversion="TZID"/>
</parameter>
<parameter name="VALUE" default="no" show="yes">
<value field="EXDATES" conversion="VALUETYPE"/>
</parameter>
</property>
<property name="EXDATE" values="list" suppressempty="yes" onlyformode="old" delayedparsing="1" valueseparator=";" altvalueseparator=",">
@ -391,6 +400,28 @@
<position field="EXDATES" repeat="array" increment="1" minshow="0"/>
</property>
<!-- parse X-SYNCEVOLUTION-EXDATE-DETACHED, but never encode it like this except internally -->
<property name="X-SYNCEVOLUTION-EXDATE-DETACHED" delayedparsing="1" mandatory="no"
show="no" rule="HAVE-SYNCEVOLUTION-EXDATE-DETACHED">
<value field="EXDATES_DETACHED"/>
<parameter name="TZID" default="no" show="yes">
<value field="EXDATES_DETACHED" conversion="TZID"/>
</parameter>
<position field="EXDATES_DETACHED" repeat="array" increment="1" minshow="0"/>
</property>
<!-- encode as normal EXDATE when backend asks for it -->
<property name="EXDATE" show="no" rule="HAVE-EXDATE-DETACHED" mandatory="no">
<value field="EXDATES_DETACHED"/>
<parameter name="TZID" default="no" show="yes">
<value field="EXDATES_DETACHED" conversion="TZID"/>
</parameter>
<position field="EXDATES_DETACHED" repeat="array" increment="1" minshow="0"/>
</property>
<!-- encode as EXDATE without TZID when backend asks for it -->
<property name="EXDATE" show="no" rule="HAVE-EXDATE-DETACHED-NO-TZID" mandatory="no">
<value field="EXDATES_DETACHED"/>
<position field="EXDATES_DETACHED" repeat="array" increment="1" minshow="0"/>
</property>
<property name="DTEND" suppressempty="yes" delayedparsing="1">
<value field="DTEND" conversion="autoenddate"/>

View file

@ -0,0 +1,2 @@
<subrule name="HAVE-EXDATE-DETACHED"/>
<subrule name="HAVE-EXDATE-DETACHED-NO-TZID"/>

View file

@ -0,0 +1 @@
<subrule name="HAVE-SYNCEVOLUTION-EXDATE-DETACHED"/>

View file

@ -0,0 +1 @@
<subrule name="SIMPLE-EXDATE"></subrule>

View file

@ -2,6 +2,8 @@
<manufacturer>Patrick Ohly</manufacturer>
<model>SyncEvolution</model>
<include rule="HAVE-SYNCEVOLUTION-EXDATE-DETACHED"/>
<include rule="HAVE-EVOLUTION-UI-SLOT"/>
<!-- Merging between SyncEvolution instances is expected to work
well, so allow the engine to update items on both

View file

@ -0,0 +1,5 @@
<remoterule name="MAEMO-CALENDAR">
<deviceid>none - this rule is activated via its name in MAKE/PARSETEXTWITHPROFILE() macro calls</deviceid>
<include rule="HAVE-EXDATE-DETACHED-NO-TZID"/>
<include rule="SIMPLE-EXDATE"/>
</remoterule>

View file

@ -0,0 +1,5 @@
<remoterule name="LOCALSTORAGE">
<deviceid>none - this rule is activated by default via its name in MAKE/PARSETEXTWITHPROFILE() macro calls</deviceid>
<!-- storing empty properties only wastes space and causes overhead, suppress them -->
<noemptyproperties>yes</noemptyproperties>
</remoterule>

View file

@ -188,6 +188,26 @@
}
]]></macro>
<macro name="FIX_EXDATE_SCRIPT"><![CDATA[
// Add time zone information to EXDATEs: necessary for
// the Maemo calendar storages because it uses EXDATE
// without TZID.
if (!ISFLOATING(DTSTART)) {
STRING tz;
tz = TIMEZONE(DTSTART);
if (tz != "UTC") {
INTEGER i;
i = 0;
while (i<SIZE(EXDATES)) {
if (ISFLOATING(EXDATES[i])) {
SETTIMEZONE(EXDATES[i], tz);
}
i=i+1;
}
}
}
]]></macro>
<!-- Uses the UID/RECURRENCE-ID fields as the only criteria for
comparing calendar data if the VCALENDAR_COMPARE_UID session
variable is true, else does a normal comparison of the

View file

@ -231,8 +231,10 @@ extern "C" void EDSAbiWrapperInit()
# endif // ENABLE_EBOOK
# ifdef ENABLE_ECAL
static const int libecalMinVersion = 3,
libecalMaxVersion = 8;
ecalhandle =
findSymbols("libecal-1.2.so", 3, 8,
findSymbols("libecal-1.2.so", libecalMinVersion, libecalMaxVersion,
FIND_SYMBOLS_NEED_ALL|FIND_SYMBOLS_LENIENT_MAX_VERSION, NULL,
&EDSAbiWrapperSingleton.e_cal_add_timezone, "e_cal_add_timezone",
&EDSAbiWrapperSingleton.e_cal_component_get_icalcomponent, "e_cal_component_get_icalcomponent",
@ -282,6 +284,7 @@ extern "C" void EDSAbiWrapperInit()
&EDSAbiWrapperSingleton.icalparameter_get_tzid, "icalparameter_get_tzid",
&EDSAbiWrapperSingleton.icalparameter_set_tzid, "icalparameter_set_tzid",
&EDSAbiWrapperSingleton.icalparameter_new_from_value_string, "icalparameter_new_from_value_string",
&EDSAbiWrapperSingleton.icalparameter_new_clone, "icalparameter_new_clone",
&EDSAbiWrapperSingleton.icalproperty_new_clone, "icalproperty_new_clone",
&EDSAbiWrapperSingleton.icalproperty_free, "icalproperty_free",
&EDSAbiWrapperSingleton.icalproperty_get_description, "icalproperty_get_description",
@ -299,12 +302,17 @@ extern "C" void EDSAbiWrapperInit()
&EDSAbiWrapperSingleton.icalproperty_new_summary, "icalproperty_new_summary",
&EDSAbiWrapperSingleton.icalproperty_new_uid, "icalproperty_new_uid",
&EDSAbiWrapperSingleton.icalproperty_new_sequence, "icalproperty_new_sequence",
&EDSAbiWrapperSingleton.icalproperty_new_recurrenceid, "icalproperty_new_recurrenceid",
&EDSAbiWrapperSingleton.icalproperty_set_value_from_string, "icalproperty_set_value_from_string",
&EDSAbiWrapperSingleton.icalproperty_set_dtstamp, "icalproperty_set_dtstamp",
&EDSAbiWrapperSingleton.icalproperty_set_lastmodified, "icalproperty_set_lastmodified",
&EDSAbiWrapperSingleton.icalproperty_set_sequence, "icalproperty_set_sequence",
&EDSAbiWrapperSingleton.icalproperty_set_uid, "icalproperty_set_uid",
&EDSAbiWrapperSingleton.icalproperty_remove_parameter_by_kind, "icalproperty_remove_parameter_by_kind",
&EDSAbiWrapperSingleton.icalproperty_add_parameter, "icalproperty_add_parameter",
&EDSAbiWrapperSingleton.icalproperty_get_value_as_string, "icalproperty_get_value_as_string",
&EDSAbiWrapperSingleton.icalproperty_get_x_name, "icalproperty_get_x_name",
&EDSAbiWrapperSingleton.icalproperty_new_from_string, "icalproperty_new_from_string",
&EDSAbiWrapperSingleton.icaltime_is_null_time, "icaltime_is_null_time",
&EDSAbiWrapperSingleton.icaltime_is_utc, "icaltime_is_utc",
&EDSAbiWrapperSingleton.icaltime_as_ical_string, "icaltime_as_ical_string",
@ -325,10 +333,11 @@ extern "C" void EDSAbiWrapperInit()
(void *)0);
EDSAbiHaveEcal = EDSAbiWrapperSingleton.e_cal_new != 0;
ecalhandle =
findSymbols("libecal-1.2.so", 3, 7,
findSymbols("libecal-1.2.so", libecalMinVersion, libecalMaxVersion,
FIND_SYMBOLS_LENIENT_MAX_VERSION, NULL,
&EDSAbiWrapperSingleton.icalcomponent_as_ical_string_r, "icalcomponent_as_ical_string_r",
&EDSAbiWrapperSingleton.icaltime_as_ical_string_r, "icaltime_as_ical_string_r",
&EDSAbiWrapperSingleton.icalproperty_get_value_as_string_r, "icalproperty_get_value_as_string_r",
(void *)0);
# endif // ENABLE_ECAL

View file

@ -180,6 +180,7 @@ struct EDSAbiWrapper {
const char* (*icalparameter_get_tzid) (const icalparameter* value);
void (*icalparameter_set_tzid) (icalparameter* value, const char* v);
icalparameter *(*icalparameter_new_from_value_string)(icalparameter_kind kind, const char *value);
icalparameter *(*icalparameter_new_clone)(icalparameter *param);
icalproperty *(*icalproperty_new_clone)(icalproperty *prop);
void (*icalproperty_free)(icalproperty *prop);
const char* (*icalproperty_get_description) (const icalproperty* prop);
@ -197,6 +198,7 @@ struct EDSAbiWrapper {
icalproperty* (*icalproperty_new_summary) (const char* v);
icalproperty* (*icalproperty_new_sequence) (int v);
icalproperty* (*icalproperty_new_uid) (const char* v);
icalproperty* (*icalproperty_new_recurrenceid) (icaltimetype v);
void (*icalproperty_set_value_from_string) (icalproperty* prop,const char* value, const char* kind);
void (*icalproperty_set_dtstamp) (icalproperty* prop, struct icaltimetype v);
void (*icalproperty_set_lastmodified) (icalproperty* prop, struct icaltimetype v);
@ -204,6 +206,11 @@ struct EDSAbiWrapper {
void (*icalproperty_set_uid) (icalproperty* prop, const char *v);
void (*icalproperty_remove_parameter_by_kind)(icalproperty* prop,
icalparameter_kind kind);
void (*icalproperty_add_parameter)(icalproperty* prop,icalparameter* parameter);
const char* (*icalproperty_get_value_as_string)(const icalproperty* prop);
const char* (*icalproperty_get_x_name)(icalproperty* prop);
icalproperty* (*icalproperty_new_from_string)(const char* str);
int (*icaltime_is_null_time)(const struct icaltimetype t);
int (*icaltime_is_utc)(const struct icaltimetype t);
const char* (*icaltime_as_ical_string) (const struct icaltimetype tt);
@ -226,6 +233,7 @@ struct EDSAbiWrapper {
// optional variants which allocate the returned string for us
const char* (*icaltime_as_ical_string_r) (const struct icaltimetype tt);
char* (*icalcomponent_as_ical_string_r) (icalcomponent* component);
char* (*icalproperty_get_value_as_string_r) (const icalproperty* prop);
# endif /* ENABLE_ICAL */
# ifdef ENABLE_BLUETOOTH
@ -347,6 +355,7 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
# define icalparameter_get_tzid EDSAbiWrapperSingleton.icalparameter_get_tzid
# define icalparameter_set_tzid EDSAbiWrapperSingleton.icalparameter_set_tzid
# define icalparameter_new_from_value_string EDSAbiWrapperSingleton.icalparameter_new_from_value_string
# define icalparameter_new_clone EDSAbiWrapperSingleton.icalparameter_new_clone
# define icalproperty_new_clone EDSAbiWrapperSingleton.icalproperty_new_clone
# define icalproperty_free EDSAbiWrapperSingleton.icalproperty_free
# define icalproperty_get_description EDSAbiWrapperSingleton.icalproperty_get_description
@ -364,12 +373,17 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
# define icalproperty_new_summary EDSAbiWrapperSingleton.icalproperty_new_summary
# define icalproperty_new_uid EDSAbiWrapperSingleton.icalproperty_new_uid
# define icalproperty_new_sequence EDSAbiWrapperSingleton.icalproperty_new_sequence
# define icalproperty_new_recurrenceid EDSAbiWrapperSingleton.icalproperty_new_recurrenceid
# define icalproperty_set_value_from_string EDSAbiWrapperSingleton.icalproperty_set_value_from_string
# define icalproperty_set_dtstamp EDSAbiWrapperSingleton.icalproperty_set_dtstamp
# define icalproperty_set_lastmodified EDSAbiWrapperSingleton.icalproperty_set_lastmodified
# define icalproperty_set_sequence EDSAbiWrapperSingleton.icalproperty_set_sequence
# define icalproperty_set_uid EDSAbiWrapperSingleton.icalproperty_set_uid
# define icalproperty_remove_parameter_by_kind EDSAbiWrapperSingleton.icalproperty_remove_parameter_by_kind
# define icalproperty_add_parameter EDSAbiWrapperSingleton.icalproperty_add_parameter
# define icalproperty_get_value_as_string (EDSAbiWrapperSingleton.icalproperty_get_value_as_string_r ? EDSAbiWrapperSingleton.icalproperty_get_value_as_string_r : (char *(*)(const icalproperty*))EDSAbiWrapperSingleton.icalproperty_get_value_as_string)
# define icalproperty_get_x_name EDSAbiWrapperSingleton.icalproperty_get_x_name
# define icalproperty_new_from_string EDSAbiWrapperSingleton.icalproperty_new_from_string
# define icaltime_is_null_time EDSAbiWrapperSingleton.icaltime_is_null_time
# define icaltime_is_utc EDSAbiWrapperSingleton.icaltime_is_utc
# define icaltime_as_ical_string (EDSAbiWrapperSingleton.icaltime_as_ical_string_r ? EDSAbiWrapperSingleton.icaltime_as_ical_string_r : EDSAbiWrapperSingleton.icaltime_as_ical_string)
@ -418,6 +432,7 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
# define LIBICAL_MEMFIXES 1
# define icaltime_as_ical_string icaltime_as_ical_string_r
# define icalcomponent_as_ical_string icalcomponent_as_ical_string_r
# define icalproperty_get_value_as_string icalproperty_get_value_as_string_r
# endif /* LIBICAL_MEMFIXES */
# endif /* ENABLE_ICAL */
# endif /* EDS_ABI_WRAPPER_NO_REDEFINE */

View file

@ -381,7 +381,21 @@ class Timespec : public timespec
static Timespec monotonic() { Timespec res; clock_gettime(CLOCK_MONOTONIC, &res); return res; }
static Timespec system() { Timespec res; clock_gettime(CLOCK_REALTIME, &res); return res; }
};
/**
* Acts like a boolean, but in addition, can also tell whether the
* value was explicitly set. Defaults to false.
*/
class Bool {
public:
Bool(bool val = false) : m_value(val), m_wasSet(false) {}
operator bool () const { return m_value; }
Bool & operator = (bool val) { m_value = val; m_wasSet = true; return *this; }
bool wasSet() const { return m_wasSet; }
private:
bool m_value;
bool m_wasSet;
};
/**
* an exception which records the source file and line

View file

@ -508,7 +508,7 @@ int main( int argc, char **argv )
return 0;
}
Cmdline::Bool useDaemon = cmdline.useDaemon();
Bool useDaemon = cmdline.useDaemon();
if(cmdline.monitor()) {

File diff suppressed because it is too large Load diff

View file

@ -286,7 +286,7 @@ class ClientTest {
/**
* utility function for dumping items which are C strings with blank lines as separator
*/
static int dump(ClientTest &client, TestingSyncSource &source, const char *file);
static int dump(ClientTest &client, TestingSyncSource &source, const std::string &file);
/**
* utility function for splitting file into items with blank lines as separator
@ -295,20 +295,20 @@ class ClientTest {
* of the generic version. The caller gets the name of the
* file that was opened here.
*/
static void getItems(const char *file, std::list<std::string> &items, std::string &realfile);
static void getItems(const std::string &file, std::list<std::string> &items, std::string &realfile);
/**
* utility function for importing items with blank lines as separator
*/
static std::string import(ClientTest &client, TestingSyncSource &source,
const ClientTestConfig &config,
const char *file, std::string &realfile);
const std::string &file, std::string &realfile);
/**
* utility function for comparing vCard and iCal files with the external
* synccompare.pl Perl script
*/
static bool compare(ClientTest &client, const char *fileA, const char *fileB);
static bool compare(ClientTest &client, const std::string &fileA, const std::string &fileB);
/**
* utility function: update a vCard or iCalendar item by inserting "MOD-" into
@ -429,7 +429,7 @@ class ClientTest {
*/
class CreateSource {
public:
CreateSource(ClientTest::Config::createsource_t createSourceParam, ClientTest &clientParam, int sourceParam, bool isSourceAParam) :
CreateSource(const ClientTest::Config::createsource_t &createSourceParam, ClientTest &clientParam, int sourceParam, bool isSourceAParam) :
createSource(createSourceParam),
client(clientParam),
source(sourceParam),
@ -473,8 +473,8 @@ public:
client(cl),
source(sourceParam),
config(co),
createSourceA(co.createSourceA, cl, sourceParam, true),
createSourceB(co.createSourceB, cl, sourceParam, false)
createSourceA(co.m_createSourceA, cl, sourceParam, true),
createSourceB(co.m_createSourceB, cl, sourceParam, false)
{}
/** set up before running a test */
@ -495,21 +495,21 @@ public:
* @retval inserted actual data that was inserted, optional
* @return the LUID of the inserted item
*/
virtual std::string insert(CreateSource createSource, const char *data, bool relaxed = false, std::string *inserted = NULL);
virtual std::string insert(CreateSource createSource, const std::string &data, bool relaxed = false, std::string *inserted = NULL);
/**
* assumes that exactly one element is currently inserted and updates it with the given item
*
* @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);
virtual void update(CreateSource createSource, const std::string &data, bool check = true);
/**
* updates one item identified by its LUID with the given item
*
* The type of the item is cleared, as in insert() above.
*/
virtual void update(CreateSource createSource, const char *data, const std::string &luid);
virtual void update(CreateSource createSource, const std::string &data, const std::string &luid);
/** deletes all items locally via sync source */
virtual void deleteAll(CreateSource createSource);
@ -590,6 +590,8 @@ public:
virtual void testLinkedItemsInsertBothUpdateChild();
virtual void testLinkedItemsInsertBothUpdateParent();
/** retrieve right set of items for running test */
ClientTestConfig::LinkedItems_t getParentChildData();
};
int countItemsOfType(TestingSyncSource *source, int state);
@ -751,6 +753,8 @@ protected:
virtual void testSlowSyncSemantic();
virtual void testComplexRefreshFromServerSemantic();
virtual void testDeleteBothSides();
virtual void testAddBothSides();
virtual void testAddBothSidesRefresh();
virtual void testLinkedItemsParentChild();
virtual void testLinkedItemsChild();
virtual void testLinkedItemsChildParent();

View file

@ -113,6 +113,11 @@ itodo20
UID, DTSTART,PERCENT-COMPLETE,SEQUENCE, URL, CLASS
text
-- N/A
-- All-day events are not supported. The server is sent such events as DTSTART/END 00:00:00/23:59:59
floating time and returns them with shifted times (DTSTART 22:00:00 UTC on a different day).
This cannot be recognized as an all-day event anymore by the client.
-- For the same reason, exceptions to a recurring meeting may shift during synchronization
(EXDATE:20001231 -> EXDATE:20001230T220000Z).
* Known test failures:
Client::Sync::vcard21

View file

@ -6,7 +6,6 @@
# start D-Bus session
eval `dbus-launch`
export DBUS_SESSION_BUS_ADDRESS
trap "kill $DBUS_SESSION_BUS_PID" EXIT
# Work-around for GNOME keyring daemon not started
# when accessed via org.freedesktop.secrets: start it
@ -15,20 +14,27 @@ trap "kill $DBUS_SESSION_BUS_PID" EXIT
# https://bugzilla.redhat.com/show_bug.cgi?id=572137
/usr/bin/gnome-keyring-daemon --start --foreground --components=secrets &
KEYRING_PID=$!
trap "kill $KEYRING_PID" EXIT
# kill all programs started by us
trap "kill $KEYRING_PID; kill $DBUS_SESSION_BUS_PID" EXIT
# If DBUS_SESSION_SH_EDS_BASE is set and our main program runs
# under valgrind, then also check EDS. DBUS_SESSION_SH_EDS_BASE
# must be the directory which contains e-addressbook/calendar-factory.
# under valgrind, then also check EDS. Otherwise start EDS only
# for certain known operations which need EDS (syncevolution, client-test)
# but not others (make, configure).
#
# DBUS_SESSION_SH_EDS_BASE must be the directory which contains
# e-addressbook/calendar-factory.
E_CAL_PID=
E_BOOK_PID=
case "$@" in *valgrind*) prefix=`echo $@ | perl -p -e 's;.*?(\S*/?valgrind\S*).*;$1;'`;;
*) prefix=;;
*syncevolution\ *|*client-test\ *|*test-dbus.py\ *) prefix=env;;
*) prefix=;; # don't start EDS
esac
if [ "$DBUS_SESSION_SH_EDS_BASE" ] && [ "$prefix" ]; then
$prefix $DBUS_SESSION_SH_EDS_BASE/e-calendar-factory &
$prefix $DBUS_SESSION_SH_EDS_BASE/e-calendar-factory --keep-running &
E_CAL_PID=$!
$prefix $DBUS_SESSION_SH_EDS_BASE/e-addressbook-factory &
$prefix $DBUS_SESSION_SH_EDS_BASE/e-addressbook-factory --keep-running &
E_BOOK_PID=$!
# give daemons some time to start and register with D-Bus
@ -59,7 +65,7 @@ shutdown () {
fi
wait "$pid"
subres=$?
case $subres in 0|130|143) true;; # 130 and 143 indicate that it was killed, probably by us
case $subres in 0|130|137|143) true;; # 130 and 143 indicate that it was killed, probably by us
*) echo $program failed with return code $subres >&2
if [ $res -eq 0 ]; then
res=$subres

View file

@ -3959,52 +3959,6 @@
obj:*
}
# ==30565==
# ==30565== Thread 1:
# ==30565==
# ==30565== 6,564 bytes in 144 blocks are definitely lost in loss record 48 of 72
# ==30565== at 0x4C2391E: malloc (vg_replace_malloc.c:207)
# ==30565== by 0x5B1FA21: strdup (in /lib/libc-2.9.so)
# ==30565== by 0xD9E080C: icalparameter_new_from_value_string (in /usr/lib/libical.so.0.43.0)
# ==30565== by 0xD9F6AF0: icalparser_add_line (in /usr/lib/libical.so.0.43.0)
# ==30565== by 0xD9F7088: icalparser_parse (in /usr/lib/libical.so.0.43.0)
# ==30565== by 0xD9F7230: icalparser_parse_string (in /usr/lib/libical.so.0.43.0)
# ==30565== by 0xA2CB224: SyncEvo::EvolutionCalendarSource::insertItem(std::string const&, std::string const&, bool) (EvolutionCalendarSource.cpp:287)
# ==30565== by 0x511AF67: SyncEvo::TrackingSyncSource::insertItem(std::string const&, std::string const&) (TrackingSyncSource.cpp:69)
# ==30565== by 0x50D9B8C: SyncEvo::SyncSourceSerialize::insertItemAsKey(sysync::KeyType*, sysync::ItemIDType const*, sysync::ItemIDType*) (SyncSource.cpp:531)
# ==30565== by 0x50D6165: SyncEvo::SyncSourceLogging::insertItemAsKey(sysync::KeyType*, sysync::ItemIDType*, boost::function<unsigned short ()(sysync::KeyType*, sysync::ItemIDType*), std::allocator<void> > const&) (function_template.hpp:825)
# ==30565== by 0x50E3064: SyncEvolution_InsertItemAsKey (function_template.hpp:825)
# ==30565== by 0x5EE86C2: sysync::TDB_Api::InsertItemAsKey(sysync::KeyType*, char const*, sysync::TDB_Api_ItemID&) (dbapi.cpp:1874)
# ==30565== by 0x5EE54B5: sysync::TPluginApiDS::apiAddItem(sysync::TMultiFieldItem&, std::string&) (pluginapids.cpp:1354)
# ==30565== by 0x5E358D1: sysync::TCustomImplDS::createItem(sysync::TSyncItem*, std::string&, bool&) (customimplds.cpp:3219)
# ==30565== by 0x5E6F8C0: sysync::TBinfileImplDS::implProcessItem(sysync::TSyncItem*, sysync::TStatusCommand&) (binfileimplds.cpp:1779)
# ==30565== by 0x5EB0EC9: sysync::TStdLogicDS::logicProcessRemoteItem(sysync::TSyncItem*, sysync::TStatusCommand&, bool&, std::string*) (stdlogicds.cpp:1222)
# ==30565== by 0x5E7FB6D: sysync::TLocalEngineDS::engProcessRemoteItemAsClient(sysync::TSyncItem*, sysync::TStatusCommand&) (localengineds.cpp:5932)
# ==30565== by 0x5E7FFC8: sysync::TLocalEngineDS::engProcessSyncOpItem(sysync::TSyncOperation, sml_item_s*, sml_metinf_metinf_s*, sysync::TStatusCommand&) (localengineds.cpp:4790)
# ==30565== by 0x5E856D9: sysync::TSyncSession::processSyncOpItem(sysync::TSyncOperation, sml_item_s*, sml_metinf_metinf_s*, sysync::TLocalEngineDS*, sysync::TStatusCommand&, bool&) (syncsession.cpp:3643)
# ==30565== by 0x5E6B501: sysync::TSyncOpCommand::execute() (synccommand.cpp:2561)
# ==30565== by 0x5E8AC64: sysync::TSyncSession::process(sysync::TSmlCommand*) (syncsession.cpp:2352)
# ==30565== by 0x5E29548: sysync::TSyncAppBase::AddCmd(void*, sml_generic_s*) (syncappbase.cpp:2071)
# ==30565== by 0x7818D0E: smlProcessData (mgrcmddispatcher.c:484)
# ==30565== by 0x5E3796A: sysync::TSyncClient::processingStep(unsigned short&, sysync::TEngineProgressType*) (syncclient.cpp:541)
# ==30565== by 0x5E5CB9D: sysync::TClientEngineInterface::SessionStep(sysync::SessionType*, unsigned short&, sysync::TEngineProgressType*) (syncclientbase.cpp:274)
# ==30565== by 0x50C0AA7: SyncEvo::SharedEngine::SessionStep(boost::shared_ptr<sysync::SessionType> const&, unsigned short&, sysync::TEngineProgressType*) (SynthesisEngine.cpp:95)
# ==30565== by 0x50E8BC5: SyncEvo::SyncContext::doSync() (SyncContext.cpp:1777)
# ==30565== by 0x50EC228: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:1572)
# ==30565== by 0x43AC59: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (in /work/runtests/head-evolution-testing/build/src/.libs/lt-client-test)
# ==30565== by 0x44F871: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (in /work/runtests/head-evolution-testing/build/src/.libs/lt-client-test)
{
icalparameter new from value string
Memcheck:Leak
fun:malloc
fun:strdup
fun:icalparameter_new_from_value_string
fun:icalparser_add_line
fun:icalparser_parse
fun:icalparser_parse_string
fun:*EvolutionCalendarSource*insertItem*
}
# ==17808==
# ==17808==
# ==17808== 32,519 (2,104 direct, 30,415 indirect) bytes in 67 blocks are definitely lost in loss==17813==
@ -4523,321 +4477,6 @@
fun:clone
}
# ==10204== Invalid read of size 8
# ==10204== at 0x73FA92D: icaltzutil_fetch_timezone (in /usr/lib/libical.so.0.43.0)
# ==10204== by 0x73FBD14: (within /usr/lib/libical.so.0.43.0)
# ==10204== by 0x73FBD64: icaltimezone_get_component (in /usr/lib/libical.so.0.43.0)
# ==10204== by 0x6BE01C: sysync::loadSystemZoneDefinitions(sysync::GZones*) (platform_timezones.cpp:158)
# ==10204== by 0x6A81B8: sysync::GZones::initialize() (timezones.cpp:95)
# ==10204== by 0x6D095E: sysync::TSyncAppBase::TSyncAppBase() (syncappbase.cpp:1227)
# ==10204== by 0x6EC128: sysync::TSyncClientBase::TSyncClientBase() (syncclientbase.cpp:352)
# ==10204== by 0x77B3F8: sysync::TEngineClientBase::TEngineClientBase() (engineclientbase.cpp:102)
# ==10204== by 0x6BE88A: sysync::TCustomClientEngineBase::TCustomClientEngineBase() (clientengine_custom_Base.cpp:49)
# ==10204== by 0x6BE912: sysync::TCustomClientEngineInterface::newSyncAppBase() (clientengine_custom_Base.cpp:39)
# ==10204== by 0x6A420C: sysync::TEngineInterface::Init() (engineinterface.cpp:1056)
# ==10204== by 0x6BBB65: sysync::TEngineModuleBase::Connect(std::string, unsigned long, unsigned short) (enginemodulebase.cpp:85)
# ==10204== by 0x6A673D: sysync::internal_ConnectEngine(bool, sysync::SDK_InterfaceType**, unsigned short, unsigned long*, unsigned long, unsigned short) (engineinterface.cpp:1869)
# ==10204== by 0x6A145A: sysync::UI_Connect(sysync::SDK_InterfaceType*&, void*&, bool&, char const*, unsigned long, unsigned short) (UI_util.cpp:181)
# ==10204== by 0x6BBB65: sysync::TEngineModuleBase::Connect(std::string, unsigned long, unsigned short) (enginemodulebase.cpp:85)
# ==10204== by 0x695D36: SyncEvo::SharedEngine::Connect(std::string const&, unsigned long, unsigned short) (SynthesisEngine.cpp:32)
# ==10204== by 0x62F070: SyncEvo::SyncContext::createEngine() (SyncContext.cpp:2537)
# ==10204== by 0x63DDEB: SyncEvo::SyncContext::SwapEngine::SwapEngine(SyncEvo::SyncContext&) (SyncContext.h:452)
# ==10204== by 0x636DE5: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2708)
# ==10204== by 0x4C07CF: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:379)
# ==10204== by 0x4DE479: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3248)
# ==10204== by 0x587412: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (ClientTest.h:765)
# ==10204== by 0x4E8AB6: SyncEvo::SyncTests::testDeleteAllRefresh() (ClientTest.cpp:1695)
# ==10204== by 0x5B6F406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B617D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6B278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6AFBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B76D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6F09C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6F9FB: CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== Address 0xec7b9b0 is 0 bytes after a block of size 0 alloc'd
# ==10204== at 0x4C216F4: calloc (vg_replace_malloc.c:397)
# ==10204== by 0x73FA492: icaltzutil_fetch_timezone (in /usr/lib/libical.so.0.43.0)
# ==10204== by 0x73FBD14: (within /usr/lib/libical.so.0.43.0)
# ==10204== by 0x73FBD64: icaltimezone_get_component (in /usr/lib/libical.so.0.43.0)
# ==10204== by 0x6BE01C: sysync::loadSystemZoneDefinitions(sysync::GZones*) (platform_timezones.cpp:158)
# ==10204== by 0x6A81B8: sysync::GZones::initialize() (timezones.cpp:95)
# ==10204== by 0x6D095E: sysync::TSyncAppBase::TSyncAppBase() (syncappbase.cpp:1227)
# ==10204== by 0x6EC128: sysync::TSyncClientBase::TSyncClientBase() (syncclientbase.cpp:352)
# ==10204== by 0x77B3F8: sysync::TEngineClientBase::TEngineClientBase() (engineclientbase.cpp:102)
# ==10204== by 0x6BE88A: sysync::TCustomClientEngineBase::TCustomClientEngineBase() (clientengine_custom_Base.cpp:49)
# ==10204== by 0x6BE912: sysync::TCustomClientEngineInterface::newSyncAppBase() (clientengine_custom_Base.cpp:39)
# ==10204== by 0x6A420C: sysync::TEngineInterface::Init() (engineinterface.cpp:1056)
# ==10204== by 0x6BBB65: sysync::TEngineModuleBase::Connect(std::string, unsigned long, unsigned short) (enginemodulebase.cpp:85)
# ==10204== by 0x6A673D: sysync::internal_ConnectEngine(bool, sysync::SDK_InterfaceType**, unsigned short, unsigned long*, unsigned long, unsigned short) (engineinterface.cpp:1869)
# ==10204== by 0x6A145A: sysync::UI_Connect(sysync::SDK_InterfaceType*&, void*&, bool&, char const*, unsigned long, unsigned short) (UI_util.cpp:181)
# ==10204== by 0x6BBB65: sysync::TEngineModuleBase::Connect(std::string, unsigned long, unsigned short) (enginemodulebase.cpp:85)
# ==10204== by 0x695D36: SyncEvo::SharedEngine::Connect(std::string const&, unsigned long, unsigned short) (SynthesisEngine.cpp:32)
# ==10204== by 0x62F070: SyncEvo::SyncContext::createEngine() (SyncContext.cpp:2537)
# ==10204== by 0x63DDEB: SyncEvo::SyncContext::SwapEngine::SwapEngine(SyncEvo::SyncContext&) (SyncContext.h:452)
# ==10204== by 0x636DE5: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2708)
# ==10204== by 0x4C07CF: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:379)
# ==10204== by 0x4DE479: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3248)
# ==10204== by 0x587412: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (ClientTest.h:765)
# ==10204== by 0x4E8AB6: SyncEvo::SyncTests::testDeleteAllRefresh() (ClientTest.cpp:1695)
# ==10204== by 0x5B6F406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B617D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6B278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6AFBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B76D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==10204== by 0x5B6F09C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
{
icaltimezone_get_component
Memcheck:Addr8
fun:icaltzutil_fetch_timezone
obj:*libical.so.*
fun:icaltimezone_get_component
}
# ==23938== Conditional jump or move depends on uninitialised value(s)
# ==23938== at 0x7423FBE: icaltime_adjust (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74294D3: icaltimezone_convert_time (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742587B: icaltime_from_timet_with_zone (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742597A: icaltime_from_timet (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74263CB: icaltzutil_fetch_timezone (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74276F4: (within /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7427744: icaltimezone_get_component (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x6CA11A: sysync::finalizeSystemZoneDefinitions(sysync::GZones*) (platform_timezones.cpp:186)
# ==23938== by 0x6B4544: sysync::GZones::loggingStarted() (timezones.cpp:114)
# ==23938== by 0x6DA507: sysync::TSyncAppBase::finishConfig() (syncappbase.cpp:1441)
# ==23938== by 0x6DA67F: sysync::TSyncAppBase::readXMLConfigStream(int (*)(char*, unsigned long, unsigned long*, void*), void*) (syncappbase.cpp:1753)
# ==23938== by 0x6DA787: sysync::TSyncAppBase::readXMLConfigConstant(char const*) (syncappbase.cpp:1786)
# ==23938== by 0x6B27E9: sysync::TEngineInterface::InitEngineXML(char const*) (engineinterface.cpp:1194)
# ==23938== by 0x69F47C: SyncEvo::SharedEngine::InitEngineXML(std::string const&) (SynthesisEngine.cpp:48)
# ==23938== by 0x624EB6: SyncEvo::SyncContext::initEngine(bool) (SyncContext.cpp:2622)
# ==23938== by 0x6364FE: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2709)
# ==23938== by 0x4BF856: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:379)
# ==23938== by 0x56B6C0: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3248)
# ==23938== by 0x57D9A1: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (ClientTest.h:765)
# ==23938== by 0x4D4EE0: SyncEvo::SyncTests::deleteAll(SyncEvo::SyncTests::DeleteAllMode) (ClientTest.cpp:1620)
# ==23938== by 0x4CDB1E: SyncEvo::SyncTests::testItems() (ClientTest.cpp:2333)
# ==23938== by 0x5B7A406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B6C7D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B76278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B75FBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B7A09C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81B29: CppUnit::TestResult::runTest(CppUnit::Test*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B84121: CppUnit::TestRunner::run(CppUnit::TestResult&, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B8713A: CppUnit::TextTestRunner::run(std::string, bool, bool, bool) (in /usr/lib/libcppunit-1.12.so.1.0.0)
{
icaltimezone_get_component II
Memcheck:Cond
fun:icaltime_adjust
fun:icaltimezone_convert_time
fun:icaltime_from_timet_with_zone
fun:icaltime_from_timet
fun:icaltzutil_fetch_timezone
obj:*libical.so*
fun:icaltimezone_get_component
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
# ==23938== Use of uninitialised value of size 8
# ==23938== at 0x7423DFB: icaltime_days_in_month (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742400B: icaltime_adjust (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74294FB: icaltimezone_convert_time (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742587B: icaltime_from_timet_with_zone (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742597A: icaltime_from_timet (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74263CB: icaltzutil_fetch_timezone (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74276F4: (within /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7427744: icaltimezone_get_component (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x6CA11A: sysync::finalizeSystemZoneDefinitions(sysync::GZones*) (platform_timezones.cpp:186)
# ==23938== by 0x6B4544: sysync::GZones::loggingStarted() (timezones.cpp:114)
# ==23938== by 0x6DA507: sysync::TSyncAppBase::finishConfig() (syncappbase.cpp:1441)
# ==23938== by 0x6DA67F: sysync::TSyncAppBase::readXMLConfigStream(int (*)(char*, unsigned long, unsigned long*, void*), void*) (syncappbase.cpp:1753)
# ==23938== by 0x6DA787: sysync::TSyncAppBase::readXMLConfigConstant(char const*) (syncappbase.cpp:1786)
# ==23938== by 0x6B27E9: sysync::TEngineInterface::InitEngineXML(char const*) (engineinterface.cpp:1194)
# ==23938== by 0x69F47C: SyncEvo::SharedEngine::InitEngineXML(std::string const&) (SynthesisEngine.cpp:48)
# ==23938== by 0x624EB6: SyncEvo::SyncContext::initEngine(bool) (SyncContext.cpp:2622)
# ==23938== by 0x6364FE: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2709)
# ==23938== by 0x4BF856: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:379)
# ==23938== by 0x56B6C0: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3248)
# ==23938== by 0x57D9A1: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (ClientTest.h:765)
# ==23938== by 0x4D4EE0: SyncEvo::SyncTests::deleteAll(SyncEvo::SyncTests::DeleteAllMode) (ClientTest.cpp:1620)
# ==23938== by 0x4CDB1E: SyncEvo::SyncTests::testItems() (ClientTest.cpp:2333)
# ==23938== by 0x5B7A406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B6C7D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B76278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B75FBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B7A09C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81B29: CppUnit::TestResult::runTest(CppUnit::Test*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B84121: CppUnit::TestRunner::run(CppUnit::TestResult&, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
{
icaltimezone_get_component III
Memcheck:Value8
fun:icaltime_days_in_month
fun:icaltime_adjust
fun:icaltimezone_convert_time
fun:icaltime_from_timet_with_zone
fun:icaltime_from_timet
fun:icaltzutil_fetch_timezone
obj:*libical.so*
fun:icaltimezone_get_component
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
{
icaltimezone_get_component III, version 2
Memcheck:Cond
fun:icaltime_days_in_month
fun:icaltime_adjust
fun:icaltimezone_convert_time
fun:icaltime_from_timet_with_zone
fun:icaltime_from_timet
fun:icaltzutil_fetch_timezone
obj:*libical.so*
fun:icaltimezone_get_component
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
{
icaltimezone_get_component IV
Memcheck:Value8
...
fun:icalcomponent_as_ical_string*
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
{
icaltimezone_get_component V
Memcheck:Cond
...
fun:icalcomponent_as_ical_string*
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
# ==23938== Conditional jump or move depends on uninitialised value(s)
# ==23938== at 0x742B5CC: icalvalue_reset_kind (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7415284: icalvalue_new_datetime (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7412488: icalproperty_set_dtstart (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7412554: icalproperty_new_dtstart (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7426476: icaltzutil_fetch_timezone (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x74276F4: (within /usr/lib/libical.so.0.44.0)
# ==23938== by 0x7427744: icaltimezone_get_component (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x6CA11A: sysync::finalizeSystemZoneDefinitions(sysync::GZones*) (platform_timezones.cpp:186)
# ==23938== by 0x6B4544: sysync::GZones::loggingStarted() (timezones.cpp:114)
# ==23938== by 0x6DA507: sysync::TSyncAppBase::finishConfig() (syncappbase.cpp:1441)
# ==23938== by 0x6DA67F: sysync::TSyncAppBase::readXMLConfigStream(int (*)(char*, unsigned long, unsigned long*, void*), void*) (syncappbase.cpp:1753)
# ==23938== by 0x6DA787: sysync::TSyncAppBase::readXMLConfigConstant(char const*) (syncappbase.cpp:1786)
# ==23938== by 0x6B27E9: sysync::TEngineInterface::InitEngineXML(char const*) (engineinterface.cpp:1194)
# ==23938== by 0x69F47C: SyncEvo::SharedEngine::InitEngineXML(std::string const&) (SynthesisEngine.cpp:48)
# ==23938== by 0x624EB6: SyncEvo::SyncContext::initEngine(bool) (SyncContext.cpp:2622)
# ==23938== by 0x6364FE: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2709)
# ==23938== by 0x4BF856: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:379)
# ==23938== by 0x56B6C0: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3248)
# ==23938== by 0x57D9A1: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (ClientTest.h:765)
# ==23938== by 0x4D4EE0: SyncEvo::SyncTests::deleteAll(SyncEvo::SyncTests::DeleteAllMode) (ClientTest.cpp:1620)
# ==23938== by 0x4CDB1E: SyncEvo::SyncTests::testItems() (ClientTest.cpp:2333)
# ==23938== by 0x5B7A406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B6C7D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B76278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B75FBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B7A09C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81B29: CppUnit::TestResult::runTest(CppUnit::Test*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B84121: CppUnit::TestRunner::run(CppUnit::TestResult&, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B8713A: CppUnit::TextTestRunner::run(std::string, bool, bool, bool) (in /usr/lib/libcppunit-1.12.so.1.0.0)
{
icaltimezone_get_component IV
Memcheck:Cond
fun:icalvalue_reset_kind
fun:icalvalue_new_datetime
fun:icalproperty_set_dtstart
fun:icalproperty_new_dtstart
fun:icaltzutil_fetch_timezone
obj:*libical.so*
fun:icaltimezone_get_component
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
# ==23938== Conditional jump or move depends on uninitialised value(s)
# ==23938== at 0x8053794: vfprintf (in /lib/libc-2.9.so)
# ==23938== by 0x8076759: vsnprintf (in /lib/libc-2.9.so)
# ==23938== by 0x805BBA2: snprintf (in /lib/libc-2.9.so)
# ==23938== by 0x742B728: print_date_to_string (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742B865: print_datetime_to_string (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x742BFF8: icalvalue_as_ical_string_r (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x741F1C4: icalproperty_as_ical_string_r (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x741AD58: icalcomponent_as_ical_string_r (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x741ADAF: icalcomponent_as_ical_string_r (in /usr/lib/libical.so.0.44.0)
# ==23938== by 0x6CA12D: sysync::finalizeSystemZoneDefinitions(sysync::GZones*) (platform_timezones.cpp:189)
# ==23938== by 0x6B4544: sysync::GZones::loggingStarted() (timezones.cpp:114)
# ==23938== by 0x6DA507: sysync::TSyncAppBase::finishConfig() (syncappbase.cpp:1441)
# ==23938== by 0x6DA67F: sysync::TSyncAppBase::readXMLConfigStream(int (*)(char*, unsigned long, unsigned long*, void*), void*) (syncappbase.cpp:1753)
# ==23938== by 0x6DA787: sysync::TSyncAppBase::readXMLConfigConstant(char const*) (syncappbase.cpp:1786)
# ==23938== by 0x6B27E9: sysync::TEngineInterface::InitEngineXML(char const*) (engineinterface.cpp:1194)
# ==23938== by 0x69F47C: SyncEvo::SharedEngine::InitEngineXML(std::string const&) (SynthesisEngine.cpp:48)
# ==23938== by 0x624EB6: SyncEvo::SyncContext::initEngine(bool) (SyncContext.cpp:2622)
# ==23938== by 0x6364FE: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2709)
# ==23938== by 0x4BF856: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:379)
# ==23938== by 0x56B6C0: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3248)
# ==23938== by 0x57D9A1: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (ClientTest.h:765)
# ==23938== by 0x4D4EE0: SyncEvo::SyncTests::deleteAll(SyncEvo::SyncTests::DeleteAllMode) (ClientTest.cpp:1620)
# ==23938== by 0x4CDB1E: SyncEvo::SyncTests::testItems() (ClientTest.cpp:2333)
# ==23938== by 0x5B7A406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B6C7D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B76278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B75FBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B7A09C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==23938== by 0x5B81B29: CppUnit::TestResult::runTest(CppUnit::Test*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
{
icalcomponent_as_ical_string_r
Memcheck:Cond
fun:vfprintf
fun:vsnprintf
fun:snprintf
fun:print_date_to_string
fun:print_datetime_to_string
fun:icalvalue_as_ical_string_r
fun:icalproperty_as_ical_string_r
fun:icalcomponent_as_ical_string_r
fun:icalcomponent_as_ical_string_r
fun:_ZN6sysync29finalizeSystemZoneDefinitionsEPNS_6GZonesE
}
# ==12472== 13,800 bytes in 5 blocks are possibly lost in loss record 890 of 925
# ==12472== at 0x4C244E8: malloc (vg_replace_malloc.c:236)
# ==12472== by 0x74A36E8: icalvalue_set_recur (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0x74A375F: icalvalue_new_recur (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0x749DC17: icalproperty_set_rrule (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0x749DC7F: icalproperty_new_rrule (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0x74B3900: icaltzutil_fetch_timezone (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0x74B46F4: ??? (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0x74B4744: icaltimezone_get_component (in /usr/lib/libical.so.0.44.0)
# ==12472== by 0xAA9C3C: sysync::finalizeSystemZoneDefinitions(sysync::GZones*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0xA78EA8: sysync::GZones::loggingStarted() (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0xA37ECD: sysync::TSyncAppBase::finishConfig() (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0xA386E0: sysync::TSyncAppBase::readXMLConfigStream(int (*)(char*, unsigned long, unsigned long*, void*), void*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0xA38A25: sysync::TSyncAppBase::readXMLConfigConstant(char const*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x9DEB2E: sysync::TEngineInterface::InitEngineXML(char const*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x9DA630: sysync::InitEngineXML(void*, char const*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x9CF250: sysync::TEngineModuleBridge::InitEngineXML(char const*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x9C1264: SyncEvo::SharedEngine::InitEngineXML(std::string const&) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x9046AD: SyncEvo::SyncContext::initEngine(bool) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x9051F1: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x65E8D8: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x75F090: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x76BCD1: SyncEvo::SyncTests::doSync(char const*, SyncEvo::SyncOptions const&) (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x75D7AB: SyncEvo::SyncTests::testTimeout() (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x7737F9: CppUnit::TestCaller<SyncEvo::SyncTests>::runTest() (in /home/pohly/work/syncevolution/src/client-test)
# ==12472== by 0x5C22406: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==12472== by 0x5C147D3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==12472== by 0x5C1E278: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==12472== by 0x5C1DFBB: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==12472== by 0x5C29D9F: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==12472== by 0x5C2209C: CppUnit::TestCase::run(CppUnit::TestResult*) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==12472==
{
potential leaks in time zone allocation
Memcheck:Leak
...
fun:icaltimezone_get_component
fun:*finalizeSystemZoneDefinitions*
}
# ==16317== 1 bytes in 1 blocks are possibly lost in loss record 1 of 1,445
# ==16317== at 0x4C244E8: malloc (vg_replace_malloc.c:236)
# ==16317== by 0x6901534: g_malloc (in /lib/libglib-2.0.so.0.2400.2)

50
test/notification-daemon.py Executable file
View file

@ -0,0 +1,50 @@
#! /usr/bin/python -u
#
# Copyright (C) 2009 Intel Corporation
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) version 3.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import dbus.service
import gobject
import random
class Notifications (dbus.service.Object):
'''fake org.freedesktop.Notifications implementation,'''
'''used when there is none already registered on the session bus'''
@dbus.service.method(dbus_interface='org.freedesktop.Notifications', in_signature='', out_signature='ssss')
def GetServerInformation(self):
return ('test-dbus', 'SyncEvolution', '0.1', '1.1')
@dbus.service.method(dbus_interface='org.freedesktop.Notifications', in_signature='', out_signature='as')
def GetCapabilities(self):
return ['actions', 'body', 'body-hyperlinks', 'body-markup', 'icon-static', 'sound']
@dbus.service.method(dbus_interface='org.freedesktop.Notifications', in_signature='susssasa{sv}i', out_signature='u')
def Notify(self, app, replaces, icon, summary, body, actions, hints, expire):
return random.randint(1,100)
DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
loop = gobject.MainLoop()
name = dbus.service.BusName("org.freedesktop.Notifications", bus)
# start dummy notification daemon, if possible;
# if it fails, ignore (probably already one running)
notifications = Notifications(bus, "/org/freedesktop/Notifications")
loop.run()

View file

@ -341,14 +341,23 @@ def step2(resultdir, result, servers, indents, srcdir, shellprefix, backenddir):
# <path>/Client_Sync_eds_contact_testItems.log
# <path>/SyncEvo_CmdlineTest_testConfigure.log
# <path>/N7SyncEvo11CmdlineTestE_testConfigure.log - C++ name mangling?
m = re.match(r'.*/(Client_Source_|Client_Sync_|N7SyncEvo\d+|[^_]*_)(.*)_([^_]*)', log)
m = re.match(r'.*/(Client_Source_|Client_Sync_|N7SyncEvo\d+|[^_]*_)(.*)_([^_]*)\.log', log)
# Client_Sync_, Client_Source_, SyncEvo_, ...
prefix = m.group(1)
# eds_contact, CmdlineTest, ...
format = m.group(2)
# testImport
casename = m.group(3)
# special case grouping of some tests: include group inside casename instead of
# format, example:
# <path>/Client_Source_apple_caldav_LinkedItems_1_testLinkedItemsParent
m = re.match(r'(.*)_(LinkedItems_\d+)', format)
if m:
format = m.group(1)
casename = m.group(2) + '::' + casename
if(format not in logdic):
logdic[format]=[]
logdic[format].append(log)
logdic[format].append((casename, log))
logprefix[format]=prefix
for format in logdic.keys():
indent +=space
@ -360,23 +369,27 @@ def step2(resultdir, result, servers, indents, srcdir, shellprefix, backenddir):
qformat = qformat.replace("_", "__");
qformat = qformat.replace("+", "_-");
result.write(indent+'<'+qformat+' prefix="'+prefix+'">\n')
for case in logdic[format]:
for casename, log in logdic[format]:
indent +=space
indents.append(indent)
casename = case.rpartition('_')[2].partition('.')[0]
result.write(indent+'<'+casename+'>')
# must avoid :: in XML
tag = casename.replace('::', '__')
# special case LinkedItems_1::testLinkedItems...: shorten it
# if tag.startswith('LinkedItems_'):
# tag = tag.split('_', 1)[1]
result.write(indent+'<'+tag+'>')
match=format+'::'+casename
matchOk=match+": okay \*\*\*"
matchKnownFailure=match+": \*\*\* failure ignored \*\*\*"
if not os.system("grep -q '" + matchKnownFailure + "' "+case):
if not os.system("grep -q '" + matchKnownFailure + "' "+log):
result.write('knownfailure')
elif not os.system("tail -10 %s | grep -q 'external transport failure (local, status 20043)'" % case):
elif not os.system("tail -10 %s | grep -q 'external transport failure (local, status 20043)'" % log):
result.write('network')
elif os.system("grep -q '" + matchOk + "' "+case):
elif os.system("grep -q '" + matchOk + "' "+log):
result.write('failed')
else:
result.write('okay')
result.write('</'+casename+'>\n')
result.write('</'+tag+'>\n')
indents.pop()
indent = indents[-1]
result.write(indent+'</'+qformat+'>\n')

View file

@ -772,7 +772,7 @@ class SyncEvolutionDist(AutotoolsBuild):
cd(self.builddir)
if self.packagesuffix:
context.runCommand("%s %s BINSUFFIX=%s deb rpm" % (self.runner, context.make, self.packagesuffix))
put, get = os.popen4("%s %s dpkg-architecture -qDEB_HOST_ARCH" % (self.runner, context.make))
put, get = os.popen4("%s dpkg-architecture -qDEB_HOST_ARCH" % (self.runner))
for arch in get.readlines():
if "i386" in arch:
context.runCommand("%s %s BINSUFFIX=%s PKGARCH=lpia deb" % (self.runner, context.make, self.packagesuffix))
@ -838,7 +838,7 @@ context.add(test)
test = SyncEvolutionTest("davical", compile,
"", options.shell,
"Client::Sync::eds_contact::testItems Client::Sync::eds_event::testItems Client::Source::davical_caldav Client::Source::davical_carddav",
"Client::Sync::eds_contact Client::Sync::eds_event Client::Source::davical_caldav Client::Source::davical_carddav",
[ "davical_caldav", "davical_carddav", "eds_event", "eds_contact" ],
"CLIENT_TEST_WEBDAV='davical caldav carddav' "
"CLIENT_TEST_NUM_ITEMS=10 " # don't stress server
@ -855,7 +855,6 @@ test = SyncEvolutionTest("apple", compile,
"CLIENT_TEST_WEBDAV='apple caldav carddav' "
"CLIENT_TEST_NUM_ITEMS=250 " # test is local, so we can afford a higher number
"CLIENT_TEST_ALARM=2400 " # but even with a local server does the test run a long time
"CLIENT_TEST_SIMPLE_UID=1 " # server gets confused by UID with special characters
"CLIENT_TEST_MODE=server " # for Client::Sync
,
testPrefix=options.testprefix)
@ -1001,6 +1000,15 @@ class FunambolTest(SyncEvolutionTest):
"eds_task",
"eds_memo" ],
"CLIENT_TEST_SKIP="
# server duplicates items in add<->add conflict because it
# does not check UID
"Client::Sync::eds_event::testAddBothSides,"
"Client::Sync::eds_event::testAddBothSidesRefresh,"
"Client::Sync::eds_task::testAddBothSides,"
"Client::Sync::eds_task::testAddBothSidesRefresh,"
# test cannot pass because we don't have CtCap info about
# the Funambol server
"Client::Sync::eds_contact::testExtensions,"
"Client::Sync::eds_event::Retry,"
"Client::Sync::eds_event::Suspend,"
"Client::Sync::eds_event::Resend,"
@ -1097,6 +1105,12 @@ mobicaltest = SyncEvolutionTest("mobical", compile,
"CLIENT_TEST_NOCHECK_SYNCMODE=1 "
"CLIENT_TEST_MAX_ITEMSIZE=2048 "
"CLIENT_TEST_SKIP="
# server duplicates items in add<->add conflict because it
# does not check UID
"Client::Sync::eds_event::testAddBothSides,"
"Client::Sync::eds_event::testAddBothSidesRefresh,"
"Client::Sync::eds_task::testAddBothSides,"
"Client::Sync::eds_task::testAddBothSidesRefresh,"
"Client::Sync::eds_contact::Retry,"
"Client::Sync::eds_contact::Suspend,"
"Client::Sync::eds_contact::Resend,"
@ -1174,12 +1188,18 @@ memotootest = SyncEvolutionTest("memotoo", compile,
"CLIENT_TEST_NOCHECK_SYNCMODE=1 "
"CLIENT_TEST_NUM_ITEMS=10 "
"CLIENT_TEST_SKIP="
# server duplicates items in add<->add conflict because it
# does not check UID
"Client::Sync::eds_event::testAddBothSides,"
"Client::Sync::eds_event::testAddBothSidesRefresh,"
"Client::Sync::eds_task::testAddBothSides,"
"Client::Sync::eds_task::testAddBothSidesRefresh,"
"Client::Sync::eds_contact::Retry,"
"Client::Sync::eds_contact::Suspend,"
"Client::Sync::eds_contact::testRefreshFromClientSync,"
"Client::Sync::eds_contact::testRefreshFromClientSemantic,"
"Client::Sync::eds_contact::testDeleteAllRefresh,"
"Client::Sync::eds_contact::testOneWayFromServer,"
# "Client::Sync::eds_contact::testRefreshFromClientSync,"
# "Client::Sync::eds_contact::testRefreshFromClientSemantic,"
# "Client::Sync::eds_contact::testDeleteAllRefresh,"
# "Client::Sync::eds_contact::testOneWayFromServer,"
"Client::Sync::eds_event::testRefreshFromClientSync,"
"Client::Sync::eds_event::testRefreshFromClientSemantic,"
"Client::Sync::eds_event::testOneWayFromServer,"

View file

@ -421,15 +421,11 @@ sub NormalizeItem {
if ($synthesis) {
# does not preserve certain properties
s/^(FN|BDAY|X-MOZILLA-HTML|X-EVOLUTION-FILE-AS|X-AIM|NICKNAME|UID|PHOTO|CALURI|SEQUENCE|TRANSP|ORGANIZER)(;[^:;\n]*)*:.*\r?\n?//gm;
s/^(FN|BDAY|X-MOZILLA-HTML|X-EVOLUTION-FILE-AS|X-AIM|NICKNAME|UID|PHOTO|CALURI|SEQUENCE|TRANSP|ORGANIZER|ROLE|FBURL|X-ANNIVERSARY|X-ASSISTANT|X-EVOLUTION-BLOG-URL|X-EVOLUTION-VIDEO-URL|X-GADUGADU|X-GROUPWISE|X-ICQ|X-JABBER|X-MANAGER|X-MSN|X-SIP|X-SKYPE|X-SPOUSE|X-YAHOO)(;[^:;\n]*)*:.*\r?\n?//gm;
# default ADR is HOME
s/^ADR;TYPE=HOME/ADR/gm;
# only some parts of N are preserved
s/^N((?:;[^;:]*)*)\:(.*)/@_ = split(\/(?<!\\);\/, $2); "N$1:$_[0];" . ($_[1] || "") . ";;" . ($_[3] || "")/gme;
# this vcard contains too many ADR and PHONE entries - ignore it
if (/This is a test case which uses almost all Evolution fields/) {
next;
}
# breaks lines at semicolons, which adds white space
while( s/^ADR:(.*); +/ADR:$1;/gm ) {}
# no attributes stored for ATTENDEEs

View file

@ -542,3 +542,87 @@
fun:smlProcessData
}
# ==19808== Invalid read of size 4
# ==19808== at 0x106E4E9A: asn1_der_coding (in /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.11)
# ==19808== by 0xD37A2F8: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD35D754: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD35D995: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD360442: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD3537EC: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD3505DF: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD3506D4: gnutls_handshake (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0x1473F1A8: ??? (in /usr/lib/gio/modules/libgiognutls.so)
# ==19808== by 0x14740D22: ??? (in /usr/lib/gio/modules/libgiognutls.so)
# ==19808== by 0x5B9C6F0: soup_socket_write (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x5B8BEDA: ??? (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x5B8C81D: ??? (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x6762E7D: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x67748D6: ??? (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x677DD04: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x677DED2: g_signal_emit (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x5B9A1AD: ??? (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x1473EC0F: ??? (in /usr/lib/gio/modules/libgiognutls.so)
# ==19808== by 0x6DF64A2: g_main_context_dispatch (in /lib/libglib-2.0.so.0.2800.6)
# ==19808== by 0x6DF6C7F: ??? (in /lib/libglib-2.0.so.0.2800.6)
# ==19808== by 0x6DF72F1: g_main_loop_run (in /lib/libglib-2.0.so.0.2800.6)
# ==19808== by 0x7240A8: SyncEvo::SoupTransportAgent::wait(bool) (SoupTransportAgent.cpp:177)
# ==19808== by 0x6B6E51: SyncEvo::SyncContext::doSync() (SyncContext.cpp:3597)
# ==19808== by 0x6BD0B4: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2904)
# ==19808== by 0x4F6521: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:472)
# ==19808== by 0x511D6B: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3959)
# ==19808== by 0x5C0BDF: SyncEvo::SyncTests::testTwoWaySync() (ClientTest.h:688)
# ==19808== by 0x610F749: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==19808== by 0x6102C83: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==19808== Address 0x10fbcaf4 is 20 bytes inside a block of size 22 alloc'd
# ==19808== at 0x4C2779D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
# ==19808== by 0x106E4E7B: asn1_der_coding (in /usr/lib/x86_64-linux-gnu/libtasn1.so.3.1.11)
# ==19808== by 0xD37A2F8: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD35D754: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD35D995: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD360442: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD3537EC: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD3505DF: ??? (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0xD3506D4: gnutls_handshake (in /usr/lib/libgnutls.so.26.16.14)
# ==19808== by 0x1473F1A8: ??? (in /usr/lib/gio/modules/libgiognutls.so)
# ==19808== by 0x14740D22: ??? (in /usr/lib/gio/modules/libgiognutls.so)
# ==19808== by 0x5B9C6F0: soup_socket_write (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x5B8BEDA: ??? (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x5B8C81D: ??? (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x6762E7D: g_closure_invoke (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x67748D6: ??? (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x677DD04: g_signal_emit_valist (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x677DED2: g_signal_emit (in /usr/lib/libgobject-2.0.so.0.2800.6)
# ==19808== by 0x5B9A1AD: ??? (in /usr/lib/libsoup-2.4.so.1.4.0)
# ==19808== by 0x1473EC0F: ??? (in /usr/lib/gio/modules/libgiognutls.so)
# ==19808== by 0x6DF64A2: g_main_context_dispatch (in /lib/libglib-2.0.so.0.2800.6)
# ==19808== by 0x6DF6C7F: ??? (in /lib/libglib-2.0.so.0.2800.6)
# ==19808== by 0x6DF72F1: g_main_loop_run (in /lib/libglib-2.0.so.0.2800.6)
# ==19808== by 0x7240A8: SyncEvo::SoupTransportAgent::wait(bool) (SoupTransportAgent.cpp:177)
# ==19808== by 0x6B6E51: SyncEvo::SyncContext::doSync() (SyncContext.cpp:3597)
# ==19808== by 0x6BD0B4: SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (SyncContext.cpp:2904)
# ==19808== by 0x4F6521: SyncEvo::TestEvolution::doSync(int const*, std::string const&, SyncEvo::SyncOptions const&) (client-test-app.cpp:472)
# ==19808== by 0x511D6B: SyncEvo::SyncTests::doSync(SyncEvo::SyncOptions const&) (ClientTest.cpp:3959)
# ==19808== by 0x5C0BDF: SyncEvo::SyncTests::testTwoWaySync() (ClientTest.h:688)
# ==19808== by 0x610F749: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0)
# ==19808==
{
glib-networking 2.28.7 + gnutls 2.10.5-3 + Google: ASN buffer
Memcheck:Addr4
fun:asn1_der_coding
...
obj:*libgiognutls.so
}
{
gnutls + libneon: ASN buffer
Memcheck:Addr4
fun:asn1_der_coding
...
obj:*libneon*
}
{
gnutls certificate: ASN buffer
Memcheck:Addr4
fun:asn1_der_coding
...
fun:gnutls_certificate_set_x509_trust_file
}

View file

@ -33,6 +33,7 @@ import dbus.service
import gobject
import sys
import re
import atexit
# introduced in python-gobject 2.16, not available
# on all Linux distros => make it optional
@ -44,9 +45,6 @@ except ImportError:
DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
loop = gobject.MainLoop()
debugger = "" # "gdb"
server = ["syncevo-dbus-server"]
monitor = ["dbus-monitor"]
@ -54,6 +52,50 @@ monitor = ["dbus-monitor"]
xdg_root = "temp-test-dbus"
configName = "dbus_unittest"
def GrepNotifications(dbuslog):
'''finds all Notify calls and returns their parameters as list of line lists'''
return re.findall(r'^method call .* dest=.* .*interface=org.freedesktop.Notifications; member=Notify\n((?:^ .*\n)*)',
dbuslog,
re.MULTILINE)
# See notification-daemon.py for a stand-alone version.
#
# Embedded here to avoid issues with setting up the environment
# in such a way that the stand-alone version can be run
# properly.
class Notifications (dbus.service.Object):
'''fake org.freedesktop.Notifications implementation,'''
'''used when there is none already registered on the session bus'''
@dbus.service.method(dbus_interface='org.freedesktop.Notifications', in_signature='', out_signature='ssss')
def GetServerInformation(self):
return ('test-dbus', 'SyncEvolution', '0.1', '1.1')
@dbus.service.method(dbus_interface='org.freedesktop.Notifications', in_signature='', out_signature='as')
def GetCapabilities(self):
return ['actions', 'body', 'body-hyperlinks', 'body-markup', 'icon-static', 'sound']
@dbus.service.method(dbus_interface='org.freedesktop.Notifications', in_signature='susssasa{sv}i', out_signature='u')
def Notify(self, app, replaces, icon, summary, body, actions, hints, expire):
return random.randint(1,100)
# fork before connecting to the D-Bus daemon
child = os.fork()
if child == 0:
bus = dbus.SessionBus()
loop = gobject.MainLoop()
name = dbus.service.BusName("org.freedesktop.Notifications", bus)
# start dummy notification daemon, if possible;
# if it fails, ignore (probably already one running)
notifications = Notifications(bus, "/org/freedesktop/Notifications")
loop.run()
sys.exit(0)
# testing continues in parent process
atexit.register(os.kill, child, 9)
bus = dbus.SessionBus()
loop = gobject.MainLoop()
def property(key, value):
"""Function decorator which sets an arbitrary property of a test.
Use like this:
@ -313,6 +355,10 @@ class DBusUtil(Timeout):
# and increase log level
env["SYNCEVOLUTION_DEBUG"] = "1"
# can be set by a test to run additional tests on the content
# of the D-Bus log
self.runTestDBusCheck = None
# testAutoSyncFailure (__main__.TestSessionAPIsDummy) => testAutoSyncFailure_TestSessionAPIsDummy
testname = str(self).replace(" ", "_").replace("__main__.", "").replace("(", "").replace(")", "")
dbuslog = testname + ".dbus.log"
@ -407,6 +453,13 @@ class DBusUtil(Timeout):
monitorout = open(dbuslog).read()
report = "\n\nD-Bus traffic:\n%s\n\nserver output:\n%s\n" % \
(monitorout, serverout)
if self.runTestDBusCheck:
try:
self.runTestDBusCheck(self, monitorout)
except:
# only append report if not part of some other error below
result.errors.append((self,
"D-Bus log failed check: %s\n%s" % (sys.exc_info()[1], (not hasfailed and report) or "")))
if DBusUtil.pserver.returncode and DBusUtil.pserver.returncode != -15:
# create a new failure specifically for the server
result.errors.append((self,
@ -1912,11 +1965,11 @@ class TestSessionAPIsDummy(unittest.TestCase, DBusUtil):
self.failUnlessEqual(self.lastState, "done")
@timeout(60)
def testAutoSyncFailure(self):
"""TestSessionAPIsDummy.testAutoSyncFailure - test that auto-sync is triggered, fails here"""
def testAutoSyncNetworkFailure(self):
"""TestSessionAPIsDummy.testAutoSyncNetworkFailure - test that auto-sync is triggered, fails due to (temporary?!) network error here"""
self.setupConfig()
# enable auto-sync
config = self.config
config = copy.deepcopy(self.config)
# Note that writing this config will modify the host's keyring!
# Use a syncURL that is unlikely to conflict with the host
# or any other D-Bus test.
@ -1980,12 +2033,23 @@ class TestSessionAPIsDummy(unittest.TestCase, DBusUtil):
self.failUnless(delta < 13)
self.failUnless(delta > 7)
# check that org.freedesktop.Notifications.Notify was not called
# (network errors are considered temporary, can't tell in this case
# that the name lookup error is permanent)
def checkDBusLog(self, content):
notifications = GrepNotifications(content)
self.failUnlessEqual(notifications,
[])
# done as part of post-processing in runTest()
self.runTestDBusCheck = checkDBusLog
@timeout(60)
def testAutoSyncLocal(self):
"""TestSessionAPIsDummy.testAutoSyncLocal - test that auto-sync is triggered for local sync"""
def testAutoSyncLocalConfigError(self):
"""TestSessionAPIsDummy.testAutoSyncLocalConfigError - test that auto-sync is triggered for local sync, fails due to permanent config error here"""
self.setupConfig()
# enable auto-sync
config = self.config
config = copy.deepcopy(self.config)
config[""]["syncURL"] = "local://@foobar" # will fail
config[""]["autoSync"] = "1"
config[""]["autoSyncDelay"] = "0"
@ -2028,6 +2092,128 @@ class TestSessionAPIsDummy(unittest.TestCase, DBusUtil):
flags = session.GetFlags()
self.failUnlessEqual(flags, [])
# check that org.freedesktop.Notifications.Notify was called
# once to report the failed attempt to start the sync
def checkDBusLog(self, content):
notifications = GrepNotifications(content)
self.failUnlessEqual(notifications,
[' string "SyncEvolution"\n'
' uint32 0\n'
' string ""\n'
' string "Sync problem."\n'
' string "Sorry, there\'s a problem with your sync that you need to attend to."\n'
' array [\n'
' string "view"\n'
' string "View"\n'
' string "default"\n'
' string "Dismiss"\n'
' ]\n'
' array [\n'
' ]\n'
' int32 -1\n'])
# done as part of post-processing in runTest()
self.runTestDBusCheck = checkDBusLog
@timeout(60)
def testAutoSyncLocalSuccess(self):
"""TestSessionAPIsDummy.testAutoSyncLocalSuccess - test that auto-sync is done successfully for local sync between file backends"""
# create @foobar config
self.session.Detach()
self.setUpSession("target-config@foobar")
config = copy.deepcopy(self.config)
config[""]["remoteDeviceId"] = "foo"
config[""]["deviceId"] = "bar"
for i in ("addressbook", "calendar", "todo", "memo"):
source = config["source/" + i]
source["database"] = source["database"] + ".server"
self.session.SetConfig(False, False, config, utf8_strings=True)
self.session.Detach()
# create dummy-test@default auto-sync config
self.setUpSession("dummy-test")
config = copy.deepcopy(self.config)
config[""]["syncURL"] = "local://@foobar"
config[""]["PeerIsClient"] = "1"
config[""]["autoSync"] = "1"
config[""]["autoSyncDelay"] = "0"
config[""]["autoSyncInterval"] = "10s"
config["source/addressbook"]["uri"] = "addressbook"
self.session.SetConfig(False, False, config, utf8_strings=True)
def session_ready(object, ready):
if self.running and object != self.sessionpath and \
(self.auto_sync_session_path == None and ready or \
self.auto_sync_session_path == object):
self.auto_sync_session_path = object
DBusUtil.quit_events.append("session " + object + (ready and " ready" or " done"))
loop.quit()
signal = bus.add_signal_receiver(session_ready,
'SessionChanged',
'org.syncevolution.Server',
self.server.bus_name,
None,
byte_arrays=True,
utf8_strings=True)
# shut down current session, will allow auto-sync
self.session.Detach()
# wait for start and end of auto-sync session
loop.run()
loop.run()
self.failUnlessEqual(DBusUtil.quit_events, ["session " + self.auto_sync_session_path + " ready",
"session " + self.auto_sync_session_path + " done"])
session = dbus.Interface(bus.get_object(self.server.bus_name,
self.auto_sync_session_path),
'org.syncevolution.Session')
reports = session.GetReports(0, 100, utf8_strings=True)
self.failUnlessEqual(len(reports), 1)
self.failUnlessEqual(reports[0]["status"], "200")
name = session.GetConfigName()
self.failUnlessEqual(name, "dummy-test")
flags = session.GetFlags()
self.failUnlessEqual(flags, [])
# check that org.freedesktop.Notifications.Notify was called
# when starting and completing the sync
def checkDBusLog(self, content):
notifications = GrepNotifications(content)
self.failUnlessEqual(notifications,
[' string "SyncEvolution"\n'
' uint32 0\n'
' string ""\n'
' string "dummy-test is syncing"\n'
' string "We have just started to sync your computer with the dummy-test sync service."\n'
' array [\n'
' string "view"\n'
' string "View"\n'
' string "default"\n'
' string "Dismiss"\n'
' ]\n'
' array [\n'
' ]\n'
' int32 -1\n',
' string "SyncEvolution"\n'
' uint32 0\n'
' string ""\n'
' string "dummy-test sync complete"\n'
' string "We have just finished syncing your computer with the dummy-test sync service."\n'
' array [\n'
' string "view"\n'
' string "View"\n'
' string "default"\n'
' string "Dismiss"\n'
' ]\n'
' array [\n'
' ]\n'
' int32 -1\n'])
# done as part of post-processing in runTest()
self.runTestDBusCheck = checkDBusLog
class TestSessionAPIsReal(unittest.TestCase, DBusUtil):
""" This class is used to test those unit tests of session APIs, depending on doing sync.
@ -2302,6 +2488,7 @@ class TestConnection(unittest.TestCase, DBusUtil):
"connection " + conpath + " got final reply",
"session done"])
@timeout(20)
def testCredentialsRight(self):
"""TestConnection.testCredentialsRight - send correct credentials"""
self.setupConfig()

View file

@ -3,7 +3,7 @@ VERSION:3.0
NICKNAME:user17
NOTE:triggers parser bug in Funambol 3.0: trailing = is mistaken for soft line break=
FN:parserbug=
N:parserbug=
N:parserbug=;;;;
X-EVOLUTION-FILE-AS:parserbug=
END:VCARD
@ -12,7 +12,7 @@ VERSION:3.0
NICKNAME:user16
NOTE:test case with empty email
FN:incomplete
N:incomplete
N:incomplete;;;;
EMAIL:
X-EVOLUTION-FILE-AS:incomplete
END:VCARD
@ -162,7 +162,7 @@ X-EVOLUTION-MANAGER:John Doe Senior
X-EVOLUTION-ASSISTANT:John Doe Junior
NICKNAME:user1
BDAY:2006-01-08
X-FOOBAR-EXTENSION;X-FOOBAR-PARAMETER=foobar:has to be stored internally by engine and preserved in testExtensions test; never sent to a peer
X-FOOBAR-EXTENSION;X-FOOBAR-PARAMETER=foobar:has to be stored internally by engine and preserved in testExtensions test\; never sent to a peer
X-TEST;PARAMETER1=nonquoted;PARAMETER2="quoted because of spaces":Content with\nMultiple\nText lines\nand national chars: äöü
X-EVOLUTION-ANNIVERSARY:2006-01-09
X-EVOLUTION-SPOUSE:Joan Doe

View file

@ -1,9 +1,9 @@
@@ -147,7 +147,7 @@
FBURL:
X-EVOLUTION-VIDEO-URL:
X-MOZILLA-HTML:FALSE
-ADR;TYPE=HOME:;Address Line 2\nAddress Line 3;Address Line 1;;;;
+ADR;TYPE=HOME:;Address Line 2 Address Line 3;Address Line 1;;;;
LABEL;TYPE=HOME:Address Line 1\nAddress Line 2\nAddress Line 3
UID:pas-id-43C15DFB000001AB
END:VCARD
@@ -163,7 +163,7 @@
NICKNAME:user1
BDAY:2006-01-08
X-FOOBAR-EXTENSION;X-FOOBAR-PARAMETER=foobar:has to be stored internally by engine and preserved in testExtensions test\; never sent to a peer
-X-TEST;PARAMETER1=nonquoted;PARAMETER2="quoted because of spaces":Content with\nMultiple\nText lines\nand national chars: äöü
+X-TEST;PARAMETER1=nonquoted:Content with\nMultiple\nText lines\nand national chars: äöü
X-EVOLUTION-ANNIVERSARY:2006-01-09
X-EVOLUTION-SPOUSE:Joan Doe
NOTE:This is a test case which uses almost all Evolution fields.

View file

@ -1,14 +1,14 @@
@@ -4,6 +4,7 @@
NOTE:triggers parser bug in Funambol 3.0: trailing = is mistaken for soft line break=
FN:parserbug=
N:parserbug=
N:parserbug=;;;;
+URL:http://john.doe.com
X-EVOLUTION-FILE-AS:parserbug=
END:VCARD
@@ -14,6 +15,7 @@
FN:incomplete
N:incomplete
N:incomplete;;;;
EMAIL:
+URL:http://john.doe.com
X-EVOLUTION-FILE-AS:incomplete
@ -70,13 +70,19 @@
X-EVOLUTION-FILE-AS:characters\, special
X-EVOLUTION-BLOG-URL:
CALURI:
@@ -161,7 +170,7 @@
@@ -156,12 +165,12 @@
VERSION:3.0
URL:http://john.doe.com
TITLE:Senior Tester
-ORG:Test Inc.;Testing;test#1
+ORG:Test Inc.
ROLE:professional test case
X-EVOLUTION-MANAGER:John Doe Senior
X-EVOLUTION-ASSISTANT:John Doe Junior
NICKNAME:user1
-BDAY:2006-01-08
+BDAY:2007-03-01
X-FOOBAR-EXTENSION;X-FOOBAR-PARAMETER=foobar:has to be stored internally by engine and preserved in testExtensions test; never sent to a peer
X-FOOBAR-EXTENSION;X-FOOBAR-PARAMETER=foobar:has to be stored internally by engine and preserved in testExtensions test\; never sent to a peer
X-TEST;PARAMETER1=nonquoted;PARAMETER2="quoted because of spaces":Content with\nMultiple\nText lines\nand national chars: äöü
X-EVOLUTION-ANNIVERSARY:2006-01-09
@@ -184,7 +193,6 @@

View file

@ -0,0 +1,26 @@
@@ -156,14 +156,14 @@
VERSION:3.0
URL:http://john.doe.com
TITLE:Senior Tester
-ORG:Test Inc.;Testing;test#1
+ORG:Test Inc.;Testing
ROLE:professional test case
X-EVOLUTION-MANAGER:John Doe Senior
X-EVOLUTION-ASSISTANT:John Doe Junior
NICKNAME:user1
BDAY:2006-01-08
X-FOOBAR-EXTENSION;X-FOOBAR-PARAMETER=foobar:has to be stored internally by engine and preserved in testExtensions test\; never sent to a peer
-X-TEST;PARAMETER1=nonquoted;PARAMETER2="quoted because of spaces":Content with\nMultiple\nText lines\nand national chars: äöü
+X-TEST;PARAMETER1=nonquoted;PARAMETER2="quoted because of spaces":Text with\nMultiple\nText lines\nand national chars: äöü
X-EVOLUTION-ANNIVERSARY:2006-01-09
X-EVOLUTION-SPOUSE:Joan Doe
NOTE:This is a test case which uses almost all Evolution fields.
@@ -198,8 +198,6 @@
TEL;TYPE=WORK;TYPE=FAX;X-EVOLUTION-UI-SLOT=4:businessfax 4
TEL;TYPE=HOME;TYPE=FAX;X-EVOLUTION-UI-SLOT=5:homefax 5
TEL;TYPE=PAGER;X-EVOLUTION-UI-SLOT=6:pager 6
-TEL;TYPE=CAR;X-EVOLUTION-UI-SLOT=7:car 7
-TEL;TYPE=PREF;X-EVOLUTION-UI-SLOT=8:primary 8
X-AIM;X-EVOLUTION-UI-SLOT=1:AIM JOHN
X-YAHOO;X-EVOLUTION-UI-SLOT=2:YAHOO JDOE
X-ICQ;X-EVOLUTION-UI-SLOT=3:ICQ JD

View file

@ -150,7 +150,7 @@
X-AIM;X-EVOLUTION-UI-SLOT=1:AIM JOHN
X-YAHOO;X-EVOLUTION-UI-SLOT=2:YAHOO JDOE
X-ICQ;X-EVOLUTION-UI-SLOT=3:ICQ JD
@@ -211,226 +120,3 @@
@@ -210,226 +119,3 @@
X-SKYPE:SKYPE DOE
X-SIP:SIP DOE
END:VCARD

View file

@ -196,6 +196,7 @@ DESCRIPTION:this is an appointment with plenty of fields set\, and
BEGIN:VALARM
X-EVOLUTION-ALARM-UID:20060416T204833Z-4250-727-1-85@gollum
ACTION:DISPLAY
DESCRIPTION:This is an event reminder
TRIGGER;VALUE=DURATION;RELATED=START:-PT1H
END:VALARM
END:VEVENT
@ -238,7 +239,7 @@ SUMMARY:Recurring
DESCRIPTION:recurs each Sonday\, 10 times
CLASS:PUBLIC
RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T090000Z
CREATED:20080407T193241
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193241
END:VEVENT
END:VCALENDAR
@ -255,13 +256,108 @@ TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring: Modified
CLASS:PUBLIC
CREATED:20080407T193241
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
RECURRENCE-ID:20080413T090000Z
DESCRIPTION:second instance modified
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50@gollum
DTSTAMP:20080407T193125Z
DTSTART:20080413T100000Z
DTEND:20080413T103000Z
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring: Modified II
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
RECURRENCE-ID:20080420T090000Z
DESCRIPTION:third instance modified\, different time
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-XX@gollum
DTSTAMP:20080407T193125Z
DTSTART:20080406T090000Z
DTEND:20080406T093000Z
TRANSP:OPAQUE
SEQUENCE:2
SUMMARY:Recurring 2
DESCRIPTION:recurs each Sunday\, 10 times
CLASS:PUBLIC
RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T090000Z
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193241
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-XX@gollum
DTSTAMP:20080407T193125Z
DTSTART:20080413T090000Z
DTEND:20080413T093000Z
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring 2: Modified
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
RECURRENCE-ID:20080413T090000Z
DESCRIPTION:second instance modified\, single detached recurrence
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-YY@gollum
DTSTAMP:20080407T193125Z
DTSTART:20080413T090000Z
DTEND:20080413T093000Z
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring 3: Modified
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
RECURRENCE-ID:20080413T090000Z
DESCRIPTION:second instance modified
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-YY@gollum
DTSTAMP:20080407T193125Z
DTSTART:20080413T100000Z
DTEND:20080413T103000Z
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring 3: Modified II
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
RECURRENCE-ID:20080420T090000Z
DESCRIPTION:third instance modified\, different time
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0

View file

@ -123,7 +123,7 @@
UID:20060416T204647Z-4272-727-1-248@gollum
DTSTAMP:20060416T204647Z
DTSTART:20060406T183000Z
@@ -215,10 +104,6 @@
@@ -216,10 +105,6 @@
SUMMARY:meeting invitation
CLASS:PUBLIC
ORGANIZER;CN=Patrick Ohly:MAILTO:Patrick.Ohly@gmx.de
@ -134,8 +134,8 @@
CREATED:20060416T205003Z
LAST-MODIFIED:20060416T205003Z
END:VEVENT
@@ -261,37 +146,3 @@
DESCRIPTION:second instance modified
@@ -357,37 +242,3 @@
DESCRIPTION:third instance modified\, different time
END:VEVENT
END:VCALENDAR
-

View file

@ -34,7 +34,7 @@
CREATED:20060416T204808Z
LAST-MODIFIED:20060416T204808Z
END:VEVENT
@@ -214,7 +196,6 @@
@@ -215,7 +197,6 @@
CATEGORIES:BUSINESS,MEETING
SUMMARY:meeting invitation
CLASS:PUBLIC

View file

@ -18,16 +18,17 @@
CREATED:20060416T204808Z
LAST-MODIFIED:20060416T204808Z
END:VEVENT
@@ -196,7 +196,7 @@
@@ -196,8 +196,7 @@
BEGIN:VALARM
X-EVOLUTION-ALARM-UID:20060416T204833Z-4250-727-1-85@gollum
ACTION:DISPLAY
-DESCRIPTION:This is an event reminder
-TRIGGER;VALUE=DURATION;RELATED=START:-PT1H
+TRIGGER;VALUE=DATE-TIME:20060406T180000Z
END:VALARM
END:VEVENT
END:VCALENDAR
@@ -266,7 +266,7 @@
@@ -362,7 +361,7 @@
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VTIMEZONE
@ -36,7 +37,7 @@
BEGIN:STANDARD
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
@@ -285,8 +285,8 @@
@@ -381,8 +380,8 @@
BEGIN:VEVENT
UID:20060416T205224Z-4272-727-1-251@gollum
DTSTAMP:20060416T205224Z

View file

@ -198,15 +198,7 @@
TRANSP:TRANSPARENT
SEQUENCE:4
SUMMARY:all fields
@@ -196,6 +304,7 @@
BEGIN:VALARM
X-EVOLUTION-ALARM-UID:20060416T204833Z-4250-727-1-85@gollum
ACTION:DISPLAY
+DESCRIPTION:This is an event reminder
TRIGGER;VALUE=DURATION;RELATED=START:-PT1H
END:VALARM
END:VEVENT
@@ -204,34 +313,29 @@
@@ -205,34 +313,29 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
@ -261,7 +253,7 @@
TRANSP:OPAQUE
SEQUENCE:2
SUMMARY:Recurring
@@ -246,52 +350,36 @@
@@ -247,18 +350,36 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
@ -294,13 +286,206 @@
SEQUENCE:7
SUMMARY:Recurring: Modified
CLASS:PUBLIC
CREATED:20080407T193241
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080413T090000Z
+RECURRENCE-ID;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T110000
DESCRIPTION:second instance modified
END:VEVENT
END:VCALENDAR
@@ -266,18 +387,36 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/softwarestudio.org/Olson_20011030_5/Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50@gollum
DTSTAMP:20080407T193125Z
-DTSTART:20080413T100000Z
-DTEND:20080413T103000Z
+DTSTART;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T120000
+DTEND;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T123000
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring: Modified II
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080420T090000Z
+RECURRENCE-ID;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080420T110000
DESCRIPTION:third instance modified\, different time
END:VEVENT
END:VCALENDAR
@@ -285,11 +424,29 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/softwarestudio.org/Olson_20011030_5/Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-XX@gollum
DTSTAMP:20080407T193125Z
-DTSTART:20080406T090000Z
-DTEND:20080406T093000Z
+DTSTART;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080406T110000
+DTEND;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080406T113000
TRANSP:OPAQUE
SEQUENCE:2
SUMMARY:Recurring 2
@@ -304,18 +461,36 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/softwarestudio.org/Olson_20011030_5/Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-XX@gollum
DTSTAMP:20080407T193125Z
-DTSTART:20080413T090000Z
-DTEND:20080413T093000Z
+DTSTART;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T110000
+DTEND;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T113000
TRANSP:OPAQUE
SEQUENCE:7
-SUMMARY:Recurring 2: Modified
+SUMMARY:Recurring: Modified
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080413T090000Z
+RECURRENCE-ID;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T110000
DESCRIPTION:second instance modified\, single detached recurrence
END:VEVENT
END:VCALENDAR
@@ -323,18 +498,36 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/softwarestudio.org/Olson_20011030_5/Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-YY@gollum
DTSTAMP:20080407T193125Z
-DTSTART:20080413T090000Z
-DTEND:20080413T093000Z
+DTSTART;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T110000
+DTEND;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T113000
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring 3: Modified
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080413T090000Z
+RECURRENCE-ID;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T110000
DESCRIPTION:second instance modified
END:VEVENT
END:VCALENDAR
@@ -342,52 +535,36 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:/softwarestudio.org/Olson_20011030_5/Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-YY@gollum
DTSTAMP:20080407T193125Z
-DTSTART:20080413T100000Z
-DTEND:20080413T103000Z
+DTSTART;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T120000
+DTEND;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080413T123000
TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring 3: Modified II
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080420T090000Z
+RECURRENCE-ID;TZID=/softwarestudio.org/Olson_20011030_5/Europe/Berlin:20080420T110000
DESCRIPTION:third instance modified\, different time
END:VEVENT
END:VCALENDAR
-
-BEGIN:VCALENDAR
-PRODID:-//Ximian//NONSGML Evolution Calendar//EN

View file

@ -129,7 +129,7 @@
^\npercent %\ntilde ~\ntick `\nbacktick `\ndouble quotation - not tested
because Evolution encodes it incorrectly\nsingle quotation '\ncolon :\n
semicolon \;\ncomma \,\n
@@ -211,7 +191,7 @@
@@ -212,7 +192,7 @@
DTEND:20060406T200000Z
TRANSP:OPAQUE
SEQUENCE:2
@ -138,7 +138,7 @@
SUMMARY:meeting invitation
CLASS:PUBLIC
ORGANIZER;CN=Patrick Ohly:MAILTO:Patrick.Ohly@gmx.de
@@ -230,14 +210,14 @@
@@ -231,14 +211,16 @@
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50@gollum
DTSTAMP:20080407T193125Z
@ -153,27 +153,49 @@
CLASS:PUBLIC
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T090000Z
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T110000
CREATED:20080407T193241
+EXDATE;VALUE=DATE:20080413
+EXDATE;VALUE=DATE:20080420
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193241
END:VEVENT
@@ -247,7 +227,7 @@
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
BEGIN:VEVENT
-UID:20080407T193125Z-19554-727-1-50@gollum
+UID:20080407T193125Z-19554-727-1-50@gollum-mod
DTSTAMP:20080407T193125Z
DTSTART:20080413T090000Z
DTEND:20080413T093000Z
@@ -257,7 +237,6 @@
@@ -258,7 +240,7 @@
CLASS:PUBLIC
CREATED:20080407T193241
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080413T090000Z
+RECURRENCE-ID:20080413T110000
DESCRIPTION:second instance modified
END:VEVENT
END:VCALENDAR
@@ -265,28 +244,11 @@
@@ -277,7 +259,7 @@
CLASS:PUBLIC
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
-RECURRENCE-ID:20080420T090000Z
+RECURRENCE-ID:20080420T110000
DESCRIPTION:third instance modified\, different time
END:VEVENT
END:VCALENDAR
@@ -288,14 +270,15 @@
BEGIN:VEVENT
UID:20080407T193125Z-19554-727-1-50-XX@gollum
DTSTAMP:20080407T193125Z
-DTSTART:20080406T090000Z
-DTEND:20080406T093000Z
+DTSTART:20080406T110000
+DTEND:20080406T113000
TRANSP:OPAQUE
SEQUENCE:2
SUMMARY:Recurring 2
DESCRIPTION:recurs each Sunday\, 10 times
CLASS:PUBLIC
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T090000Z
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T110000
+EXDATE;VALUE=DATE:20080413
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193241
END:VEVENT
@@ -361,28 +344,11 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0

View file

@ -33,7 +33,7 @@
UID:20060406T211449Z-4562-727-1-63@gollum
DTSTAMP:20060406T211449Z
LAST-MODIFIED:20060416T203532Z
@@ -90,25 +70,7 @@
@@ -90,59 +70,7 @@
CLASS:PUBLIC
CREATED:20060416T203924Z
LAST-MODIFIED:20060416T203949Z
@ -56,23 +56,67 @@
-RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20070406T180000Z
-CREATED:20060416T204021Z
-LAST-MODIFIED:20060416T204021Z
-END:VEVENT
-END:VCALENDAR
-
-BEGIN:VCALENDAR
-PRODID:-//Ximian//NONSGML Evolution Calendar//EN
-VERSION:2.0
-BEGIN:VEVENT
-UID:20060416T204026Z-4272-727-1-244@gollum
-DTSTAMP:20060416T204026Z
-DTSTART;VALUE=DATE:20060406
-DTEND;VALUE=DATE:20060407
-TRANSP:TRANSPARENT
-SEQUENCE:2
-SUMMARY:all day event
-CLASS:PUBLIC
-CREATED:20060416T204042Z
-LAST-MODIFIED:20060416T204042Z
-END:VEVENT
-END:VCALENDAR
-
-BEGIN:VCALENDAR
-PRODID:-//Ximian//NONSGML Evolution Calendar//EN
-VERSION:2.0
-BEGIN:VEVENT
-UID:20060416T204047Z-4272-727-1-245@gollum
-DTSTAMP:20060416T204047Z
-DTSTART;VALUE=DATE:20060406
-DTEND;VALUE=DATE:20060408
-TRANSP:TRANSPARENT
-SEQUENCE:2
-SUMMARY:two day event
-CLASS:PUBLIC
-CREATED:20060416T204104Z
-LAST-MODIFIED:20060416T204104Z
+RRULE:FREQ=MONTHLY;BYMONTHDAY=6;INTERVAL=1;UNTIL=20060606T173000Z
END:VEVENT
END:VCALENDAR
@@ -193,11 +155,6 @@
@@ -161,8 +89,6 @@
Saturday
CLASS:PUBLIC
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20060412T183000Z
-EXDATE;VALUE=DATE:20060408
-EXDATE;VALUE=DATE:20060407
CREATED:20060416T204808Z
LAST-MODIFIED:20060416T204808Z
END:VEVENT
@@ -193,12 +119,6 @@
^\npercent %\ntilde ~\ntick `\nbacktick `\ndouble quotation - not tested
because Evolution encodes it incorrectly\nsingle quotation '\ncolon :\n
semicolon \;\ncomma \,\n
-BEGIN:VALARM
-X-EVOLUTION-ALARM-UID:20060416T204833Z-4250-727-1-85@gollum
-ACTION:DISPLAY
-DESCRIPTION:This is an event reminder
-TRIGGER;VALUE=DURATION;RELATED=START:-PT1H
-END:VALARM
END:VEVENT
END:VCALENDAR
@@ -265,28 +222,11 @@
@@ -361,28 +281,11 @@
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0

View file

@ -193,7 +193,7 @@
TRANSP:TRANSPARENT
SEQUENCE:4
SUMMARY:all fields
@@ -185,40 +265,43 @@
@@ -185,41 +265,43 @@
CREATED:20060416T204625Z
LAST-MODIFIED:20060416T204833Z
DESCRIPTION:this is an appointment with plenty of fields set\, and
@ -208,6 +208,7 @@
-BEGIN:VALARM
-X-EVOLUTION-ALARM-UID:20060416T204833Z-4250-727-1-85@gollum
-ACTION:DISPLAY
-DESCRIPTION:This is an event reminder
-TRIGGER;VALUE=DURATION;RELATED=START:-PT1H
-END:VALARM
+ special attributes...

View file

@ -324,7 +324,7 @@ SUMMARY:Recurring
DESCRIPTION:recurs each Sonday\, 10 times
CLASS:PUBLIC
RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;UNTIL=20080608T090000Z
CREATED:20080407T193241
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193241
END:VEVENT
END:VCALENDAR
@ -359,7 +359,7 @@ TRANSP:OPAQUE
SEQUENCE:7
SUMMARY:Recurring: Modified
CLASS:PUBLIC
CREATED:20080407T193241
CREATED:20080407T193241Z
LAST-MODIFIED:20080407T193647
RECURRENCE-ID;TZID=Europe/Berlin:20080413T110000
DESCRIPTION:second instance modified

View file

@ -147,10 +147,12 @@ perl \
$LOGFILE
SUBRET=$?
# bad valgrind log result overrides successful completion or being killed by SIGTERM (143) or SIGINT (130)
if ( [ $RET -eq 0 ] || [ $RET -eq 130 ] || [ $RET -eq 143 ] ) && [ $SUBRET -ne 0 ]; then
# bad valgrind log result always overrides normal completion status:
# that way the valgrind errors also show up in the nightly test summary
# in the case where some other test already failed
if [ $SUBRET -ne 0 ]; then
RET=$SUBRET
echo valgrindcheck: "$@": log analysis overrides return code with $SUBRET >&2
echo valgrindcheck: "$@": log analysis overrides return code $RET with $SUBRET >&2
fi
rm $LOGFILE