[folks] Add an EDS backend
- From: Raul Gutierrez Segales <raulgs src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Add an EDS backend
- Date: Tue, 12 Jul 2011 18:52:25 +0000 (UTC)
commit 31f40df6da4766401b576635a8a632db84ee0a01
Author: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
Date: Tue Jul 12 19:00:00 2011 +0100
Add an EDS backend
Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=638281
NEWS | 1 +
backends/Makefile.am | 5 +
backends/eds/Makefile.am | 67 +++
backends/eds/backend.mk | 1 +
backends/eds/eds-backend-factory.vala | 64 ++
backends/eds/eds-backend.vala | 178 ++++++
backends/eds/lib/Makefile.am | 116 ++++
backends/eds/lib/edsf-persona-store.vala | 811 ++++++++++++++++++++++++++
backends/eds/lib/edsf-persona.vala | 806 +++++++++++++++++++++++++
backends/eds/lib/folks-eds-uninstalled.pc.in | 12 +
backends/eds/lib/folks-eds.deps | 6 +
backends/eds/lib/folks-eds.pc.in | 15 +
configure.ac | 37 ++-
tests/Makefile.am | 5 +
tests/eds/Makefile.am | 211 +++++++
tests/eds/add-contacts-stress-test.vala | 200 +++++++
tests/eds/add-persona.vala | 394 +++++++++++++
tests/eds/avatar-details.vala | 154 +++++
tests/eds/data/backend-eds-only.ini | 5 +
tests/eds/email-details.vala | 210 +++++++
tests/eds/im-details.vala | 169 ++++++
tests/eds/individual-retrieval.vala | 143 +++++
tests/eds/link-personas.vala | 408 +++++++++++++
tests/eds/name-details.vala | 220 +++++++
tests/eds/persona-store-tests.vala | 214 +++++++
tests/eds/phone-details.vala | 214 +++++++
tests/eds/postal-address-details.vala | 177 ++++++
tests/eds/remove-persona.vala | 203 +++++++
tests/eds/removing-contacts.vala | 135 +++++
tests/eds/set-avatar.vala | 167 ++++++
tests/eds/set-emails.vala | 154 +++++
tests/eds/set-full-name.vala | 149 +++++
tests/eds/set-im-addresses.vala | 156 +++++
tests/eds/set-notes.vala | 155 +++++
tests/eds/set-phones.vala | 154 +++++
tests/eds/set-postal-addresses.vala | 166 ++++++
tests/eds/set-structured-name.vala | 151 +++++
tests/eds/updating-contacts.vala | 156 +++++
tests/lib/Makefile.am | 5 +
tests/lib/eds/Makefile.am | 56 ++
tests/lib/eds/backend.vala | 291 +++++++++
tests/tools/eds.sh | 25 +
tests/tools/with-session-bus-eds.sh | 44 ++
43 files changed, 7009 insertions(+), 1 deletions(-)
---
diff --git a/NEWS b/NEWS
index acf66b3..075bc18 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ Bugs fixed:
* Bug 653325 â Build system does not complain if trying to build docs without
vala-doc installed
* Bug 653746 â mismatch between hash and equals in Note
+* Bug 638281 â Add an EDS backend
API changes:
* Swf.Persona retains and exposes its libsocialweb Contact
diff --git a/backends/Makefile.am b/backends/Makefile.am
index ba51ad5..0aa6709 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -11,11 +11,16 @@ if ENABLE_TRACKER
SUBDIRS += tracker
endif
+if ENABLE_EDS
+SUBDIRS += eds
+endif
+
DIST_SUBDIRS = \
telepathy \
key-file \
tracker \
libsocialweb \
+ eds \
$(NULL)
-include $(top_srcdir)/git.mk
diff --git a/backends/eds/Makefile.am b/backends/eds/Makefile.am
new file mode 100644
index 0000000..e49f898
--- /dev/null
+++ b/backends/eds/Makefile.am
@@ -0,0 +1,67 @@
+SUBDIRS = lib
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/folks \
+ -I$(top_srcdir)/backends/eds/lib \
+ -include $(CONFIG_HEADER) \
+ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
+ -DBACKEND_NAME=\"$(BACKEND_NAME)\" \
+ -DG_LOG_DOMAIN=\"$(BACKEND_NAME)\" \
+ $(NULL)
+
+VALAFLAGS += \
+ --vapidir=. \
+ --vapidir=$(top_builddir)/backends/eds/lib \
+ --vapidir=$(top_srcdir)/folks \
+ $(addprefix --pkg ,$(folks_backend_eds_deps)) \
+ $(NULL)
+
+backenddir = $(BACKEND_DIR)/eds
+backend_LTLIBRARIES = libfolks-backend-eds.la
+
+libfolks_backend_eds_la_SOURCES = \
+ eds-backend.vala \
+ eds-backend-factory.vala \
+ $(NULL)
+
+folks_backend_eds_deps = \
+ folks \
+ folks-eds \
+ gee-1.0 \
+ gio-2.0 \
+ gobject-2.0 \
+ libebook-1.2 \
+ libedataserver-1.2 \
+ libxml-2.0 \
+ $(NULL)
+
+libfolks_backend_eds_la_CFLAGS = \
+ $(GIO_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(EBOOK_CFLAGS) \
+ $(EDATASERVER_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libfolks_backend_eds_la_LIBADD = \
+ lib/libfolks-eds.la \
+ $(top_builddir)/folks/libfolks.la \
+ $(GIO_LIBS) \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(EBOOK_LIBS) \
+ $(EDATASERVER_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libfolks_backend_eds_la_LDFLAGS = -shared -fPIC -module -avoid-version
+
+GITIGNOREFILES = \
+ folks-backend-eds.vapi \
+ $(libfolks_backend_eds_la_SOURCES:.vala=.c) \
+ libfolks_backend_eds_la_vala.stamp \
+ $(NULL)
+
+-include backend.mk
+-include $(top_srcdir)/git.mk
diff --git a/backends/eds/backend.mk b/backends/eds/backend.mk
new file mode 100644
index 0000000..cd1f182
--- /dev/null
+++ b/backends/eds/backend.mk
@@ -0,0 +1 @@
+BACKEND_NAME = eds
diff --git a/backends/eds/eds-backend-factory.vala b/backends/eds/eds-backend-factory.vala
new file mode 100644
index 0000000..d532aed
--- /dev/null
+++ b/backends/eds/eds-backend-factory.vala
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ * Travis Reitter <travis reitter collabora co uk>
+ * Marco Barisione <marco barisione collabora co uk>
+ * Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ * This file was originally part of Rygel.
+ */
+
+using Folks;
+using Folks.Backends.Eds;
+
+private BackendFactory _backend_factory = null;
+
+/**
+ * The eds backend module entry point.
+ *
+ * @since 0.5.UNRELEASED
+ */
+public void module_init (BackendStore backend_store)
+{
+ _backend_factory = new BackendFactory (backend_store);
+}
+
+/**
+ * The eds backend module exit point.
+ *
+ * @since 0.5.UNRELEASED
+ */
+public void module_finalize (BackendStore backend_store)
+{
+ _backend_factory = null;
+}
+
+/**
+ * A backend factory to create a single { link Backend}.
+ */
+public class Folks.Backends.Eds.BackendFactory : Object
+{
+ /**
+ * { inheritDoc}
+ */
+ public BackendFactory (BackendStore backend_store)
+ {
+ backend_store.add_backend (new Backend ());
+ }
+}
diff --git a/backends/eds/eds-backend.vala b/backends/eds/eds-backend.vala
new file mode 100644
index 0000000..2eaf375
--- /dev/null
+++ b/backends/eds/eds-backend.vala
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Travis Reitter <travis reitter collabora co uk>
+ * Marco Barisione <marco barisione collabora co uk>
+ * Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ */
+
+using E;
+using Gee;
+using GLib;
+using Folks;
+using Folks.Backends.Eds;
+
+extern const string BACKEND_NAME;
+
+/**
+ * A backend which connects to EDS and creates a { link PersonaStore}
+ * for each service.
+ */
+public class Folks.Backends.Eds.Backend : Folks.Backend
+{
+ public static const string use_addressbooks =
+ "FOLKS_BACKEND_EDS_USE_ADDRESSBOOKS";
+ private bool _is_prepared = false;
+ private HashMap<string, PersonaStore> _persona_stores;
+ private Map<string, PersonaStore> _persona_stores_ro;
+ private E.SourceList _ab_sources;
+
+ /**
+ * { inheritDoc}
+ */
+ public override string name { get { return BACKEND_NAME; } }
+
+ /**
+ * { inheritDoc}
+ */
+ public override Map<string, PersonaStore> persona_stores
+ {
+ get { return this._persona_stores_ro; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public Backend ()
+ {
+ this._persona_stores = new HashMap<string, PersonaStore> ();
+ this._persona_stores_ro = this._persona_stores.read_only_view;
+ }
+
+ /**
+ * Whether this Backend has been prepared.
+ *
+ * See { link Folks.Backend.is_prepared}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override async void prepare () throws GLib.Error
+ {
+ lock (this._is_prepared)
+ {
+ if (!this._is_prepared)
+ {
+ string[] use_addressbooks = this._get_addressbooks_from_env ();
+ this._create_avatars_cache_dir ();
+
+ E.BookClient.get_sources (out this._ab_sources);
+ unowned GLib.SList<weak E.SourceGroup> groups =
+ this._ab_sources.peek_groups ();
+
+ foreach (var g in groups)
+ {
+ foreach (E.Source s in g.peek_sources ())
+ {
+ if (use_addressbooks.length > 0)
+ {
+ if (s.peek_name () in use_addressbooks)
+ {
+ this._add_addressbook (s);
+ }
+ }
+ else
+ {
+ this._add_addressbook (s);
+ }
+ }
+ }
+
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+ }
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override async void unprepare () throws GLib.Error
+ {
+ foreach (var persona_store in this._persona_stores.values)
+ {
+ this.persona_store_removed (persona_store);
+ }
+
+ this._persona_stores.clear ();
+ this.notify_property ("persona-stores");
+
+ this._is_prepared = false;
+ this.notify_property ("is-prepared");
+ }
+
+ private void _create_avatars_cache_dir ()
+ {
+ string avatars_dir = GLib.Path.build_filename
+ (GLib.Environment.get_user_cache_dir (), "folks", "avatars");
+ DirUtils.create_with_parents (avatars_dir, 0700);
+ }
+
+ /**
+ * Add a new addressbook connected to a Persona Store.
+ */
+ private void _add_addressbook (E.Source s)
+ {
+ string relative_uri = s.peek_relative_uri ();
+
+ if (this._persona_stores.has_key (relative_uri))
+ return;
+
+ var store = new Edsf.PersonaStore (s);
+ this._persona_stores.set (store.id, store);
+ store.removed.connect (this._store_removed_cb);
+ this.notify_property ("persona-stores");
+ this.persona_store_added (store);
+ }
+
+ private void _store_removed_cb (Folks.PersonaStore store)
+ {
+ store.removed.disconnect (this._store_removed_cb);
+ this.persona_store_removed (store);
+ this.persona_stores.unset (store.id);
+ }
+
+ private string[] _get_addressbooks_from_env ()
+ {
+ string[] addressbooks = {};
+ string ab_list = Environment.get_variable (this.use_addressbooks);
+
+ if (ab_list != null && ab_list != "")
+ {
+ addressbooks = ab_list.split (":");
+ }
+
+ return addressbooks;
+ }
+}
diff --git a/backends/eds/lib/Makefile.am b/backends/eds/lib/Makefile.am
new file mode 100644
index 0000000..4a7242e
--- /dev/null
+++ b/backends/eds/lib/Makefile.am
@@ -0,0 +1,116 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/folks \
+ -include $(CONFIG_HEADER) \
+ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
+ -DBACKEND_NAME=\"$(BACKEND_NAME)\" \
+ -DG_LOG_DOMAIN=\"$(BACKEND_NAME)\" \
+ $(NULL)
+
+VAPIGENFLAGS += \
+ --vapidir=. \
+ --vapidir=$(top_srcdir)/folks \
+ $(NULL)
+
+folks_edsdir = $(libdir)
+folks_eds_LTLIBRARIES = libfolks-eds.la
+
+CLEANFILES =
+
+##################################################################
+# Support library
+##################################################################
+
+pkgconfig_in = folks-eds.pc.in
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = $(pkgconfig_in:.in=)
+
+libfolks_eds_la_vala.stamp:
+
+folks_eds_valasources = \
+ edsf-persona.vala \
+ edsf-persona-store.vala \
+ $(NULL)
+
+libfolks_eds_la_SOURCES = \
+ $(folks_eds_valasources) \
+ $(NULL)
+
+VALAFLAGS = \
+ --vapidir=. \
+ --vapidir=$(top_srcdir)/folks \
+ $(addprefix --pkg ,$(folks_backend_eds_deps)) \
+ --vapi folks-eds.vapi \
+ -H folks-eds.h \
+ $(NULL)
+
+folks_backend_eds_deps = \
+ folks \
+ gee-1.0 \
+ gio-2.0 \
+ gobject-2.0 \
+ libebook-1.2 \
+ libedataserver-1.2 \
+ libxml-2.0 \
+ $(NULL)
+
+libfolks_eds_la_CFLAGS = \
+ $(GIO_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(EBOOK_CFLAGS) \
+ $(EDATASERVER_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libfolks_eds_la_LIBADD = \
+ $(top_builddir)/folks/libfolks.la \
+ $(EBOOK_LIBS) \
+ $(EDATASERVER_LIBS) \
+ $(GIO_LIBS) \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+# The quoting here is unnecessary but harmless, and has the useful side-effect
+# that vim quickfix mode (:make) doesn't interpret the libtool --mode=link
+# command as an error message in a bizarrely named file
+libfolks_eds_la_LDFLAGS = \
+ -version-info "$(LT_CURRENT)":"$(LT_REVISION)":"$(LT_AGE)" \
+ -export-symbols-regex "^(EDSF|edsf)_.*|" \
+ $(NULL)
+
+folks_eds_includedir = $(includedir)/folks
+folks_eds_include_HEADERS = \
+ folks-eds.h \
+ $(NULL)
+
+vapidir = $(datadir)/vala/vapi
+dist_vapi_DATA = \
+ folks-eds.vapi \
+ folks-eds.deps \
+ $(NULL)
+
+##################################################################
+# General
+##################################################################
+
+CLEANFILES += \
+ $(pkgconfig_in:.in=) \
+ folks-eds-uninstalled.pc \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ $(folks_eds_valasources:.vala=.c) \
+ libfolks_eds_la_vala.stamp \
+ folks-eds.h \
+ folks-eds.vapi \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(pkgconfig_in) \
+ $(MAINTAINERCLEANFILES) \
+ $(NULL)
+
+-include ../backend.mk
+-include $(top_srcdir)/git.mk
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
new file mode 100644
index 0000000..e4ecdc5
--- /dev/null
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -0,0 +1,811 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Travis Reitter <travis reitter collabora co uk>
+ * Philip Withnall <philip withnall collabora co uk>
+ * Marco Barisione <marco barisione collabora co uk>
+ * Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ */
+
+using E;
+using Folks;
+using Gee;
+using GLib;
+
+extern const string BACKEND_NAME;
+
+/**
+ * A persona store.
+ * It will create { link Persona}s for each contacts on the main addressbook.
+ */
+public class Edsf.PersonaStore : Folks.PersonaStore
+{
+ private HashMap<string, Persona> _personas;
+ private Map<string, Persona> _personas_ro;
+ private bool _is_prepared = false;
+ private E.BookClient _addressbook;
+ private E.BookClientView _ebookview;
+ private string _addressbook_uri = null;
+ private E.Source _source;
+ private string _query_str;
+
+ /**
+ * The type of persona store this is.
+ *
+ * See { link Folks.PersonaStore.type_id}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override string type_id { get { return BACKEND_NAME; } }
+
+ /**
+ * Whether this PersonaStore can add { link Folks.Persona}s.
+ *
+ * See { link Folks.PersonaStore.can_add_personas}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override MaybeBool can_add_personas
+ {
+ get { return MaybeBool.TRUE; }
+ }
+
+ /**
+ * Whether this PersonaStore can set the alias of { link Folks.Persona}s.
+ *
+ * See { link Folks.PersonaStore.can_alias_personas}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override MaybeBool can_alias_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can set the groups of { link Folks.Persona}s.
+ *
+ * See { link Folks.PersonaStore.can_group_personas}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override MaybeBool can_group_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can remove { link Folks.Persona}s.
+ *
+ * See { link Folks.PersonaStore.can_remove_personas}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override MaybeBool can_remove_personas
+ {
+ get { return MaybeBool.TRUE; }
+ }
+
+ /**
+ * Whether this PersonaStore has been prepared.
+ *
+ * See { link Folks.PersonaStore.is_prepared}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * The { link Persona}s exposed by this PersonaStore.
+ *
+ * See { link Folks.PersonaStore.personas}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override Map<string, Persona> personas
+ {
+ get { return this._personas_ro; }
+ }
+
+ /**
+ * Create a new PersonaStore.
+ *
+ * Create a new persona store to store the { link Persona}s for the contacts
+ *
+ * @param s the e-d-s source being represented by the persona store
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public PersonaStore (E.Source s)
+ {
+ string uri = s.peek_relative_uri ();
+ Object (id: uri, display_name: uri);
+ this._source = s;
+ this._addressbook_uri = uri;
+ this._personas = new HashMap<string, Persona> ();
+ this._personas_ro = this._personas.read_only_view;
+ this._query_str = "(contains \"x-evolution-any-field\" \"\")";
+ }
+
+ ~PersonaStore ()
+ {
+ try
+ {
+ if (this._ebookview != null)
+ {
+ this._ebookview.objects_added.disconnect (
+ this._contacts_added_cb);
+ this._ebookview.objects_removed.disconnect (
+ this._contacts_removed_cb);
+ this._ebookview.objects_modified.disconnect (
+ this._contacts_changed_cb);
+ this._ebookview.stop ();
+
+ this._ebookview = null;
+ }
+
+ this._addressbook = null;
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("~PersonaStore: %s\n", e.message);
+ }
+ }
+
+ /**
+ * Add a new { link Persona} to the PersonaStore.
+ *
+ * Accepted keys for `details` are:
+ * - PersonaStore.detail_key (PersonaDetail.AVATAR)
+ * - PersonaStore.detail_key (PersonaDetail.EMAIL_ADDRESSES)
+ * - PersonaStore.detail_key (PersonaDetail.FULL_NAME)
+ * - PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES)
+ * - PersonaStore.detail_key (PersonaDetail.PHONE_NUMBERS)
+ * - PersonaStore.detail_key (PersonaDetail.POSTAL_ADDRESSES)
+ * - PersonaStore.detail_key (PersonaDetail.STRUCTURED_NAME)
+ * - PersonaStore.detail_key (PersonaDetail.LOCAL_IDS)
+ * - PersonaDetail.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES)
+ * - PersonaStore.detail_key (PersonaDetail.NOTES)
+ *
+ * See { link Folks.PersonaStore.add_persona_from_details}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override async Folks.Persona? add_persona_from_details (
+ HashTable<string, Value?> details) throws Folks.PersonaStoreError
+ {
+ E.Contact contact = new E.Contact ();
+
+ foreach (var k in details.get_keys ())
+ {
+ Value? v = details.lookup (k);
+ if (k == Folks.PersonaStore.detail_key (
+ PersonaDetail.FULL_NAME))
+ {
+ contact.set (E.Contact.field_id ("full_name"),
+ v.get_string ());
+ }
+ else if (k == Folks.PersonaStore.detail_key (
+ PersonaDetail.EMAIL_ADDRESSES))
+ {
+ Set<FieldDetails> email_addresses =
+ (Set<FieldDetails>) v.get_object ();
+ yield this._set_contact_attributes (contact, email_addresses,
+ "EMAIL", E.ContactField.EMAIL);
+ }
+ else if (k == Folks.PersonaStore.detail_key (PersonaDetail.AVATAR))
+ {
+ var avatar = (File) v.get_object ();
+ yield this._set_contact_avatar (contact, avatar);
+ }
+ else if (k == Folks.PersonaStore.detail_key (
+ PersonaDetail.IM_ADDRESSES))
+ {
+ var im_addresses = (MultiMap<string, string>) v.get_object ();
+ yield this._set_contact_im_addrs (contact, im_addresses);
+ }
+ else if (k == Folks.PersonaStore.detail_key (
+ PersonaDetail.PHONE_NUMBERS))
+ {
+ Set<FieldDetails> phone_numbers =
+ (Set<FieldDetails>) v.get_object ();
+ yield this._set_contact_attributes (contact,
+ phone_numbers, "TEL",
+ E.ContactField.TEL);
+ }
+ else if (k == Folks.PersonaStore.detail_key (
+ PersonaDetail.POSTAL_ADDRESSES))
+ {
+ Set<PostalAddress> postal_addresses =
+ (Set<PostalAddress>) v.get_object ();
+ yield this._set_contact_postal_addresses (contact,
+ postal_addresses);
+ }
+ else if (k == Folks.PersonaStore.detail_key (
+ PersonaDetail.STRUCTURED_NAME))
+ {
+ StructuredName sname = (StructuredName) v.get_object ();
+ yield this._set_contact_name (contact, sname);
+ }
+ else if (k == Folks.PersonaStore.detail_key (PersonaDetail.LOCAL_IDS))
+ {
+ Set<string> local_ids = (Set<string>) v.get_object ();
+ yield this._set_contact_local_ids (contact, local_ids);
+ }
+ else if (k == Folks.PersonaStore.detail_key
+ (PersonaDetail.WEB_SERVICE_ADDRESSES))
+ {
+ HashMultiMap<string, string> web_service_addresses =
+ (HashMultiMap<string, string>) v.get_object ();
+ yield this._set_contact_web_service_addresses (contact,
+ web_service_addresses);
+ }
+ else if (k == Folks.PersonaStore.detail_key (PersonaDetail.NOTES))
+ {
+ var notes = (Gee.HashSet<Note>) v.get_object ();
+ yield this._set_contact_notes (contact, notes);
+ }
+ }
+
+ Edsf.Persona? persona = null;
+
+ try
+ {
+ string added_uid;
+ var result = yield this._addressbook.add_contact (contact,
+ out added_uid);
+
+ if (result)
+ {
+ debug ("Created contact with uid: %s\n", added_uid);
+ lock (this._personas)
+ {
+ var iid = Edsf.Persona.build_iid (this.id, added_uid);
+ persona = this._personas.get (iid);
+ if (persona == null)
+ {
+ contact.set (E.Contact.field_id ("id"), added_uid);
+ persona = new Persona (this, contact);
+ this._personas.set (persona.iid, persona);
+ var added_personas = new HashSet<Persona> ();
+ added_personas.add (persona);
+ this._emit_personas_changed (added_personas, null);
+ }
+ }
+ }
+ else
+ {
+ throw new PersonaStoreError.CREATE_FAILED
+ ("BookClient.add_contact () failed.");
+ }
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("add_persona_from_details: %s\n",
+ e.message);
+ }
+
+ return persona;
+ }
+
+ /**
+ * Remove a { link Persona} from the PersonaStore.
+ *
+ * @param persona the that should be removed
+ *
+ * See { link Folks.PersonaStore.remove_persona}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override async void remove_persona (Folks.Persona persona)
+ throws Folks.PersonaStoreError
+ {
+ try
+ {
+ yield this._addressbook.remove_contact (
+ ((Edsf.Persona) persona).contact);
+ }
+ catch (GLib.Error e)
+ {
+ /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=652425 */
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Can't remove contact: %s\n", e.message);
+ }
+ }
+
+ /**
+ * Prepare the PersonaStore for use.
+ *
+ * TODO: we should throw different errors dependening on what went wrong
+ * when we were trying to setup the PersonaStore.
+ *
+ * See { link Folks.PersonaStore.prepare}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override async void prepare ()
+ {
+ /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=652637 */
+ lock (this._is_prepared)
+ {
+ if (this._is_prepared)
+ {
+ return;
+ }
+
+ /* FIXME: we need better error codes */
+
+ try
+ {
+ this._addressbook = new E.BookClient (this._source);
+ }
+ catch (GLib.Error e1)
+ {
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Couldn't get BookClient: %s\n", e1.message);
+ }
+
+ try
+ {
+ yield this._addressbook.open (true, null);
+ }
+ catch (GLib.Error e2)
+ {
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Couldn't open addressbook: %s\n", e2.message);
+ }
+
+ if (this._addressbook.is_opened () == false)
+ {
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Couldn't open addressbook\n");
+ }
+
+ bool got_view = false;
+ try
+ {
+ got_view = yield this._addressbook.get_view (this._query_str,
+ out this._ebookview);
+ }
+ catch (GLib.Error e3)
+ {
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Couldn't get book view: %s\n", e3.message);
+ }
+
+ if (got_view == false)
+ {
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Couldn't get book view\n");
+ }
+
+ this._ebookview.objects_added.connect (this._contacts_added_cb);
+ this._ebookview.objects_removed.connect (this._contacts_removed_cb);
+ this._ebookview.objects_modified.connect (this._contacts_changed_cb);
+
+ try
+ {
+ this._ebookview.start ();
+ }
+ catch (GLib.Error e4)
+ {
+ throw new PersonaStoreError.INVALID_ARGUMENT (
+ "Couldn't start bookview: %s\n", e4.message);
+ }
+
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+ }
+ }
+
+ internal async void _set_avatar (Edsf.Persona persona, File avatar)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_avatar (contact, avatar);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Can't update avatar: %s\n", e.message);
+ }
+ }
+
+ internal async void _set_web_service_addresses (Edsf.Persona persona,
+ MultiMap<string, string> web_service_addresses)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_web_service_addresses (contact,
+ web_service_addresses);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Can't set local IDS: %s\n", e.message);
+ }
+ }
+
+ private async void _set_contact_web_service_addresses (E.Contact contact,
+ MultiMap<string, string> web_service_addresses)
+ {
+ var attr = contact.get_attribute ("X-FOLKS-WEB-SERVICES-IDS");
+ if (attr != null)
+ {
+ contact.remove_attribute (attr);
+ }
+
+ var attr_n = new VCardAttribute (null, "X-FOLKS-WEB-SERVICES-IDS");
+ foreach (var service in web_service_addresses.get_keys ())
+ {
+ var param = new E.VCardAttributeParam (service);
+ foreach (var id in web_service_addresses.get (service))
+ {
+ param.add_value (id);
+ }
+ attr_n.add_param (param);
+ }
+ contact.add_attribute (attr_n);
+ }
+
+ internal async void _set_local_ids (Edsf.Persona persona,
+ Set<string> local_ids)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_local_ids (contact, local_ids);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Can't set local IDS: %s\n", e.message);
+ }
+ }
+
+ private async void _set_contact_local_ids (E.Contact contact,
+ Set<string> local_ids)
+ {
+ var attr = contact.get_attribute ("X-FOLKS-CONTACTS-IDS");
+ if (attr != null)
+ {
+ contact.remove_attribute (attr);
+ }
+
+ attr = new VCardAttribute (null, "X-FOLKS-CONTACTS-IDS");
+ foreach (var local_id in local_ids)
+ {
+ attr.add_value (local_id);
+ }
+
+ contact.add_attribute (attr);
+ }
+
+ private async void _set_contact_avatar (E.Contact contact,
+ File avatar)
+ {
+ try
+ {
+ uint8[] photo_content;
+ yield avatar.load_contents_async (null, out photo_content);
+
+ var cp = new ContactPhoto ();
+ cp.type = ContactPhotoType.INLINED;
+ cp.set_inlined (photo_content);
+
+ contact.set (E.Contact.field_id ("photo"), cp);
+ }
+ catch (GLib.Error e_avatar)
+ {
+ GLib.warning ("Can't load avatar %s: %s\n\n", avatar.get_path (),
+ e_avatar.message);
+ }
+ }
+
+ internal async void _set_emails (Edsf.Persona persona,
+ Set<FieldDetails> emails)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_attributes (contact, emails, "EMAIL",
+ E.ContactField.EMAIL);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update email-addresses: %s\n",
+ error.message);
+ }
+ }
+
+ internal async void _set_phones (Edsf.Persona persona,
+ Set<FieldDetails> phones)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_attributes (contact, phones, "TEL",
+ E.ContactField.TEL);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update phones: %s\n", error.message);
+ }
+ }
+
+ internal async void _set_postal_addresses (Edsf.Persona persona,
+ Set<PostalAddress> addresses)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_postal_addresses (contact,
+ addresses);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update postal addresses: %s\n",
+ error.message);
+ }
+ }
+
+ private async void _set_contact_postal_addresses (E.Contact contact,
+ Set<PostalAddress> addresses)
+ {
+ foreach (var pa in addresses)
+ {
+ var address = new E.ContactAddress ();
+
+ address.po = pa.po_box;
+ address.ext = pa.extension;
+ address.street = pa.street;
+ address.locality = pa.locality;
+ address.region = pa.region;
+ address.code = pa.postal_code;
+ address.country = pa.country;
+ address.address_format = pa.address_format;
+
+ if (pa.types.size > 0)
+ {
+ var pa_type = pa.types.to_array ()[0];
+ contact.set (E.Contact.field_id (pa_type), address);
+ }
+ else
+ {
+ contact.set (E.ContactField.ADDRESS_OTHER, address);
+ }
+ }
+ }
+
+ private async void _set_contact_attributes (E.Contact contact,
+ Set<FieldDetails> new_attributes,
+ string attrib_name, E.ContactField field_id)
+ {
+ var attributes = new GLib.List <E.VCardAttribute>();
+
+ foreach (var e in new_attributes)
+ {
+ var attr = new E.VCardAttribute (null, attrib_name);
+ attr.add_value (e.value);
+ foreach (var param_name in e.parameters.get_keys ())
+ {
+ var param = new E.VCardAttributeParam (param_name.up ());
+ foreach (var param_val in e.parameters.get (param_name))
+ {
+ param.add_value (param_val);
+ }
+ attr.add_param (param);
+ }
+ attributes.prepend (attr);
+ }
+
+ contact.set_attributes (field_id, attributes);
+ }
+
+ internal async void _set_full_name (Edsf.Persona persona,
+ string full_name)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ contact.set (E.Contact.field_id ("full_name"), full_name);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update full name: %s\n", error.message);
+ }
+ }
+
+ internal async void _set_notes (Edsf.Persona persona,
+ Set<Note> notes)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_notes (contact, notes);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update notes: %s\n", error.message);
+ }
+ }
+
+ private async void _set_contact_notes (E.Contact contact, Set<Note> notes)
+ {
+ string note_str = "";
+ foreach (var note in notes)
+ {
+ if (note_str != "")
+ {
+ note_str += ". ";
+ }
+ note_str += note.content;
+ }
+
+ contact.set (E.Contact.field_id ("note"), note_str);
+ }
+
+ internal async void _set_structured_name (Edsf.Persona persona,
+ StructuredName sname)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_name (contact, sname);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update structured name: %s\n", error.message);
+ }
+ }
+
+ private async void _set_contact_name (E.Contact contact,
+ StructuredName sname)
+ {
+ E.ContactName contact_name = new E.ContactName ();
+
+ contact_name.family = sname.family_name;
+ contact_name.given = sname.given_name;
+ contact_name.additional = sname.additional_names;
+ contact_name.suffixes = sname.suffixes;
+ contact_name.prefixes = sname.prefixes;
+
+ contact.set (E.Contact.field_id ("name"), contact_name);
+ }
+
+ internal async void _set_im_addrs (Edsf.Persona persona,
+ MultiMap<string, string> im_addrs)
+ {
+ try
+ {
+ E.Contact contact = ((Edsf.Persona) persona).contact;
+ yield this._set_contact_im_addrs (contact, im_addrs);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error error)
+ {
+ GLib.warning ("Can't update IM addresses: %s\n", error.message);
+ }
+ }
+
+ /* TODO: this could be smarter & more efficient. */
+ private async void _set_contact_im_addrs (E.Contact contact,
+ MultiMap<string, string> im_addrs)
+ {
+ var im_eds_map = Edsf.Persona._get_im_eds_map ();
+
+ /* First let's remove everything */
+ foreach (var field_id in im_eds_map.get_values ())
+ {
+ var attrs = contact.get_attributes (field_id);
+ foreach (var attr in attrs)
+ {
+ contact.remove_attribute (attr);
+ }
+ }
+
+ foreach (var proto in im_addrs.get_keys ())
+ {
+ var attributes = new GLib.List <E.VCardAttribute>();
+ var attrib_name = ("X-" + proto).up ();
+ bool added = false;
+
+ foreach (var im in im_addrs.get (proto))
+ {
+ var attr_n = new E.VCardAttribute (null, attrib_name);
+ attr_n.add_value (im);
+ attributes.prepend (attr_n);
+ added = true;
+ }
+
+ if (added)
+ {
+ var field_id_t = im_eds_map.lookup (proto);
+ contact.set_attributes (field_id_t, attributes);
+ }
+ }
+ }
+
+ private void _contacts_added_cb (GLib.List<E.Contact> contacts)
+ {
+ var added_personas = new HashSet<Persona> ();
+ lock (this._personas)
+ {
+ foreach (E.Contact c in contacts)
+ {
+ var iid = Edsf.Persona.build_iid_from_contact (this.id, c);
+ var persona = this._personas.get (iid);
+ if (persona == null)
+ {
+ persona = new Persona (this, c);
+ this._personas.set (persona.iid, persona);
+ added_personas.add (persona);
+ }
+ }
+ }
+
+ if (added_personas.size > 0)
+ {
+ this._emit_personas_changed (added_personas, null);
+ }
+ }
+
+ private void _contacts_changed_cb (GLib.List<E.Contact> contacts)
+ {
+ foreach (E.Contact c in contacts)
+ {
+ var iid = Edsf.Persona.build_iid_from_contact (this.id, c);
+ var persona = this._personas.get (iid);
+ if (persona != null)
+ {
+ persona._update (c);
+ }
+ }
+ }
+
+ private void _contacts_removed_cb (GLib.List<string> contacts_ids)
+ {
+ var removed_personas = new HashSet<Persona> ();
+
+ foreach (string contact_id in contacts_ids)
+ {
+ var iid = Edsf.Persona.build_iid (this.id, contact_id);
+ var persona = _personas.get (iid);
+ if (persona != null)
+ {
+ removed_personas.add (persona);
+ this._personas.unset (persona.iid);
+ }
+ }
+
+ if (removed_personas.size > 0)
+ {
+ this._emit_personas_changed (null, removed_personas);
+ }
+ }
+}
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
new file mode 100644
index 0000000..8cf04f2
--- /dev/null
+++ b/backends/eds/lib/edsf-persona.vala
@@ -0,0 +1,806 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Travis Reitter <travis reitter collabora co uk>
+ * Marco Barisione <marco barisione collabora co uk>
+ * Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ */
+
+using E;
+using Folks;
+using Gee;
+using GLib;
+using Xml;
+
+/**
+ * A persona subclass which represents a single EDS contact.
+ */
+public class Edsf.Persona : Folks.Persona,
+ AvatarDetails,
+ EmailDetails,
+ GenderDetails,
+ ImDetails,
+ LocalIdDetails,
+ NameDetails,
+ NoteDetails,
+ PhoneDetails,
+ UrlDetails,
+ PostalAddressDetails,
+ WebServiceDetails
+{
+ /* The following 4 definitions are used by the tests */
+ public static const string[] phone_fields = {
+ "assistant_phone", "business_phone", "business_phone_2", "callback_phone",
+ "car_phone", "company_phone", "home_phone", "home_phone_2", "isdn_phone",
+ "mobile_phone", "other_phone", "primary_phone"
+ };
+ public static const string[] address_fields = {
+ "address_home", "address_other", "address_work"
+ };
+ public static const string[] email_fields = {
+ "email_1", "email_2", "email_3", "email_4"
+ };
+ public static const string[] url_properties = {
+ "blog_url", "fburl", "homepage_url", "video_url"
+ };
+ private const string[] _linkable_properties = { "im-addresses",
+ "local-ids",
+ "web-service-addresses" };
+ private HashSet<FieldDetails> _phone_numbers;
+ private Set<FieldDetails> _phone_numbers_ro;
+ private HashSet<FieldDetails> _email_addresses;
+ private Set<FieldDetails> _email_addresses_ro;
+ private HashSet<Note> _notes;
+ private Set<Note> _notes_ro;
+ private static HashTable<string, E.ContactField> _im_eds_map = null;
+
+ private HashSet<PostalAddress> _postal_addresses;
+ private Set<PostalAddress> _postal_addresses_ro;
+
+ private HashSet<string> _local_ids;
+ private Set<string> _local_ids_ro;
+
+ private HashMultiMap<string, string> _web_service_addresses;
+
+ /**
+ * The e-d-s contact represented by this Persona
+ */
+ public E.Contact contact
+ {
+ get;
+ private set;
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public MultiMap<string, string> web_service_addresses
+ {
+ get { return this._web_service_addresses; }
+ set
+ {
+ var store = (Edsf.PersonaStore) this.store;
+ store._set_web_service_addresses (this, value);
+ }
+ }
+
+ /**
+ * IDs used to link { link Edsf.Persona}s.
+ */
+ public Set<string> local_ids
+ {
+ get
+ {
+ if (this._local_ids.contains (this.contact_id) == false)
+ {
+ this._local_ids.add (this.contact_id);
+ }
+ return this._local_ids_ro;
+ }
+ set
+ {
+ ((Edsf.PersonaStore) this.store)._set_local_ids (this, value);
+ }
+ }
+
+ /**
+ * The postal addresses of the contact.
+ *
+ * A list of postal addresses associated to the contact.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Set<PostalAddress> postal_addresses
+ {
+ get { return this._postal_addresses_ro; }
+ private set
+ {
+ ((Edsf.PersonaStore) this.store)._set_postal_addresses (this, value);
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Set<FieldDetails> phone_numbers
+ {
+ get { return this._phone_numbers_ro; }
+ private set
+ {
+ ((Edsf.PersonaStore) this.store)._set_phones (this, value);
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Set<FieldDetails> email_addresses
+ {
+ get { return this._email_addresses_ro; }
+ private set
+ {
+ ((Edsf.PersonaStore) this.store)._set_emails (this, value);
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Set<Note> notes
+ {
+ get { return this._notes_ro; }
+ private set
+ {
+ ((Edsf.PersonaStore) this.store)._set_notes (this, value);
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override string[] linkable_properties
+ {
+ get { return this._linkable_properties; }
+ }
+
+ private File _avatar;
+ /**
+ * An avatar for the Persona.
+ *
+ * See { link Folks.Avatar.avatar}.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public File avatar
+ {
+ get { return this._avatar; }
+ set
+ {
+ if (this._avatar == null ||
+ !this._avatar.equal (value))
+ {
+ ((Edsf.PersonaStore) this.store)._set_avatar (this, value);
+ }
+ }
+ }
+
+ private StructuredName _structured_name;
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public StructuredName structured_name
+ {
+ get { return this._structured_name; }
+ set
+ {
+ ((Edsf.PersonaStore) this.store)._set_structured_name (this, value);
+ }
+ }
+
+ /**
+ * The e-d-s contact uid
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public string contact_id { get; private set; }
+
+ private string _full_name;
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public string full_name
+ {
+ get { return this._full_name; }
+ set
+ {
+ ((Edsf.PersonaStore) this.store)._set_full_name (this, value);
+ }
+ }
+
+ private string _nickname;
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public string nickname { get { return this._nickname; } }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Gender gender { get; private set; }
+
+ private HashSet<FieldDetails> _urls;
+ private Set<FieldDetails> _urls_ro;
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Set<FieldDetails> urls
+ {
+ get { return this._urls_ro; }
+ set
+ {
+ GLib.warning ("Urls setting not supported yet\n");
+ }
+ }
+
+ private HashMultiMap<string, string> _im_addresses =
+ new HashMultiMap<string, string> ();
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public MultiMap<string, string> im_addresses
+ {
+ get { return this._im_addresses; }
+ set
+ {
+ ((Edsf.PersonaStore) this.store)._set_im_addrs (this, value);
+ }
+ }
+
+ /**
+ * Build a IID.
+ *
+ * @param store_id the { link PersonaStore.id}
+ * @param contact the Contact
+ * @return a valid IID
+ *
+ * @since 0.5.UNRELEASED
+ */
+ internal static string build_iid_from_contact (string store_id,
+ E.Contact contact)
+ {
+ var contact_id =
+ (string) Edsf.Persona._get_property_from_contact (contact, "id");
+ return Edsf.Persona.build_iid (store_id, contact_id);
+ }
+
+ /**
+ * Build a IID.
+ *
+ * @param store_id the { link PersonaStore.id}
+ * @param contact_id the id belonging to the Contact
+ * @return a valid IID
+ *
+ * @since 0.5.UNRELEASED
+ */
+ internal static string build_iid (string store_id, string contact_id)
+ {
+ return "%s:%s".printf (store_id, contact_id);
+ }
+
+
+ /**
+ * Create a new persona.
+ *
+ * Create a new persona for the { link PersonaStore} `store`, representing
+ * the EDS contact given by `contact`.
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public Persona (PersonaStore store, E.Contact contact)
+ {
+ var contact_id =
+ (string) Edsf.Persona._get_property_from_contact (contact, "id");
+ var uid = this.build_uid (BACKEND_NAME, store.id, contact_id);
+ var iid = Edsf.Persona.build_iid (store.id, contact_id);
+ var is_user = BookClient.is_self (contact);
+ var full_name =
+ (string) Edsf.Persona._get_property_from_contact (contact,
+ "full_name");
+
+ debug ("Creating new Edsf.Persona with IID '%s'", iid);
+
+ Object (display_id: full_name,
+ uid: uid,
+ iid: iid,
+ store: store,
+ gender: Gender.UNSPECIFIED,
+ is_user: is_user);
+
+ this.contact_id = contact_id;
+ this._phone_numbers = new HashSet<FieldDetails> ();
+ this._phone_numbers_ro = this._phone_numbers.read_only_view;
+ this._email_addresses = new HashSet<FieldDetails> ();
+ this._email_addresses_ro = this._email_addresses.read_only_view;
+ this._notes = new HashSet<Note> ();
+ this._notes_ro = this._notes.read_only_view;
+ this._urls = new HashSet<FieldDetails> ();
+ this._urls_ro = this._urls.read_only_view;
+ this._postal_addresses = new HashSet<PostalAddress> ();
+ this._postal_addresses_ro = this._postal_addresses.read_only_view;
+ this._local_ids = new HashSet<string> ();
+ this._local_ids_ro = this._local_ids.read_only_view;
+ this._web_service_addresses = new HashMultiMap<string, string> ();
+
+ this._update (contact);
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public override void linkable_property_to_links (string prop_name,
+ Folks.Persona.LinkablePropertyCallback callback)
+ {
+ if (prop_name == "im-addresses")
+ {
+ foreach (var protocol in this._im_addresses.get_keys ())
+ {
+ var im_addresses = this._im_addresses.get (protocol);
+
+ foreach (string address in im_addresses)
+ callback (protocol + ":" + address);
+ }
+ }
+ else if (prop_name == "local-ids")
+ {
+ foreach (var id in this._local_ids)
+ {
+ callback (id);
+ }
+ }
+ else if (prop_name == "web-service-addresses")
+ {
+ foreach (var web_service in this.web_service_addresses.get_keys ())
+ {
+ var web_service_addresses =
+ this._web_service_addresses.get (web_service);
+
+ foreach (string address in web_service_addresses)
+ callback (web_service + ":" + address);
+ }
+ }
+ else
+ {
+ /* Chain up */
+ base.linkable_property_to_links (prop_name, callback);
+ }
+ }
+
+ ~Persona ()
+ {
+ debug ("Destroying Edsf.Persona '%s': %p", this.uid, this);
+ }
+
+ /**
+ * Update attribs of the persona.
+ */
+ internal void _update (E.Contact contact)
+ {
+ this.contact = contact;
+
+ this._update_names ();
+ this._update_avatar ();
+ this._update_urls ();
+ this._update_phones ();
+ this._update_addresses ();
+ this._update_emails ();
+ this._update_im_addresses ();
+ this._update_notes ();
+ this._update_local_ids ();
+ this._update_web_services_addresses ();
+ }
+
+ private void _update_web_services_addresses ()
+ {
+ this._web_service_addresses.clear ();
+
+ var services = this.contact.get_attribute ("X-FOLKS-WEB-SERVICES-IDS");
+ if (services != null)
+ {
+ foreach (var service in services.get_params ())
+ {
+ var service_name = service.get_name ().down ();
+ foreach (var service_id in service.get_values ())
+ {
+ this._web_service_addresses.set (service_name, service_id);
+ }
+ }
+ }
+
+ this.notify_property ("web-service-addresses");
+ }
+
+ private void _update_emails ()
+ {
+ this._email_addresses.clear ();
+
+ var attrs = _contact.get_attributes (E.ContactField.EMAIL);
+ foreach (var attr in attrs)
+ {
+ var fd = new FieldDetails (attr.get_value ());
+ foreach (var param in attr.get_params ())
+ {
+ string param_name = param.get_name ().down ();
+ foreach (var param_value in param.get_values ())
+ {
+ fd.add_parameter (param_name, param_value);
+ }
+ }
+ this._email_addresses.add (fd);
+ }
+
+ this.notify_property ("email-addresses");
+ }
+
+ private void _update_notes ()
+ {
+ this._notes.clear ();
+
+ string n = (string) this._get_property ("note");
+ if (n != null && n != "")
+ {
+ var note = new Note (n);
+ this._notes.add (note);
+ }
+
+ this.notify_property ("notes");
+ }
+
+ private void _update_names ()
+ {
+ string full_name = (string) this._get_property ("full_name");
+ if (this._full_name != full_name)
+ {
+ this._full_name = full_name;
+ this.notify_property ("full-name");
+ }
+
+ string nickname = (string) this._get_property ("nickname");
+ if (this.nickname != nickname)
+ {
+ this._nickname = nickname;
+ this.notify_property ("nickname");
+ }
+
+ StructuredName? structured_name = null;
+ E.ContactName? cn = (E.ContactName) this._get_property ("name");
+ if (cn != null)
+ {
+ string family_name = cn.family;
+ string given_name = cn.given;
+ string additional_names = cn.additional;
+ string prefixes = cn.prefixes;
+ string suffixes = cn.suffixes;
+ structured_name = new StructuredName (family_name, given_name,
+ additional_names, prefixes,
+ suffixes);
+ }
+
+ if (structured_name != null && !structured_name.is_empty ())
+ {
+ this._structured_name = structured_name;
+ this.notify_property ("structured-name");
+ }
+ else if (this._structured_name != null)
+ {
+ this._structured_name = null;
+ this.notify_property ("structured-name");
+ }
+ }
+
+ private void _update_avatar ()
+ {
+ string filename = this.uid.delimit (Path.DIR_SEPARATOR.to_string (), '-');
+ string cached_avatar_path = GLib.Path.build_filename (
+ GLib.Environment.get_user_cache_dir (), "folks",
+ "avatars", filename);
+ E.ContactPhoto? p = (E.ContactPhoto) this._get_property ("photo");
+
+ this._avatar = File.new_for_path (cached_avatar_path);
+
+ if (p != null)
+ {
+ var content_old = this.get_avatar_content ();
+ var content_new = this._get_avatar_content_from_contact (p);
+
+ if (content_old != content_new)
+ {
+ try
+ {
+ this._avatar.replace_contents (content_new,
+ content_new.length,
+ null, false, FileCreateFlags.REPLACE_DESTINATION,
+ null);
+ this.notify_property ("avatar");
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Can't write avatar: %s\n", e.message);
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ this._avatar.delete ();
+ }
+ catch (GLib.Error e) {}
+ finally
+ {
+ this._avatar = null;
+ this.notify_property ("avatar");
+ }
+ }
+ }
+
+ private void _update_urls ()
+ {
+ this._urls.clear ();
+
+ foreach (string url_property in this.url_properties)
+ {
+ string u = (string) this._get_property (url_property);
+ if (u != null && u != "")
+ {
+ this._urls.add (new FieldDetails (u));
+ }
+ }
+
+ this.notify_property ("urls");
+ }
+
+ private void _update_im_addresses ()
+ {
+ var im_eds_map = this._get_im_eds_map ();
+ this._im_addresses.clear ();
+
+ foreach (var proto in im_eds_map.get_keys ())
+ {
+ var addresses = this.contact.get_attributes (
+ im_eds_map.lookup (proto));
+ foreach (var attr in addresses)
+ {
+ try
+ {
+ var addr = attr.get_value ();
+ string address = (owned) ImDetails.normalise_im_address (addr,
+ proto);
+ this._im_addresses.set (proto, address);
+ }
+ catch (Folks.ImDetailsError e)
+ {
+ GLib.warning (
+ "Problem when trying to normalise address: %s\n",
+ e.message);
+ }
+ }
+ }
+
+ this.notify_property ("im-addresses");
+ }
+
+ /**
+ * Get the avatars content
+ *
+ * @since 0.5.UNRELEASED
+ */
+ public string get_avatar_content ()
+ {
+ string content = "";
+
+ if (this._avatar != null &&
+ this._avatar.query_exists ())
+ {
+ try
+ {
+ uint8[] content_temp;
+ this._avatar.load_contents (null, out content_temp);
+ content = (string) content_temp;
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Can't compare avatars: %s\n", e.message);
+ }
+ }
+
+ return content;
+ }
+
+ private string _get_avatar_content_from_contact (E.ContactPhoto p)
+ {
+ string content = "";
+
+ if (p.type == ContactPhotoType.INLINED)
+ {
+ content = (string) p.get_inlined ();
+ }
+ else if (p.type == ContactPhotoType.URI)
+ {
+ try
+ {
+ uint8[] temp_content;
+ var file = File.new_for_uri (p.get_uri ());
+ file.load_contents (null, out temp_content);
+ content = (string) temp_content;
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Couldn't load content for avatar: %s\n",
+ p.get_uri ());
+ }
+ }
+
+ return content;
+ }
+
+ /**
+ * build a table of im protocols / im protocol aliases
+ */
+ internal static HashTable<string, E.ContactField> _get_im_eds_map ()
+ {
+ lock (Edsf.Persona._im_eds_map)
+ {
+ if (Edsf.Persona._im_eds_map == null)
+ {
+ Edsf.Persona._im_eds_map =
+ new HashTable<string, E.ContactField> (str_hash, str_equal);
+ Edsf.Persona._im_eds_map.insert ("aim", ContactField.IM_AIM);
+ Edsf.Persona._im_eds_map.insert ("yahoo", ContactField.IM_YAHOO);
+ Edsf.Persona._im_eds_map.insert ("groupwise",
+ ContactField.IM_GROUPWISE);
+ Edsf.Persona._im_eds_map.insert ("jabber",
+ ContactField.IM_JABBER);
+ Edsf.Persona._im_eds_map.insert ("msn",
+ ContactField.IM_MSN);
+ Edsf.Persona._im_eds_map.insert ("icq",
+ ContactField.IM_ICQ);
+ Edsf.Persona._im_eds_map.insert ("gadugadu",
+ ContactField.IM_GADUGADU);
+ Edsf.Persona._im_eds_map.insert ("skype",
+ ContactField.IM_SKYPE);
+ }
+ }
+
+ return Edsf.Persona._im_eds_map;
+ }
+
+ private void _update_phones ()
+ {
+ this._phone_numbers.clear ();
+
+ var attrs = _contact.get_attributes (E.ContactField.TEL);
+ foreach (var attr in attrs)
+ {
+ var fd = new FieldDetails (attr.get_value ());
+ foreach (var param in attr.get_params ())
+ {
+ string param_name = param.get_name ().down ();
+ foreach (var param_value in param.get_values ())
+ {
+ fd.add_parameter (param_name, param_value);
+ }
+ }
+ this._phone_numbers.add (fd);
+ }
+
+ this.notify_property ("phone-numbers");
+ }
+
+ /*
+ * TODO: we should check if addresses corresponding to different types
+ * are the same and if so instantiate only one PostalAddress
+ * (with the given types).
+ */
+ private void _update_addresses ()
+ {
+ this._postal_addresses.clear ();
+
+ foreach (string afield in this.address_fields)
+ {
+ E.ContactAddress a =
+ (E.ContactAddress) this._get_property (afield);
+ if (a != null)
+ {
+ /* FIXME: might be my broken setup, but it looks like
+ * e-d-s is ignoring the address_format param */
+ var address_format = a.address_format;
+ var postal_code = a.code;
+ var country = a.country;
+ var extension = a.ext;
+ var locality = a.locality;
+ var po_box = a.po;
+ var region = a.region;
+ var street = a.street;
+ var types = new HashSet<string> ();
+ types.add (afield);
+
+ PostalAddress pa = new PostalAddress (po_box, extension, street,
+ locality, region, postal_code, country,
+ address_format, types, null);
+ this._postal_addresses.add (pa);
+ }
+ }
+
+ this.notify_property ("postal-addresses");
+ }
+
+ private void _update_local_ids ()
+ {
+ this._local_ids.clear ();
+
+ var ids = this.contact.get_attribute ("X-FOLKS-CONTACTS-IDS");
+ if (ids != null)
+ {
+ unowned GLib.List<string> ids_v = ids.get_values ();
+
+ foreach (var local_id in ids_v)
+ {
+ this._local_ids.add (local_id);
+ }
+ }
+
+ this.notify_property ("local-ids");
+ }
+
+ internal static void * _get_property_from_contact (E.Contact contact,
+ string prop_name)
+ {
+ void *prop_value = null;
+ prop_value = contact.get (E.Contact.field_id (prop_name));
+ return prop_value;
+ }
+
+ private void * _get_property (string prop_name)
+ {
+ return Edsf.Persona._get_property_from_contact (this.contact,
+ prop_name);
+ }
+}
diff --git a/backends/eds/lib/folks-eds-uninstalled.pc.in b/backends/eds/lib/folks-eds-uninstalled.pc.in
new file mode 100644
index 0000000..d1f76e7
--- /dev/null
+++ b/backends/eds/lib/folks-eds-uninstalled.pc.in
@@ -0,0 +1,12 @@
+prefix=
+exec_prefix=
+abs_top_srcdir= abs_top_srcdir@
+abs_top_builddir= abs_top_builddir@
+vapidir= abs_top_srcdir@/folks
+
+Name: Folks e-d-s support library (uninstalled copy)
+Description: Evolution Data Server support library for the Folks meta-contacts library
+Version: @VERSION@
+Requires: folks glib-2.0 gobject-2.0 gee-1.0 libebook-1.2 libedataserver-1.2
+Libs: ${abs_top_builddir}/backends/telepathy/libfolks-eds.la
+Cflags: -I${abs_top_srcdir} -I${abs_top_srcdir}/backends/eds -I${abs_top_builddir}
diff --git a/backends/eds/lib/folks-eds.deps b/backends/eds/lib/folks-eds.deps
new file mode 100644
index 0000000..9cb8d84
--- /dev/null
+++ b/backends/eds/lib/folks-eds.deps
@@ -0,0 +1,6 @@
+glib-2.0
+gobject-2.0
+folks
+libebook-1.2
+libedataserver-1.2
+gee-1.0
diff --git a/backends/eds/lib/folks-eds.pc.in b/backends/eds/lib/folks-eds.pc.in
new file mode 100644
index 0000000..4e01ba4
--- /dev/null
+++ b/backends/eds/lib/folks-eds.pc.in
@@ -0,0 +1,15 @@
+prefix= prefix@
+exec_prefix= exec_prefix@
+libdir= libdir@
+bindir= bindir@
+includedir= includedir@
+datarootdir= datarootdir@
+datadir= datadir@
+vapidir= datadir@/vala/vapi
+
+Name: Folks e-d-s support library
+Description: Evolution Data Server support library for the Folks meta-contacts library
+Version: @VERSION@
+Requires: folks glib-2.0 gobject-2.0 gee-1.0 libebook-1.2 libedataserver-1.2
+Libs: -L${libdir} -lfolks-eds
+Cflags: -I${includedir} -I${includedir}/folks
diff --git a/configure.ac b/configure.ac
index 3b93742..79752a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -77,6 +77,14 @@ AC_ARG_ENABLE(tracker-backend,
AM_CONDITIONAL([ENABLE_TRACKER], [test "x$enable_tracker_backend" = "xyes"])
+AC_ARG_ENABLE(eds-backend,
+ AC_HELP_STRING([--enable-eds-backend],
+ [ build the E-D-S backend]),
+ enable_eds_backend=$enableval,
+ enable_eds_backend=no )
+
+AM_CONDITIONAL([ENABLE_EDS], [test "x$enable_eds_backend" = "xyes"])
+
# Automatically check the dependencies for the libsocialweb backend
SW_CLIENT_REQUIRED=0.25.15
AC_ARG_ENABLE(libsocialweb-backend,
@@ -124,6 +132,8 @@ VALA_REQUIRED=0.12.0
VALADOC_REQUIRED=0.2.1
TRACKER_SPARQL_REQUIRED=0.10
GCONF2_REQUIRED=2.31
+EBOOK_REQUIRED=3.0.1
+EDATASERVER_REQUIRED=3.0.1
PKG_CHECK_MODULES([GLIB],
[glib-2.0 >= $GLIB_REQUIRED
@@ -142,6 +152,11 @@ if test x$enable_tracker_backend = xyes; then
[tracker-sparql-0.10 >= $TRACKER_SPARQL_REQUIRED])
fi
+if test x$enable_eds_backend = xyes; then
+ PKG_CHECK_MODULES([EBOOK], [libebook-1.2 >= $EBOOK_REQUIRED])
+ PKG_CHECK_MODULES([EDATASERVER], [libedataserver-1.2 >= $EDATASERVER_REQUIRED])
+fi
+
#
# Vala building options -- allows tarball builds without installing Vala
#
@@ -218,6 +233,9 @@ if test "x$enable_vala" = "xyes" ; then
VALA_CHECK_PACKAGES([tracker-sparql-0.10])
fi
+ if test x$enable_eds_backend = xyes; then
+ VALA_CHECK_PACKAGES([libxml-2.0])
+ fi
fi
# this will set HAVE_INTROSPECTION
@@ -244,6 +262,8 @@ BACKEND_KF='$(top_builddir)/backends/key-file/.libs/libfolks-backend-key-file.so
AC_SUBST([BACKEND_KF])
BACKEND_TP='$(top_builddir)/backends/telepathy/.libs/libfolks-backend-telepathy.so'
AC_SUBST([BACKEND_TP])
+BACKEND_EDS='$(top_builddir)/backends/eds/.libs/libfolks-backend-eds.so'
+AC_SUBST([BACKEND_EDS])
if test x$have_libsocialweb_backend = xyes; then
BACKEND_LIBSOCIALWEB='$(top_builddir)/backends/libsocialweb/.libs/libfolks-backend-libsocialweb.so'
@@ -255,6 +275,11 @@ if test x$enable_tracker_backend = xyes; then
AC_SUBST([BACKEND_TRACKER])
fi
+if test x$enable_eds_backend = xyes; then
+ BACKEND_EDS='$(top_builddir)/backends/eds/.libs/libfolks-backend-eds.so'
+ AC_SUBST([BACKEND_EDS])
+fi
+
# All of the backend libraries in our tree; to be used by the tests
BACKEND_UNINST_PATH='$(BACKEND_KF):$(BACKEND_TP)'
if test x$have_libsocialweb_backend = xyes; then
@@ -265,6 +290,10 @@ if test x$enable_tracker_backend = xyes; then
TRACKER_BACKEND_UNINST_PATH='$(BACKEND_TRACKER)'
BACKEND_UNINST_PATH="$BACKEND_UNINST_PATH:$TRACKER_BACKEND_UNINST_PATH"
fi
+if test x$enable_eds_backend = xyes; then
+ EDS_BACKEND_UNINST_PATH='$(BACKEND_EDS)'
+ BACKEND_UNINST_PATH="$BACKEND_UNINST_PATH:$EDS_BACKEND_UNINST_PATH"
+fi
AC_SUBST([BACKEND_UNINST_PATH])
# -----------------------------------------------------------
@@ -404,6 +433,8 @@ AC_CONFIG_FILES([
backends/telepathy/lib/folks-telepathy-uninstalled.pc
backends/tracker/lib/folks-tracker.pc
backends/tracker/lib/folks-tracker-uninstalled.pc
+ backends/eds/lib/folks-eds.pc
+ backends/eds/lib/folks-eds-uninstalled.pc
folks/folks.pc
folks/folks-uninstalled.pc
Makefile
@@ -417,6 +448,8 @@ AC_CONFIG_FILES([
backends/telepathy/lib/Makefile
backends/tracker/Makefile
backends/tracker/lib/Makefile
+ backends/eds/Makefile
+ backends/eds/lib/Makefile
folks/Makefile
docs/Makefile
po/Makefile.in
@@ -433,6 +466,8 @@ AC_CONFIG_FILES([
tests/lib/key-file/Makefile
tests/lib/libsocialweb/Makefile
tests/lib/libsocialweb/session.conf
+ tests/eds/Makefile
+ tests/lib/eds/Makefile
tests/lib/telepathy/Makefile
tests/lib/tracker/Makefile
tests/lib/telepathy/contactlist/Makefile
@@ -457,6 +492,6 @@ Configure summary:
Inspector tool..............: ${with_inspect_tool}
Tracker backend.............: ${enable_tracker_backend}
Libsocialweb backend........: ${have_libsocialweb_backend}
-
+ E-D-S backend...............: ${enable_eds_backend}
"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0c29f1e..00e2f40 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,6 +15,10 @@ if ENABLE_TRACKER
SUBDIRS += tracker
endif
+if ENABLE_EDS
+SUBDIRS += eds
+endif
+
DIST_SUBDIRS = \
data \
lib \
@@ -24,6 +28,7 @@ DIST_SUBDIRS = \
telepathy \
libsocialweb \
tracker \
+ eds \
$(NULL)
TESTS_ENVIRONMENT = \
diff --git a/tests/eds/Makefile.am b/tests/eds/Makefile.am
new file mode 100644
index 0000000..6fc1645
--- /dev/null
+++ b/tests/eds/Makefile.am
@@ -0,0 +1,211 @@
+AM_CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(EBOOK_CFLAGS) \
+ $(EDATASERVER_CFLAGS) \
+ $(GCONF2_CFLAGS) \
+ -I$(top_srcdir)/folks \
+ -I$(top_srcdir)/backends/eds/lib \
+ -I$(top_srcdir)/tests/lib \
+ -I$(top_srcdir)/tests/lib/eds \
+ -include $(CONFIG_HEADER) \
+ $(NULL)
+
+LDADD = \
+ $(top_builddir)/tests/lib/eds/libeds-test.la \
+ $(top_builddir)/tests/lib/libfolks-test.la \
+ $(top_builddir)/backends/eds/lib/libfolks-eds.la
+ $(top_builddir)/folks/libfolks.la \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(GCONF2_LIBS) \
+ -L$(top_srcdir)/backends/eds/lib \
+ $(NULL)
+
+AM_VALAFLAGS = \
+ --vapidir=. \
+ --vapidir=$(top_srcdir)/folks \
+ --vapidir=$(top_srcdir)/backends/eds/lib \
+ --vapidir=$(top_srcdir)/tests/lib \
+ --vapidir=$(top_srcdir)/tests/lib/eds \
+ --pkg gobject-2.0 \
+ --pkg gio-2.0 \
+ --pkg gee-1.0 \
+ --pkg folks \
+ --pkg folks-test \
+ --pkg libebook-1.2 \
+ --pkg libedataserver-1.2 \
+ --pkg libxml-2.0 \
+ --pkg folks-eds \
+ --pkg eds-test \
+ --pkg gconf-2.0 \
+ $(NULL)
+
+# in order from least to most complex
+noinst_PROGRAMS = \
+ persona-store-tests \
+ individual-retrieval \
+ phone-details \
+ email-details \
+ name-details \
+ removing-contacts \
+ updating-contacts \
+ avatar-details \
+ add-persona \
+ im-details \
+ postal-address-details \
+ remove-persona \
+ set-avatar \
+ set-emails \
+ set-im-addresses \
+ set-full-name \
+ set-structured-name \
+ set-phones \
+ set-postal-addresses \
+ link-personas \
+ set-notes \
+ add-contacts-stress-test \
+ $(NULL)
+
+RUN_WITH_PRIVATE_BUS = $(top_srcdir)/tests/tools/with-session-bus-eds.sh
+
+backend_store_key_file=$(srcdir)/data/backend-eds-only.ini
+avatar_file= abs_top_srcdir@/tests/data/avatar-01.jpg
+TESTS_ENVIRONMENT = \
+ GCONF_DEFAULT_SOURCE_PATH= abs_top_srcdir@/tests/data/gconf.path \
+ FOLKS_BACKEND_PATH=$(BACKEND_UNINST_PATH) \
+ FOLKS_BACKEND_STORE_KEY_FILE_PATH=$(backend_store_key_file) \
+ AVATAR_FILE_PATH=$(avatar_file) \
+ $(RUN_WITH_PRIVATE_BUS) \
+ --session \
+ --
+
+TESTS = $(noinst_PROGRAMS)
+
+persona_store_tests_SOURCES = \
+ persona-store-tests.vala \
+ $(NULL)
+
+individual_retrieval_SOURCES = \
+ individual-retrieval.vala \
+ $(NULL)
+
+removing_contacts_SOURCES = \
+ removing-contacts.vala \
+ $(NULL)
+
+updating_contacts_SOURCES = \
+ updating-contacts.vala \
+ $(NULL)
+
+phone_details_SOURCES = \
+ phone-details.vala \
+ $(NULL)
+
+email_details_SOURCES = \
+ email-details.vala \
+ $(NULL)
+
+name_details_SOURCES = \
+ name-details.vala \
+ $(NULL)
+
+avatar_details_SOURCES = \
+ avatar-details.vala \
+ $(NULL)
+
+add_persona_SOURCES = \
+ add-persona.vala \
+ $(NULL)
+
+im_details_SOURCES = \
+ im-details.vala \
+ $(NULL)
+
+postal_address_details_SOURCES = \
+ postal-address-details.vala \
+ $(NULL)
+
+remove_persona_SOURCES = \
+ remove-persona.vala \
+ $(NULL)
+
+set_avatar_SOURCES = \
+ set-avatar.vala \
+ $(NULL)
+
+set_emails_SOURCES = \
+ set-emails.vala \
+ $(NULL)
+
+set_im_addresses_SOURCES = \
+ set-im-addresses.vala \
+ $(NULL)
+
+set_full_name_SOURCES = \
+ set-full-name.vala \
+ $(NULL)
+
+set_structured_name_SOURCES = \
+ set-structured-name.vala \
+ $(NULL)
+
+set_phones_SOURCES = \
+ set-phones.vala \
+ $(NULL)
+
+set_postal_addresses_SOURCES = \
+ set-postal-addresses.vala \
+ $(NULL)
+
+link_personas_SOURCES = \
+ link-personas.vala \
+ $(NULL)
+
+set_notes_SOURCES = \
+ set-notes.vala \
+ $(NULL)
+
+add_contacts_stress_test_SOURCES = \
+ add-contacts-stress-test.vala \
+ $(NULL)
+
+CLEANFILES = \
+ *.pid \
+ *.address \
+ $(TESTS) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ $(addsuffix .c,$(noinst_PROGRAMS)) \
+ persona_store_tests_vala.stamp \
+ individual_retrieval_vala.stamp \
+ removing_contacts_vala.stamp \
+ updating_contacts_vala.stamp \
+ phone_details_vala.stamp \
+ name_details_vala.stamp \
+ email_details_vala.stamp \
+ avatar_details_vala.stamp \
+ add_persona_vala.stamp \
+ im_details_vala.stamp \
+ postal_address_details_vala.stamp \
+ remove_persona_vala.stamp \
+ set_avatar_vala.stamp \
+ set_emails_vala.stamp \
+ set_im_addresses_vala.stamp \
+ set_full_name_vala.stamp \
+ set_structured_name_vala.stamp \
+ set_phones_vala.stamp \
+ set_postal_addresses_vala.stamp \
+ link_personas_vala.stamp \
+ set_notes_vala.stamp \
+ add_contacts_stress_test_vala.stamp \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(MAINTAINERCLEANFILES) \
+ $(backend_store_key_file) \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
+-include $(top_srcdir)/check.mk
\ No newline at end of file
diff --git a/tests/eds/add-contacts-stress-test.vala b/tests/eds/add-contacts-stress-test.vala
new file mode 100644
index 0000000..b850ef3
--- /dev/null
+++ b/tests/eds/add-contacts-stress-test.vala
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using Folks;
+using Gee;
+
+public class AddContactsStressTestTests : Folks.TestCase
+{
+ private GLib.MainLoop _main_loop;
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private Edsf.PersonaStore _pstore;
+ private bool _added_contacts = false;
+ private HashTable<string, bool> _contacts_found;
+ private int _contacts_cnt = 150;
+
+ public AddContactsStressTestTests ()
+ {
+ base ("AddContactsStressTestTests");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ var test_desc = "stress testing adding (%d) contacts to e-d-s ".printf (
+ this._contacts_cnt);
+ this.add_test (test_desc, this.test_add_contacts);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_add_contacts ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+
+ this._contacts_found = new HashTable<string, bool> (str_hash, str_equal);
+ for (var i=0; i<this._contacts_cnt; i++)
+ {
+ var persona_name = "full_name -%d".printf (i);
+ this._contacts_found.insert (persona_name, false);
+ }
+
+ this._test_add_persona_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ int found = 0;
+ foreach (var k in this._contacts_found.get_values ())
+ {
+ if (k)
+ found++;
+ }
+
+ assert (found == this._contacts_cnt);
+ }
+
+ private async void _test_add_persona_async ()
+ {
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+
+ this._pstore = null;
+ foreach (var backend in store.enabled_backends.values)
+ {
+ this._pstore =
+ (Edsf.PersonaStore) backend.persona_stores.get ("local://test");
+ if (this._pstore != null)
+ break;
+ }
+ assert (this._pstore != null);
+ this._pstore.notify["is-prepared"].connect (this._notify_pstore_cb);
+ this._try_to_add ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private async void _add_contacts ()
+ {
+ for (var i=0; i<this._contacts_cnt; i++)
+ {
+ var persona_name = "full_name -%d".printf (i);
+ HashTable<string, Value?> details = new HashTable<string, Value?>
+ (str_hash, str_equal);
+
+ Value? v1 = Value (typeof (string));
+ v1.set_string (persona_name);
+ details.insert (Folks.PersonaStore.detail_key (
+ PersonaDetail.FULL_NAME),
+ (owned) v1);
+
+ try
+ {
+ yield this._aggregator.add_persona_from_details (null,
+ this._pstore, details);
+ }
+ catch (Folks.IndividualAggregatorError e)
+ {
+ GLib.warning ("[AddContactsStressTest]: %d: %s\n", i,
+ e.message);
+ }
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (var i in added)
+ {
+ assert (this._contacts_found.lookup (i.full_name) == false);
+ this._contacts_found.replace (i.full_name, true);
+ }
+
+ assert (removed.size == 0);
+
+ this._exit_if_all_contacts_found ();
+ }
+
+ private void _notify_pstore_cb (Object _pstore, ParamSpec ps)
+ {
+ this._try_to_add ();
+ }
+
+ private void _try_to_add ()
+ {
+ lock (this._added_contacts)
+ {
+ if (this._pstore.is_prepared &&
+ this._added_contacts == false)
+ {
+ this._added_contacts = true;
+ this._add_contacts ();
+ }
+ }
+ }
+
+ private void _exit_if_all_contacts_found ()
+ {
+ foreach (var k in this._contacts_found.get_keys ())
+ {
+ var v = this._contacts_found.lookup (k);
+ if (v == false)
+ return;
+ }
+ this._main_loop.quit ();
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new AddContactsStressTestTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/add-persona.vala b/tests/eds/add-persona.vala
new file mode 100644
index 0000000..acc0660
--- /dev/null
+++ b/tests/eds/add-persona.vala
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using Folks;
+using Gee;
+
+public class AddPersonaTests : Folks.TestCase
+{
+ private GLib.MainLoop _main_loop;
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private string _persona_fullname;
+ private string _email_1;
+ private Edsf.PersonaStore _pstore;
+ private bool _added_persona = false;
+ private HashTable<string, bool> _properties_found;
+ private string _avatar_path;
+ private string _im_addr_1;
+ private string _im_addr_2;
+ private string _phone_1;
+ private string _phone_2;
+ private PostalAddress _address;
+ private string _po_box = "12345";
+ private string _locality = "locality";
+ private string _postal_code = "code";
+ private string _street = "some street";
+ private string _extension = "some extension";
+ private string _country = "some country";
+ private string _region = "some region";
+ private string _family_name;
+ private string _given_name;
+ private string _note = "This is a note.";
+
+ public AddPersonaTests ()
+ {
+ base ("AddPersonaTests");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("test adding a persona to e-d-s ", this.test_add_persona);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_add_persona ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ this._persona_fullname = "persona #1";
+ this._email_1 = "someone-1 example org";
+ this._avatar_path = Environment.get_variable ("AVATAR_FILE_PATH");
+ this._im_addr_1 = "someone-1 jabber example org";
+ this._im_addr_2 = "someone-2 jabber example org";
+ this._phone_1 = "12345";
+ this._phone_2 = "54321";
+ this._family_name = "family";
+ this._given_name = "given";
+
+ var types = new HashSet<string> ();
+ types.add (Edsf.Persona.address_fields[0]);
+ this._address = new PostalAddress (this._po_box,
+ this._extension, this._street, this._locality, this._region,
+ this._postal_code, this._country, null, types, null);
+
+ this._properties_found = new HashTable<string, bool>
+ (str_hash, str_equal);
+ this._properties_found.insert ("full_name", false);
+ this._properties_found.insert ("email-1", false);
+ this._properties_found.insert ("avatar", false);
+ this._properties_found.insert ("im-addr-1", false);
+ this._properties_found.insert ("im-addr-2", false);
+ this._properties_found.insert ("phone-1", false);
+ this._properties_found.insert ("phone-2", false);
+ this._properties_found.insert ("postal-address-1", false);
+ this._properties_found.insert ("structured_name", false);
+ this._properties_found.insert ("note", false);
+
+ this._test_add_persona_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ foreach (var k in this._properties_found.get_values ())
+ {
+ assert (k);
+ }
+ }
+
+ private async void _test_add_persona_async ()
+ {
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+
+ this._pstore = null;
+ foreach (var backend in store.enabled_backends.values)
+ {
+ this._pstore =
+ (Edsf.PersonaStore) backend.persona_stores.get ("local://test");
+ if (this._pstore != null)
+ break;
+ }
+ assert (this._pstore != null);
+ this._pstore.notify["is-prepared"].connect (this._notify_pstore_cb);
+ this._try_to_add ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private async void _add_persona ()
+ {
+ HashTable<string, Value?> details = new HashTable<string, Value?>
+ (str_hash, str_equal);
+
+ Value? v1 = Value (typeof (string));
+ v1.set_string (this._persona_fullname);
+ details.insert (Folks.PersonaStore.detail_key (PersonaDetail.FULL_NAME),
+ (owned) v1);
+
+ Value? v2 = Value (typeof (Set<FieldDetails>));
+ var emails = new HashSet<FieldDetails> ();
+ var email_1 = new FieldDetails (this._email_1);
+ email_1.set_parameter ("type", Edsf.Persona.email_fields[0]);
+ emails.add (email_1);
+ v2.set_object (emails);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.EMAIL_ADDRESSES),
+ (owned) v2);
+
+ Value? v3 = Value (typeof (File));
+ File avatar = File.new_for_path (this._avatar_path);
+ v3.set_object (avatar);
+ details.insert (Folks.PersonaStore.detail_key (PersonaDetail.AVATAR),
+ (owned) v3);
+
+ Value? v4 = Value (typeof (MultiMap<string, string>));
+ var im_addrs = new HashMultiMap<string, string> ();
+ im_addrs.set ("jabber", this._im_addr_1);
+ im_addrs.set ("yahoo", this._im_addr_2);
+ v4.set_object (im_addrs);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES), v4);
+
+ Value? v5 = Value (typeof (Set<FieldDetails>));
+ var phones = new HashSet<FieldDetails> ();
+ var phone_1 = new FieldDetails (this._phone_1);
+ phone_1.set_parameter ("type", Edsf.Persona.phone_fields[0]);
+ phones.add (phone_1);
+ var phone_2 = new FieldDetails (this._phone_2);
+ phone_2.set_parameter ("type", Edsf.Persona.phone_fields[1]);
+ phones.add (phone_2);
+ v5.set_object (phones);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.PHONE_NUMBERS),
+ (owned) v5);
+
+ Value? v6 = Value (typeof (Set<PostalAddress>));
+ var postal_addresses = new HashSet<PostalAddress> ();
+
+ var types = new HashSet<string> ();
+ types.add (Edsf.Persona.address_fields[0]);
+ PostalAddress postal_a = new PostalAddress (this._po_box,
+ this._extension, this._street, this._locality, this._region,
+ this._postal_code, this._country, null, types, null);
+ postal_addresses.add (postal_a);
+ v6.set_object (postal_addresses);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.POSTAL_ADDRESSES),
+ (owned) v6);
+
+ Value? v7 = Value (typeof (StructuredName));
+ StructuredName sname = new StructuredName (this._family_name,
+ this._given_name, null, null, null);
+ v7.set_object (sname);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.STRUCTURED_NAME),
+ (owned) v7);
+
+ Value? v8 = Value (typeof (Set<Note>));
+ var notes = new HashSet<Note> ();
+ var note = new Note(this._note);
+ notes.add (note);
+ v8.set_object (notes);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.NOTES),
+ (owned) v8);
+
+ try
+ {
+ yield this._aggregator.add_persona_from_details (null,
+ this._pstore, details);
+ }
+ catch (Folks.IndividualAggregatorError e)
+ {
+ GLib.warning ("[AddPersonaError] add_persona_from_details: %s\n",
+ e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (var i in added)
+ {
+ if (i.is_user == false)
+ {
+ i.notify["full-name"].connect (this._notify_cb);
+ i.notify["email-addresses"].connect (this._notify_cb);
+ i.notify["avatar"].connect (this._notify_cb);
+ i.notify["im-addresses"].connect (this._notify_cb);
+ i.notify["phone-numbers"].connect (this._notify_cb);
+ i.notify["postal-addresses"].connect (this._notify_cb);
+ i.notify["structured-name"].connect (this._notify_cb);
+ i.notify["notes"].connect (this._notify_cb);
+
+ this._check_properties (i);
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ this._check_properties (i);
+ }
+
+ private void _notify_pstore_cb (Object _pstore, ParamSpec ps)
+ {
+ this._try_to_add ();
+ }
+
+ private void _try_to_add ()
+ {
+ lock (this._added_persona)
+ {
+ if (this._pstore.is_prepared &&
+ this._added_persona == false)
+ {
+ this._added_persona = true;
+ this._add_persona ();
+ }
+ }
+ }
+
+ private void _check_properties (Individual i)
+ {
+ if (i.full_name == this._persona_fullname)
+ this._properties_found.replace ("full_name", true);
+
+ foreach (var e in i.email_addresses)
+ {
+ if (e.value == this._email_1)
+ {
+ this._properties_found.replace ("email-1", true);
+ }
+ }
+
+ if (i.avatar != null)
+ {
+ uint8[] content_a;
+ uint8[] content_b;
+ var b = File.new_for_path (this._avatar_path);
+
+ try
+ {
+ i.avatar.load_contents (null, out content_a);
+ b.load_contents (null, out content_b);
+
+ if (((string) content_a) == ((string) content_b))
+ {
+ this._properties_found.replace ("avatar", true);
+ }
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Couldn't load avatars: %s",
+ e.message);
+ }
+ }
+
+ foreach (var proto in i.im_addresses.get_keys ())
+ {
+ var addrs = i.im_addresses.get (proto);
+ foreach (var a in addrs)
+ {
+ if (a == this._im_addr_1)
+ this._properties_found.replace ("im-addr-1", true);
+ else if (a == this._im_addr_2)
+ this._properties_found.replace ("im-addr-2", true);
+ }
+ }
+
+ foreach (var e in i.phone_numbers)
+ {
+ if (e.value == this._phone_1)
+ {
+ this._properties_found.replace ("phone-1", true);
+ }
+ else if (e.value == this._phone_2)
+ {
+ this._properties_found.replace ("phone-2", true);
+ }
+ }
+
+ foreach (var pa in i.postal_addresses)
+ {
+ this._address.uid = pa.uid;
+ if (pa.equal (this._address))
+ this._properties_found.replace ("postal-address-1", true);
+ }
+
+ if (i.structured_name != null &&
+ i.structured_name.family_name == this._family_name &&
+ i.structured_name.given_name == this._given_name)
+ this._properties_found.replace ("structured_name", true);
+
+ foreach (var note in i.notes)
+ {
+ if (note.content == this._note)
+ {
+ this._properties_found.replace ("note", true);
+ break;
+ }
+ }
+
+ this._exit_if_all_properties_found ();
+ }
+
+ private void _exit_if_all_properties_found ()
+ {
+ foreach (var k in this._properties_found.get_keys ())
+ {
+ var v = this._properties_found.lookup (k);
+ if (v == false)
+ return;
+ }
+ this._main_loop.quit ();
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new AddPersonaTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/avatar-details.vala b/tests/eds/avatar-details.vala
new file mode 100644
index 0000000..63332ef
--- /dev/null
+++ b/tests/eds/avatar-details.vala
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class AvatarDetailsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private Gee.HashMap<string, Value?> _c1;
+ private bool _avatars_are_equal;
+ private string _avatar_path;
+
+ public AvatarDetailsTests ()
+ {
+ base ("AvatarDetails");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("avatar details interface", this.test_avatar);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_avatar ()
+ {
+ this._c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ this._avatar_path = Environment.get_variable ("AVATAR_FILE_PATH");
+ this._avatars_are_equal = false;
+ Value? v;
+
+ this._eds_backend.reset();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ this._c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string (this._avatar_path);
+ this._c1.set ("avatar",(owned) v);
+ this._eds_backend.add_contact (this._c1);
+
+ this._test_avatar_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ return false;
+ });
+
+ this._main_loop.run ();
+
+ assert (this._avatars_are_equal);
+ }
+
+ private async void _test_avatar_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+
+ assert (removed.size == 0);
+
+ foreach (Individual i in added)
+ {
+ assert (i.personas.size == 1);
+
+ if (i.full_name == "bernie h. innocenti")
+ {
+ uint8[] content_a;
+ uint8[] content_b;
+ var b = File.new_for_path (this._avatar_path);
+
+ try
+ {
+ i.avatar.load_contents (null, out content_a);
+ b.load_contents (null, out content_b);
+
+ if (((string) content_a) == ((string) content_b))
+ {
+ this._avatars_are_equal = true;
+ this._main_loop.quit ();
+ }
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("couldn't load file a");
+ }
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new AvatarDetailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/data/backend-eds-only.ini b/tests/eds/data/backend-eds-only.ini
new file mode 100644
index 0000000..e8a66e1
--- /dev/null
+++ b/tests/eds/data/backend-eds-only.ini
@@ -0,0 +1,5 @@
+[eds]
+enabled=true
+
+[all-others]
+enabled=false
diff --git a/tests/eds/email-details.vala b/tests/eds/email-details.vala
new file mode 100644
index 0000000..2bcdbe0
--- /dev/null
+++ b/tests/eds/email-details.vala
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class EmailDetailsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private int _email_count;
+ private HashSet<string> _email_types;
+ private Gee.HashMap<string, Value?> _c1;
+ private Gee.HashMap<string, Value?> _c2;
+ private Gee.HashMap<string, Value?> _c3;
+
+ public EmailDetailsTests ()
+ {
+ base ("EmailDetails");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("email details interface", this.test_email_details);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_email_details ()
+ {
+ this._email_count = 0;
+ this._email_types = new HashSet<string> (str_hash,
+ str_equal);
+ this._c1 = new Gee.HashMap<string, Value?> ();
+ this._c2 = new Gee.HashMap<string, Value?> ();
+ this._c3 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ this._c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("bernie example org");
+ this._c1.set (Edsf.Persona.email_fields[0], (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("bernie innocenti example org");
+ this._c1.set (Edsf.Persona.email_fields[1], (owned) v);
+ this._eds_backend.add_contact (this._c1);
+
+ v = Value (typeof (string));
+ v.set_string ("richard m. stallman");
+ this._c2.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("rms example org");
+ this._c2.set (Edsf.Persona.email_fields[0], (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("rms 1 example org");
+ this._c2.set (Edsf.Persona.email_fields[1], (owned) v);
+ this._eds_backend.add_contact (this._c2);
+
+ v = Value (typeof (string));
+ v.set_string ("foo bar");
+ this._c3.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("foo example org");
+ this._c3.set (Edsf.Persona.email_fields[0], (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("foo bar example org");
+ this._c3.set (Edsf.Persona.email_fields[1], (owned) v);
+ this._eds_backend.add_contact (this._c3);
+
+ this._test_email_details_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ return false;
+ });
+
+ this._main_loop.run ();
+
+ assert (this._email_count == 6);
+ assert (this._email_types.size == 1);
+ assert (this._c1.size == 0);
+ assert (this._c2.size == 0);
+ assert (this._c3.size == 0);
+
+ foreach (var pt in this._email_types)
+ {
+ assert (pt == "OTHER");
+ }
+ }
+
+ private async void _test_email_details_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ unowned Gee.HashMap<string, Value?> contact = null;
+ assert (i.personas.size == 1);
+
+ if (i.full_name == "bernie h. innocenti")
+ {
+ contact = this._c1;
+ }
+ else if (i.full_name == "richard m. stallman")
+ {
+ contact = this._c2;
+ }
+ else if (i.full_name == "foo bar")
+ {
+ contact = this._c3;
+ }
+
+ if (contact == null)
+ {
+ continue;
+ }
+
+ contact.unset ("full_name");
+ var email_owner = (Folks.EmailDetails) i;
+ foreach (var e in email_owner.email_addresses)
+ {
+ this._email_count++;
+
+ bool found = false;
+ for (int j = 0; j < 2; j++) {
+ var v = Edsf.Persona.email_fields[j];
+ if (contact.get (v) != null &&
+ contact.get (v).get_string () == e.value) {
+ found = true;
+ contact.unset (v);
+ }
+ }
+ assert (found);
+ foreach (var v in e.get_parameter_values("type"))
+ {
+ this._email_types.add (v);
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new EmailDetailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/im-details.vala b/tests/eds/im-details.vala
new file mode 100644
index 0000000..565c717
--- /dev/null
+++ b/tests/eds/im-details.vala
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using Folks;
+using Gee;
+
+public class ImDetailsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private int _num_addrs;
+ private bool _found_addr_1;
+ private bool _found_addr_2;
+ private string _fullname;
+ private string _im_addrs;
+
+ public ImDetailsTests ()
+ {
+ base ("ImDetailsTests");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("test im details interface",
+ this.test_im_details_interface);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_im_details_interface ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._fullname = "persona #1";
+ this._im_addrs = "im_jabber_home_1#test1 example org";
+ this._im_addrs += ",im_yahoo_home_1#test2 example org";
+ Value? v;
+
+ this._eds_backend.reset();
+
+ v = Value (typeof (string));
+ v.set_string (this._fullname);
+ c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string (this._im_addrs);
+ c1.set ("im_addresses", (owned) v);
+
+ this._eds_backend.add_contact (c1);
+
+ this._num_addrs = 0;
+ this._found_addr_1 = false;
+ this._found_addr_2 = false;
+
+ this._test_im_details_interface_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._num_addrs == 2);
+ assert (this._found_addr_1 == true);
+ assert (this._found_addr_2 == true);
+ }
+
+ private async void _test_im_details_interface_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (var i in added)
+ {
+ string full_name = i.full_name;
+ if (full_name == this._fullname)
+ {
+ foreach (var proto in i.im_addresses.get_keys ())
+ {
+ var addrs = i.im_addresses.get (proto);
+
+ if (proto == "jabber")
+ {
+ if (addrs.contains ("test1 example org"))
+ {
+ this._found_addr_1 = true;
+ this._num_addrs++;
+ }
+ }
+ else if (proto == "yahoo")
+ {
+ if (addrs.contains ("test2 example org"))
+ {
+ this._found_addr_2 = true;
+ this._num_addrs++;
+ }
+ }
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+
+ if (this._num_addrs == 2 &&
+ this._found_addr_1 == true &&
+ this._found_addr_2 == true)
+ this._main_loop.quit ();
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new ImDetailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/individual-retrieval.vala b/tests/eds/individual-retrieval.vala
new file mode 100644
index 0000000..e0f8737
--- /dev/null
+++ b/tests/eds/individual-retrieval.vala
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class IndividualRetrievalTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private HashSet<string> _found_individuals;
+
+ public IndividualRetrievalTests ()
+ {
+ base ("IndividualRetrieval");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("singleton individuals", this.test_singleton_individuals);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_singleton_individuals ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ Gee.HashMap<string, Value?> c2 = new Gee.HashMap<string, Value?> ();
+ this._found_individuals = new HashSet<string> (str_hash,
+ str_equal);
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._eds_backend.reset();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("bernie example org");
+ c1.set(Edsf.Persona.email_fields[0], (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ v = Value (typeof (string));
+ v.set_string ("richard m. stallman");
+ c2.set("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("rms example org");
+ c2.set(Edsf.Persona.email_fields[0], (owned) v);
+ this._eds_backend.add_contact (c2);
+
+ this._test_singleton_individuals_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ return false;
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_individuals.size == 2);
+ }
+
+ private async void _test_singleton_individuals_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ assert (i.personas.size == 1);
+ this._found_individuals.add (i.id);
+ }
+
+ if (this._found_individuals.size == 2)
+ {
+ this._main_loop.quit ();
+ }
+
+ assert (removed.size == 0);
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new IndividualRetrievalTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/link-personas.vala b/tests/eds/link-personas.vala
new file mode 100644
index 0000000..44c66a7
--- /dev/null
+++ b/tests/eds/link-personas.vala
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using Folks;
+using Gee;
+
+enum LinkingMethod
+{
+ IM_ADDRESSES,
+ LOCAL_IDS,
+ WEB_SERVICE_ADDRESSES
+}
+
+
+public class LinkPersonasTests : Folks.TestCase
+{
+ private GLib.MainLoop _main_loop;
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private string _persona_fullname_1;
+ private string _persona_fullname_2;
+ private string _im_address_1 = "someone-1 jabber example org";
+ private string _im_address_2 = "someone-2 jabber example org";
+ private bool _linking_fired;
+ private bool _persona_found_1;
+ private bool _persona_found_2;
+ private string _persona_iid_1;
+ private string _persona_iid_2;
+ private HashSet<Persona> _personas;
+ private int _removed_individuals;
+ private string _folks_config_key = "/system/folks/backends/primary_store";
+ private unowned GConf.Client _gconf_client;
+ private Gee.HashMap<string, string> _linking_props;
+ private LinkingMethod _linking_method;
+
+ public LinkPersonasTests ()
+ {
+ base ("LinkPersonasTests");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("test linking personas via IM addresses",
+ this.test_linking_personas_via_im_addresses);
+ this.add_test ("test linking personas via local IDs",
+ this.test_linking_personas_via_local_ids);
+ this.add_test ("test linking personas via web service addresses",
+ this.test_linking_personas_via_web_service_addresses);
+ }
+
+ public override void set_up ()
+ {
+ /* We configure eds as the primary (writeable) store */
+ this._gconf_client = GConf.Client.get_default ();
+ try
+ {
+ GConf.Value val = new GConf.Value (GConf.ValueType.STRING);
+ val.set_string ("eds");
+ this._gconf_client.set (this._folks_config_key, val);
+ }
+ catch (GLib.Error e)
+ {
+ warning ("Couldn't set primary store: %s\n", e.message);
+ }
+
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+
+ try
+ {
+ this._gconf_client.unset (this._folks_config_key);
+ }
+ catch (GLib.Error e)
+ {
+ warning ("Couldn't unset primary store: %s\n", e.message);
+ }
+ }
+
+ public void test_linking_personas_via_im_addresses ()
+ {
+ this._linking_method = LinkingMethod.IM_ADDRESSES;
+ this._test_linking_personas ();
+ }
+
+ public void test_linking_personas_via_local_ids ()
+ {
+ this._linking_method = LinkingMethod.LOCAL_IDS;
+ this._test_linking_personas ();
+ }
+
+ public void test_linking_personas_via_web_service_addresses ()
+ {
+ this._linking_method = LinkingMethod.WEB_SERVICE_ADDRESSES;
+ this._test_linking_personas ();
+ }
+
+ private void _test_linking_personas ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ this._persona_fullname_1 = "persona #1";
+ this._persona_fullname_2 = "persona #2";
+ this._personas = new HashSet<Persona> ();
+ this._removed_individuals = 0;
+ this._persona_found_1 = false;
+ this._persona_found_2 = false;
+ this._linking_fired = false;
+ this._persona_iid_1 = "";
+ this._persona_iid_2 = "";
+
+ this._linking_props = new Gee.HashMap<string, string> ();
+ if (this._linking_method == LinkingMethod.IM_ADDRESSES ||
+ this._linking_method == LinkingMethod.WEB_SERVICE_ADDRESSES)
+ {
+ this._linking_props.set ("prop1", this._im_address_1);
+ this._linking_props.set ("prop2", this._im_address_2);
+ }
+
+ this._test_linking_personas_async ();
+
+ var timer_id = Timeout.add_seconds (8, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ /* Check we get the new individual (containing the linked
+ * personas) and that the previous ones were removed. */
+ assert (this._linking_props.size == 0);
+ assert (this._removed_individuals == 2);
+
+ GLib.Source.remove (timer_id);
+ this._aggregator = null;
+ this._main_loop = null;
+ }
+
+ private async void _test_linking_personas_async ()
+ {
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+
+ PersonaStore pstore = null;
+ foreach (var backend in store.enabled_backends.values)
+ {
+ pstore = backend.persona_stores.get ("local://test");
+ if (pstore != null)
+ break;
+ }
+ assert (pstore != null);
+
+ yield _add_personas (pstore);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ /* Here is how this test is expected to work:
+ * - we start by adding 2 personas
+ * - this should trigger individuals-changed with 2 new individuals
+ * - we ask the IndividualAggregator to link the 2 personas coming
+ * from those individuals
+ * - we wait for a new Individual which contains the linkable
+ * attributes of these 2 personas
+ */
+ private async void _add_personas (PersonaStore pstore)
+ {
+ HashTable<string, Value?> details1 = new HashTable<string, Value?>
+ (str_hash, str_equal);
+ Value? v1;
+ var wsk =
+ Folks.PersonaStore.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES);
+
+ if (this._linking_method == LinkingMethod.IM_ADDRESSES)
+ {
+ v1 = Value (typeof (MultiMap<string, string>));
+ var im_addrs1 = new HashMultiMap<string, string> ();
+ im_addrs1.set ("jabber", this._im_address_1);
+ v1.set_object (im_addrs1);
+ details1.insert ("im-addresses", (owned) v1);
+ }
+ else if (this._linking_method == LinkingMethod.WEB_SERVICE_ADDRESSES)
+ {
+ v1 = Value (typeof (MultiMap<string, string>));
+ var wsa1 = new HashMultiMap<string, string> ();
+ wsa1.set ("twitter", this._im_address_1);
+ v1.set_object (wsa1);
+ details1.insert (wsk, (owned) v1);
+ }
+
+ Value? v2 = Value (typeof (string));
+ v2.set_string (this._persona_fullname_1);
+ details1.insert ("full-name", (owned) v2);
+
+ HashTable<string, Value?> details2 = new HashTable<string, Value?>
+ (str_hash, str_equal);
+
+ Value? v3;
+ if (this._linking_method == LinkingMethod.IM_ADDRESSES)
+ {
+ v3 = Value (typeof (MultiMap<string, string>));
+ var im_addrs2 = new HashMultiMap<string, string> ();
+ im_addrs2.set ("yahoo", this._im_address_2);
+ v3.set_object (im_addrs2);
+ details2.insert ("im-addresses", (owned) v3);
+ }
+ else if (this._linking_method == LinkingMethod.WEB_SERVICE_ADDRESSES)
+ {
+ v3 = Value (typeof (MultiMap<string, string>));
+ var wsa2 = new HashMultiMap<string, string> ();
+ wsa2.set ("lastfm", this._im_address_2);
+ v3.set_object (wsa2);
+ details2.insert (wsk, (owned) v3);
+ }
+
+ Value? v4 = Value (typeof (string));
+ v4.set_string (this._persona_fullname_2);
+ details2.insert ("full-name", (owned)v4);
+
+ try
+ {
+ yield this._aggregator.add_persona_from_details (null,
+ pstore, details1);
+
+ yield this._aggregator.add_persona_from_details (null,
+ pstore, details2);
+ }
+ catch (Folks.IndividualAggregatorError e)
+ {
+ GLib.warning ("[AddPersonaError] add_persona_from_details: %s\n",
+ e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (var i in added)
+ {
+ this._check_personas (i);
+ }
+
+ if (removed.size > 0)
+ this._removed_individuals += (int) removed.size;
+ }
+
+ /* As mentioned in _add_personas here we actually check
+ * for the following events
+ *
+ * - spot the 2 individuals corresponding to the 2 personas we've added
+ * - when we've spotted these 2, we pack them in a list and feed that to
+ * IndividualAggregator#link_personas
+ * - this should fire a new individuals-changed event with a new individual
+ * which should be the linked individual if it contains the linking
+ * properties of the 2 linked personas.
+ */
+ private async void _check_personas (Individual i)
+ {
+ Persona first_persona = null;
+ foreach (var p in i.personas)
+ {
+ first_persona = p;
+ break;
+ }
+
+ if (i.full_name == this._persona_fullname_1 &&
+ this._persona_iid_1 == "")
+ {
+ this._persona_iid_1 = first_persona.iid;
+ this._personas.add (first_persona);
+ if (this._linking_method == LinkingMethod.LOCAL_IDS)
+ {
+ var contact_id1 = ((Edsf.Persona) first_persona).contact_id;
+ this._linking_props.set ("prop1", contact_id1);
+ }
+ }
+ else if (i.full_name == this._persona_fullname_2 &&
+ this._persona_iid_2 == "")
+ {
+ this._persona_iid_2 = first_persona.iid;
+ this._personas.add (first_persona);
+ if (this._linking_method == LinkingMethod.LOCAL_IDS)
+ {
+ var contact_id2 = ((Edsf.Persona) first_persona).contact_id;
+ this._linking_props.set ("prop2", contact_id2);
+ }
+ }
+ else if (i.personas.size > 1)
+ {
+ /* Lets check if it contains all the linking properties */
+ if (this._linking_method == LinkingMethod.IM_ADDRESSES)
+ {
+ foreach (var proto in i.im_addresses.get_keys ())
+ {
+ var addrs = i.im_addresses.get (proto);
+ foreach (var a in addrs)
+ {
+ if (a == this._linking_props.get ("prop1"))
+ {
+ this._linking_props.unset ("prop1");
+ }
+ else if (a == this._linking_props.get ("prop2"))
+ {
+ this._linking_props.unset ("prop2");
+ }
+ }
+ }
+ }
+ else if (this._linking_method == LinkingMethod.LOCAL_IDS)
+ {
+ foreach (var local_id in i.local_ids)
+ {
+ if (local_id == this._linking_props.get ("prop1"))
+ {
+ this._linking_props.unset ("prop1");
+ }
+ else if (local_id == this._linking_props.get ("prop2"))
+ {
+ this._linking_props.unset ("prop2");
+ }
+ }
+ }
+ else if (this._linking_method == LinkingMethod.WEB_SERVICE_ADDRESSES)
+ {
+ foreach (var service in i.web_service_addresses.get_keys ())
+ {
+ var ws_ids = i.web_service_addresses.get (service);
+ foreach (var ws_id in ws_ids)
+ {
+ if (ws_id == this._linking_props.get ("prop1"))
+ {
+ this._linking_props.unset ("prop1");
+ }
+ else if (ws_id == this._linking_props.get ("prop2"))
+ {
+ this._linking_props.unset ("prop2");
+ }
+ }
+ }
+ }
+
+ if (this._linking_props.size == 0)
+ {
+ this._main_loop.quit ();
+ }
+ }
+
+ /* We can try linking the personas only once we've got the
+ * 2 initially created personas. */
+ if (this._personas.size == 2 &&
+ this._linking_fired == false)
+ {
+ this._linking_fired = true;
+ try
+ {
+ yield this._aggregator.link_personas (this._personas);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("link_personas: %s\n", e.message);
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new LinkPersonasTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/name-details.vala b/tests/eds/name-details.vala
new file mode 100644
index 0000000..a47e2f8
--- /dev/null
+++ b/tests/eds/name-details.vala
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class NameDetailsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private int _names_count;
+ private Gee.HashMap<string, Value?> _c1;
+ private Gee.HashMap<string, Value?> _c2;
+
+ public NameDetailsTests ()
+ {
+ base ("NameDetails");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("name details interface", this.test_names);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_names ()
+ {
+ this._c1 = new Gee.HashMap<string, Value?> ();
+ this._c2 = new Gee.HashMap<string, Value?> ();
+ this._names_count = 0;
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._eds_backend.reset ();
+
+ /* FIXME: passing the EContactName would be better */
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ this._c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("bernie");
+ this._c1.set ("nickname", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("Innocenti");
+ this._c1.set ("contact_name_family", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("Bernardo");
+ this._c1.set ("contact_name_given", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("H.");
+ this._c1.set ("contact_name_additional", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("Mr.");
+ this._c1.set ("contact_name_prefixes", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("(sysadmin FSF)");
+ this._c1.set ("contact_name_suffixes", (owned) v);
+ this._eds_backend.add_contact (this._c1);
+
+ v = Value (typeof (string));
+ v.set_string ("richard m. stallman");
+ this._c2.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("Stallman");
+ this._c2.set ("contact_name_family", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("Richard M.");
+ this._c2.set ("contact_name_given", (owned) v);
+ this._eds_backend.add_contact (this._c2);
+
+ this._test_names_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ return false;
+ });
+
+ this._main_loop.run ();
+
+ assert (this._names_count == 2);
+ assert (this._c1.size == 0);
+ assert (this._c2.size == 0);
+ }
+
+ private async void _test_names_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ string s;
+
+ assert (i.personas.size == 1);
+
+ var name = (Folks.NameDetails) i;
+
+ if (i.full_name == "bernie h. innocenti")
+ {
+ assert (name.structured_name.is_empty () == false);
+
+ s = this._c1.get ("full_name").get_string ();
+ assert (name.full_name == s);
+ this._c1.unset ("full_name");
+
+ s = this._c1.get ("nickname").get_string ();
+ assert (name.nickname == s);
+ this._c1.unset ("nickname");
+
+ s = this._c1.get ("contact_name_family").get_string ();
+ assert (name.structured_name.family_name == s);
+ this._c1.unset ("contact_name_family");
+
+ s = this._c1.get ("contact_name_given").get_string ();
+ assert (name.structured_name.given_name == s);
+ this._c1.unset ("contact_name_given");
+
+ s = this._c1.get ("contact_name_additional").get_string ();
+ assert (name.structured_name.additional_names == s);
+ this._c1.unset ("contact_name_additional");
+
+ s = this._c1.get ("contact_name_prefixes").get_string ();
+ assert (name.structured_name.prefixes == s);
+ this._c1.unset ("contact_name_prefixes");
+
+ s = this._c1.get ("contact_name_suffixes").get_string ();
+ assert (name.structured_name.suffixes == s);
+ this._c1.unset ("contact_name_suffixes");
+ }
+ else if (i.full_name == "richard m. stallman")
+ {
+ assert (name.structured_name.is_empty () == false);
+
+ s = this._c2.get ("full_name").get_string ();
+ assert (name.full_name == s);
+ this._c2.unset ("full_name");
+
+ s = this._c2.get ("contact_name_family").get_string ();
+ assert (name.structured_name.family_name == s);
+ this._c2.unset ("contact_name_family");
+
+ s = this._c2.get ("contact_name_given").get_string ();
+ assert (name.structured_name.given_name == s);
+ this._c2.unset ("contact_name_given");
+ }
+
+ this._names_count++;
+ }
+
+ assert (removed.size == 0);
+
+ if (this._c1.size == 0 &&
+ this._c2.size == 0)
+ {
+ this._main_loop.quit ();
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new NameDetailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/persona-store-tests.vala b/tests/eds/persona-store-tests.vala
new file mode 100644
index 0000000..3385158
--- /dev/null
+++ b/tests/eds/persona-store-tests.vala
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class PersonaStoreTests : Folks.TestCase
+{
+ private EdsTest.Backend eds_backend;
+ private HashSet<string> group_flags_received;
+
+ public PersonaStoreTests ()
+ {
+ base ("PersonaStoreTests");
+ this.eds_backend = new EdsTest.Backend ();
+ this.add_test ("persona store tests", this.test_persona_store);
+ }
+
+ public override void set_up ()
+ {
+ this.group_flags_received = new HashSet<string> (str_hash, str_equal);
+ this.eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ }
+
+ public void test_persona_store ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ Gee.HashMap<string, Value?> c2 = new Gee.HashMap<string, Value?> ();
+ var main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this.eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("bernie example org");
+ c1.set (Edsf.Persona.email_fields[0], (owned) v);
+ this.eds_backend.add_contact (c1);
+
+ v = Value (typeof (string));
+ v.set_string ("richard m. stallman");
+ c2.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("rms example org");
+ c2.set (Edsf.Persona.email_fields[0], (owned) v);
+ this.eds_backend.add_contact (c2);
+
+ var backend_store = BackendStore.dup ();
+ backend_store.prepare.begin ((o, r) =>
+ {
+ backend_store.prepare.end (r);
+ });
+ backend_store.backend_available.connect ((b) =>
+ {
+ if (b.name == "eds")
+ {
+ b.persona_store_added.connect ((ps) =>
+ {
+ this.set_up_persona_store (ps);
+ });
+
+ foreach (var store in b.persona_stores.values)
+ {
+ this.set_up_persona_store (store);
+ }
+
+ }
+ });
+
+ backend_store.load_backends ();
+
+ Timeout.add_seconds (3, () =>
+ {
+ main_loop.quit ();
+ return false;
+ });
+
+ main_loop.run ();
+
+ this.eds_backend.tear_down ();
+ }
+
+ private void set_up_persona_store (Folks.PersonaStore store)
+ {
+ store.prepare.begin ((obj, result) =>
+ {
+ try
+ {
+ store.prepare.end (result);
+
+ if (store.can_add_personas != MaybeBool.UNSET)
+ can_add_personas_cb (store, null);
+ else
+ store.notify["can-add-personas"].connect (
+ this.can_add_personas_cb);
+
+ if (store.can_remove_personas != MaybeBool.UNSET)
+ can_remove_personas_cb (store, null);
+ else
+ store.notify["can-remove-personas"].connect (
+ this.can_remove_personas_cb);
+
+ if (store.can_alias_personas != MaybeBool.UNSET)
+ can_alias_personas_cb (store, null);
+ else
+ store.notify["can-alias-personas"].connect (
+ this.can_alias_personas_cb);
+
+ if (store.can_group_personas != MaybeBool.UNSET)
+ can_group_personas_cb (store, null);
+ else
+ store.notify["can-group-personas"].connect (
+ this.can_group_personas_cb);
+ }
+ catch (GLib.Error e)
+ {
+ warning ("Error preparing PersonaStore type: %s, id: %s: " +
+ "'%s'", store.type_id, store.id, e.message);
+ }
+ });
+ }
+
+ private void can_add_personas_cb (GLib.Object s, ParamSpec? p)
+ {
+ assert (s is Edsf.PersonaStore);
+ var store = (Edsf.PersonaStore) s;
+
+ if (store.can_add_personas != MaybeBool.UNSET)
+ {
+ assert (store.can_add_personas == MaybeBool.TRUE);
+
+ store.notify["can-add-personas"].disconnect (
+ this.can_add_personas_cb);
+ }
+ }
+
+ private void can_remove_personas_cb (GLib.Object s, ParamSpec? p)
+ {
+ assert (s is Edsf.PersonaStore);
+ var store = (Edsf.PersonaStore) s;
+
+ if (store.can_remove_personas != MaybeBool.UNSET)
+ {
+ assert (store.can_remove_personas == MaybeBool.TRUE);
+
+ store.notify["can-remove-personas"].disconnect (
+ this.can_remove_personas_cb);
+ }
+ }
+
+ private void can_alias_personas_cb (GLib.Object s, ParamSpec? p)
+ {
+ assert (s is Edsf.PersonaStore);
+ var store = (Edsf.PersonaStore) s;
+
+ if (store.can_alias_personas != MaybeBool.UNSET)
+ {
+ assert (store.can_alias_personas == MaybeBool.FALSE);
+
+ store.notify["can-alias-personas"].disconnect (
+ this.can_alias_personas_cb);
+ }
+ }
+
+ private void can_group_personas_cb (GLib.Object s, ParamSpec? p)
+ {
+ assert (s is Edsf.PersonaStore);
+ var store = (Edsf.PersonaStore) s;
+
+ if (store.can_group_personas != MaybeBool.UNSET)
+ {
+ assert (store.can_group_personas == MaybeBool.FALSE);
+
+ store.notify["can-group-personas"].disconnect (
+ this.can_group_personas_cb);
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new PersonaStoreTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/phone-details.vala b/tests/eds/phone-details.vala
new file mode 100644
index 0000000..dffcc13
--- /dev/null
+++ b/tests/eds/phone-details.vala
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class PhoneDetailsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private int _phones_count;
+ private HashSet<string> _phone_types;
+ private Gee.HashMap<string, Value?> _c1;
+ private Gee.HashMap<string, Value?> _c2;
+
+ public PhoneDetailsTests ()
+ {
+ base ("PhoneDetails");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("phone details interface", this.test_phone_numbers);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_phone_numbers ()
+ {
+ this._phones_count = 0;
+ this._phone_types = new HashSet<string> (str_hash,
+ str_equal);
+ this._c1 = new Gee.HashMap<string, Value?> ();
+ this._c2 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._eds_backend.reset();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ this._c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("123");
+ this._c1.set ("car_phone", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("1234");
+ this._c1.set ("company_phone", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("12345");
+ this._c1.set ("home_phone", (owned) v);
+ this._eds_backend.add_contact (this._c1);
+
+ v = Value (typeof (string));
+ v.set_string ("richard m. stallman");
+ this._c2.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("54321");
+ this._c2.set ("car_phone", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("4321");
+ this._c2.set ("company_phone", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("321");
+ this._c2.set ("home_phone", (owned) v);
+ this._eds_backend.add_contact (this._c2);
+
+ this._test_phone_numbers_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ return false;
+ });
+
+ this._main_loop.run ();
+
+ assert (this._phones_count == 6);
+ assert (this._phone_types.size == 3);
+ assert (this._c1.size == 0);
+ assert (this._c2.size == 0);
+
+ foreach (var pt in this._phone_types)
+ {
+ assert(pt in Edsf.Persona.phone_fields);
+ }
+ }
+
+ private async void _test_phone_numbers_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ unowned Gee.HashMap<string, Value?> contact = null;
+ assert (i.personas.size == 1);
+
+ if (i.full_name == "bernie h. innocenti")
+ {
+ contact = this._c1;
+ }
+ else if (i.full_name == "richard m. stallman")
+ {
+ contact = this._c2;
+ }
+
+ if (contact == null)
+ {
+ continue;
+ }
+
+ contact.unset ("full_name");
+ var phone_numbers = (Folks.PhoneDetails) i;
+ foreach (var p in phone_numbers.phone_numbers)
+ {
+ this._phones_count++;
+ foreach (var t in p.get_parameter_values ("type"))
+ {
+ string? v = null;
+
+ if (t == "CAR")
+ {
+ v = "car_phone";
+ }
+ else if (t == "HOME")
+ {
+ v = "home_phone";
+ }
+ else if (t == "X-EVOLUTION-COMPANY")
+ {
+ v = "company_phone";
+ }
+
+ if (v == null)
+ {
+ continue;
+ }
+
+ this._phone_types.add (v);
+ assert (contact.get (v).get_string () == p.value);
+ contact.unset (v);
+ }
+ }
+ }
+
+ if (this._phones_count == 6)
+ {
+ this._main_loop.quit ();
+ }
+
+ assert (removed.size == 0);
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new PhoneDetailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/postal-address-details.vala b/tests/eds/postal-address-details.vala
new file mode 100644
index 0000000..b322425
--- /dev/null
+++ b/tests/eds/postal-address-details.vala
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using Folks;
+using Gee;
+
+public class PostalAddressDetailsTests : Folks.TestCase
+{
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private EdsTest.Backend _eds_backend;
+ private string _pobox = "12345";
+ private string _locality = "example locality";
+ private string _postalcode = "example postalcode";
+ private string _street = "example street";
+ private string _extended = "example extended address";
+ private string _country = "example country";
+ private string _region = "example region";
+ private PostalAddress _postal_address;
+ private bool _found_postal_address;
+ private string _fullname;
+
+ public PostalAddressDetailsTests ()
+ {
+ base ("PostalAddressDetailsTests");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("test postal address details interface",
+ this.test_postal_address_details_interface);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_postal_address_details_interface ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._fullname = "persona #1";
+ Value? v;
+
+ var types = new HashSet<string> ();
+ types.add (Edsf.Persona.address_fields[0]);
+ this._postal_address = new PostalAddress (
+ this._pobox,
+ this._extended,
+ this._street,
+ this._locality,
+ this._region,
+ this._postalcode,
+ this._country,
+ null, types, "eds_id");
+
+ v = Value (typeof (string));
+ v.set_string (this._fullname);
+ c1.set ("full_name", (owned) v);
+ var types1 = new HashSet<string> ();
+ types1.add (Edsf.Persona.address_fields[0]);
+ var postal_address_copy = new PostalAddress (
+ this._pobox,
+ this._extended,
+ this._street,
+ this._locality,
+ this._region,
+ this._postalcode,
+ this._country,
+ null, types1, "eds_id");
+ v = Value (typeof (PostalAddress));
+ v.set_object (postal_address_copy);
+ c1.set (Edsf.Persona.address_fields[0], (owned) v);
+
+ this._eds_backend.add_contact (c1);
+
+ this._found_postal_address = false;
+
+ this._test_postal_address_details_interface_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_postal_address == true);
+ }
+
+ private async void _test_postal_address_details_interface_async ()
+ {
+
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (var i in added)
+ {
+ if (i.full_name == this._fullname)
+ {
+ foreach (var p in i.postal_addresses)
+ {
+ /* We copy the uid - we don't know it.
+ * Although we could get it from the 1st
+ * personas iid; there is no real need.
+ */
+ this._postal_address.uid = p.uid;
+
+ if (p.equal (this._postal_address))
+ {
+ this._found_postal_address = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new PostalAddressDetailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/remove-persona.vala b/tests/eds/remove-persona.vala
new file mode 100644
index 0000000..476e3af
--- /dev/null
+++ b/tests/eds/remove-persona.vala
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using Folks;
+using Gee;
+
+public class RemovePersonaTests : Folks.TestCase
+{
+ private GLib.MainLoop _main_loop;
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private string _persona_fullname;
+ private bool _persona_removed;
+ private bool _individual_removed;
+ private string _individual_id;
+ private PersonaStore _pstore;
+ private string _persona_id;
+ private Individual _individual;
+ private bool _added_persona = false;
+
+ public RemovePersonaTests ()
+ {
+ base ("RemovePersonaTests");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("test removing personas from e-d-s ",
+ this.test_remove_persona);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ public void test_remove_persona ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ this._persona_fullname = "persona #1";
+
+ this._persona_removed = false;
+ this._individual_removed = false;
+
+ this._test_remove_persona_async ();
+
+ Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._persona_removed == true);
+ assert (this._individual_removed == true);
+ }
+
+ private async void _test_remove_persona_async ()
+ {
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+
+ this._pstore = null;
+ foreach (var backend in store.enabled_backends.values)
+ {
+ this._pstore = backend.persona_stores.get ("local://test");
+ if (this._pstore != null)
+ break;
+ }
+ assert (this._pstore != null);
+
+ this._pstore.notify["is-prepared"].connect (this._notify_pstore_cb);
+ this._try_to_add ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _notify_pstore_cb (Object _pstore, ParamSpec ps)
+ {
+ this._try_to_add ();
+ }
+
+ private void _try_to_add ()
+ {
+ if (this._pstore.is_prepared &&
+ this._added_persona == false)
+ {
+ this._added_persona = true;
+ this._add_persona ();
+ }
+ }
+
+ private async void _add_persona ()
+ {
+ HashTable<string, Value?> details = new HashTable<string, Value?>
+ (str_hash, str_equal);
+ Value? v1 = Value (typeof (string));
+ v1.set_string (this._persona_fullname);
+ details.insert (Folks.PersonaStore.detail_key (PersonaDetail.FULL_NAME),
+ (owned) v1);
+
+ try
+ {
+ yield this._aggregator.add_persona_from_details
+ (null, this._pstore, details);
+ }
+ catch (Folks.IndividualAggregatorError e)
+ {
+ GLib.warning ("[RemovePersonaError] add_persona_from_details: %s\n",
+ e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (var i in added)
+ {
+ if (i.full_name == this._persona_fullname)
+ {
+ this._individual_id = i.id;
+
+ /* Only examine the first persona */
+ foreach (var p in i.personas)
+ {
+ this._persona_id = p.iid;
+ break;
+ }
+
+ this._individual = i;
+ if (this._pstore.personas.has_key (this._persona_id) == true)
+ {
+ this._pstore.personas_changed.connect (this._personas_cb);
+ this._aggregator.remove_individual (this._individual);
+ }
+ }
+ }
+
+ foreach (var i in removed)
+ {
+ if (i.id == this._individual_id)
+ {
+ this._individual_removed = true;
+ }
+ }
+ }
+
+ private void _personas_cb ()
+ {
+ if (this._pstore.personas.has_key (this._persona_id) == false)
+ {
+ this._persona_removed = true;
+ this._main_loop.quit ();
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new RemovePersonaTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/removing-contacts.vala b/tests/eds/removing-contacts.vala
new file mode 100644
index 0000000..50009f9
--- /dev/null
+++ b/tests/eds/removing-contacts.vala
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class RemovingContactsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _removed;
+ private bool _added;
+
+ public RemovingContactsTests ()
+ {
+ base ("IndividualRetrieval");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("removing contact", this.test_removal);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_removal ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._added = false;
+ this._removed = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_removal_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ return false;
+ });
+
+ this._main_loop.run ();
+
+ assert (this._added == true);
+ assert (this._removed == true);
+ }
+
+ private async void _test_removal_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+ this._added = true;
+ assert (name.full_name == "bernie h. innocenti");
+ this._eds_backend.remove_contact (0);
+ }
+
+ foreach (Individual i in removed)
+ {
+ var name = (Folks.NameDetails) i;
+ assert (name.full_name == "bernie h. innocenti");
+ this._removed = true;
+ this._main_loop.quit ();
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new RemovingContactsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-avatar.vala b/tests/eds/set-avatar.vala
new file mode 100644
index 0000000..d12eaa7
--- /dev/null
+++ b/tests/eds/set-avatar.vala
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetAvatarTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+ private File _avatar;
+
+ public SetAvatarTests ()
+ {
+ base ("SetAvatar");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting avatar on e-d-s persona", this.test_set_avatar);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_avatar ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ var avatar_path = Environment.get_variable ("AVATAR_FILE_PATH");
+ this._avatar = File.new_for_path (avatar_path);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_avatar_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_avatar_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["avatar"].connect (this._notify_avatar_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ ((AvatarDetails) p).avatar = this._avatar;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_avatar_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ var name = (Folks.NameDetails) i;
+ if (name.full_name == "bernie h. innocenti")
+ {
+ uint8[] content_a;
+ uint8[] content_b;
+
+ try
+ {
+ i.avatar.load_contents (null, out content_a);
+ this._avatar.load_contents (null, out content_b);
+
+ if (((string) content_a) == ((string) content_b))
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Couldn't compare avatars: %s\n", e.message);
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetAvatarTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-emails.vala b/tests/eds/set-emails.vala
new file mode 100644
index 0000000..204a9d4
--- /dev/null
+++ b/tests/eds/set-emails.vala
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetEmailsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+
+ public SetEmailsTests ()
+ {
+ base ("SetEmails");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting emails on e-d-s persona", this.test_set_emails);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_emails ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_emails_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_emails_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["email-addresses"].connect (this._notify_emails_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ var emails = new HashSet<FieldDetails> ();
+ var email_1 = new FieldDetails ("bernie example org");
+ email_1.set_parameter ("type", "OTHER");
+ emails.add (email_1);
+ ((EmailDetails) p).email_addresses = emails;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_emails_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ foreach (var e in i.email_addresses)
+ {
+ if (e.value == "bernie example org")
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetEmailsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-full-name.vala b/tests/eds/set-full-name.vala
new file mode 100644
index 0000000..8578bc7
--- /dev/null
+++ b/tests/eds/set-full-name.vala
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetFullNameTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+
+ public SetFullNameTests ()
+ {
+ base ("SetFullName");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting full name on e-d-s persona",
+ this.test_set_full_name);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_full_name ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_full_name_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_full_name_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["full-name"].connect (this._notify_full_name_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ ((NameDetails) p).full_name = "bernie";
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_full_name_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ var name = (Folks.NameDetails) i;
+ if (name.full_name == "bernie")
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetFullNameTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-im-addresses.vala b/tests/eds/set-im-addresses.vala
new file mode 100644
index 0000000..4fc44f7
--- /dev/null
+++ b/tests/eds/set-im-addresses.vala
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetIMAddressesTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+
+ public SetIMAddressesTests ()
+ {
+ base ("SetIMAddresses");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting im addresses on e-d-s persona",
+ this.test_set_im_addresses);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_im_addresses ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_im_addresses_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_im_addresses_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["im-addresses"].connect (this._notify_im_addresses_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ var im_addrs = new HashMultiMap<string, string> ();
+ im_addrs.set ("jabber", "bernie example org");
+ ((ImDetails) p).im_addresses = im_addrs;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_im_addresses_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ foreach (var proto in i.im_addresses.get_keys ())
+ {
+ foreach (var im in i.im_addresses.get (proto))
+ {
+ if (im == "bernie example org")
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetIMAddressesTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-notes.vala b/tests/eds/set-notes.vala
new file mode 100644
index 0000000..43cad5c
--- /dev/null
+++ b/tests/eds/set-notes.vala
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetNotesTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+ private string _note = "This is a note.";
+
+ public SetNotesTests ()
+ {
+ base ("SetNotes");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting notes name on e-d-s persona",
+ this.test_set_notes);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_notes ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_full_name_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_full_name_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["notes"].connect (this._notify_notes_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ var notes = new HashSet<Note> ();
+ var note = new Note(this._note);
+ notes.add (note);
+ ((NoteDetails) p).notes = notes;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_notes_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ foreach (var note in i.notes)
+ {
+ if (note.content == this._note)
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetNotesTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-phones.vala b/tests/eds/set-phones.vala
new file mode 100644
index 0000000..df4aa6f
--- /dev/null
+++ b/tests/eds/set-phones.vala
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetPhonesTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+
+ public SetPhonesTests ()
+ {
+ base ("SetPhones");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting phones on e-d-s persona", this.test_set_phones);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_phones ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_phones_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_phones_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["phone-numbers"].connect (this._notify_phones_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ var phones = new HashSet<FieldDetails> ();
+ var phone_1 = new FieldDetails ("1234");
+ phone_1.set_parameter ("type", "HOME");
+ phones.add (phone_1);
+ ((PhoneDetails) p).phone_numbers = phones;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_phones_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ foreach (var p in i.phone_numbers)
+ {
+ if (p.value == "1234")
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetPhonesTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-postal-addresses.vala b/tests/eds/set-postal-addresses.vala
new file mode 100644
index 0000000..dc9356c
--- /dev/null
+++ b/tests/eds/set-postal-addresses.vala
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetPostalAddressesTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+ private PostalAddress _postal;
+
+ public SetPostalAddressesTests ()
+ {
+ base ("SetPostalAddresses");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting postal addresss on e-d-s persona",
+ this.test_set_postal_addresses);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_postal_addresses ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+ var types = new HashSet<string> ();
+ types.add ("address_other");
+ this._postal = new PostalAddress ("123", "extension", "street",
+ "locality", "region", "postal code", "country", "",
+ types, "123");
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_postal_addresses_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_postal_addresses_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["postal-addresses"].connect (
+ this._notify_postal_addresses_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ var addresses = new HashSet<PostalAddress> ();
+ var types = new HashSet<string> ();
+ types.add ("address_other");
+ var addr1 = new PostalAddress ("123", "extension", "street",
+ "locality", "region", "postal code", "country", "format",
+ types, "123");
+ addresses.add (addr1);
+ ((PostalAddressDetails) p).postal_addresses = addresses;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_postal_addresses_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ foreach (var p in i.postal_addresses)
+ {
+ p.uid = this._postal.uid;
+ if (p.equal (this._postal))
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetPostalAddressesTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/set-structured-name.vala b/tests/eds/set-structured-name.vala
new file mode 100644
index 0000000..31f7331
--- /dev/null
+++ b/tests/eds/set-structured-name.vala
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetStructuredNameTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+ private StructuredName _sname;
+
+ public SetStructuredNameTests ()
+ {
+ base ("SetStructuredName");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("setting structured name on e-d-s persona",
+ this.test_set_structured_name);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_set_structured_name ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ this._sname = new StructuredName.simple ("Innocenti", "Bernie");
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_structured_name_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_set_structured_name_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["structured-name"].connect (
+ this._notify_structured_name_cb);
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ ((NameDetails) p).structured_name = this._sname;
+ }
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private void _notify_structured_name_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ if (i.structured_name.equal (this._sname))
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new SetStructuredNameTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/eds/updating-contacts.vala b/tests/eds/updating-contacts.vala
new file mode 100644
index 0000000..b03c5c4
--- /dev/null
+++ b/tests/eds/updating-contacts.vala
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class UpdatingContactsTests : Folks.TestCase
+{
+ private EdsTest.Backend _eds_backend;
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+
+ public UpdatingContactsTests ()
+ {
+ base ("UpdatingContacts");
+
+ this._eds_backend = new EdsTest.Backend ();
+
+ this.add_test ("updating contact", this.test_updates);
+ }
+
+ public override void set_up ()
+ {
+ this._eds_backend.set_up ();
+ }
+
+ public override void tear_down ()
+ {
+ this._eds_backend.tear_down ();
+ }
+
+ void test_updates ()
+ {
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("bernie h. innocenti");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_updates_async ();
+
+ Timeout.add_seconds (5, () => {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void _test_updates_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed.connect
+ (this._individuals_changed_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _individuals_changed_cb
+ (Set<Individual> added,
+ Set<Individual> removed,
+ string? message,
+ Persona? actor,
+ GroupDetails.ChangeReason reason)
+ {
+ foreach (Individual i in added)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "bernie h. innocenti")
+ {
+ i.notify["full-name"].connect (this._notify_full_name_cb);
+ this._found_before_update = true;
+ this._update_contact ();
+ }
+ }
+
+ assert (removed.size == 0);
+ }
+
+ private async void _update_contact ()
+ {
+ Gee.HashMap<string, Value?> updated_data =
+ new Gee.HashMap<string, Value?> ();
+ Value? v;
+
+ v = Value (typeof (string));
+ v.set_string ("bernie innocenti");
+ updated_data.set("full_name", (owned) v);
+ yield this._eds_backend.update_contact (0, updated_data);
+ }
+
+ private void _notify_full_name_cb (Object individual_obj, ParamSpec ps)
+ {
+ Folks.Individual i = (Folks.Individual) individual_obj;
+ var name = (Folks.NameDetails) i;
+ if (name.full_name == "bernie innocenti")
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ TestSuite root = TestSuite.get_root ();
+ root.add_suite (new UpdatingContactsTests ().get_suite ());
+
+ Test.run ();
+
+ return 0;
+}
diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am
index 1e1c595..5f7a4dd 100644
--- a/tests/lib/Makefile.am
+++ b/tests/lib/Makefile.am
@@ -11,11 +11,16 @@ if ENABLE_TRACKER
SUBDIRS += tracker
endif
+if ENABLE_EDS
+SUBDIRS += eds
+endif
+
DIST_SUBDIRS = \
key-file \
telepathy \
libsocialweb \
tracker \
+ eds \
$(NULL)
noinst_LTLIBRARIES = libfolks-test.la
diff --git a/tests/lib/eds/Makefile.am b/tests/lib/eds/Makefile.am
new file mode 100644
index 0000000..1c8346c
--- /dev/null
+++ b/tests/lib/eds/Makefile.am
@@ -0,0 +1,56 @@
+VALAFLAGS += \
+ --library=eds-test \
+ --header=eds-test.h \
+ --vapidir=$(top_srcdir)/folks \
+ --vapidir=$(top_srcdir)/backends/eds/lib \
+ --vapidir=$(top_srcdir)/backends/eds/vapi \
+ --vapidir=. \
+ --pkg gobject-2.0 \
+ --pkg gio-2.0 \
+ --pkg gee-1.0 \
+ --pkg folks \
+ --pkg libebook-1.2 \
+ --pkg libedataserver-1.2 \
+ --pkg libxml-2.0 \
+ --pkg folks-eds \
+ $(NULL)
+
+noinst_LTLIBRARIES = libeds-test.la
+
+libeds_test_la_SOURCES = \
+ backend.vala \
+ $(NULL)
+
+libeds_test_la_CFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(EBOOK_CFLAGS) \
+ $(EDATASERVER_CFLAGS) \
+ -I$(top_srcdir)/backends/eds/lib \
+ $(NULL)
+
+libeds_test_la_LIBADD = \
+ $(top_builddir)/folks/libfolks.la \
+ $(top_builddir)/backends/eds/libfolks-backend-eds.la \
+ $(EBOOK_LIBS) \
+ $(EDATASERVER_LIBS) \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ eds-test.vapi \
+ eds-test.h \
+ $(NULL)
+
+EXTRA_DIST = \
+ eds-test.vapi \
+ eds-test.h \
+ $(NULL)
+
+GITIGNOREFILES = \
+ $(libeds_test_la_SOURCES:.vala=.c) \
+ libeds_test_la_vala.stamp \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/tests/lib/eds/backend.vala b/tests/lib/eds/backend.vala
new file mode 100644
index 0000000..bf32db0
--- /dev/null
+++ b/tests/lib/eds/backend.vala
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using E;
+using Folks;
+using Random;
+
+errordomain EdsTest.BackendSetupError
+{
+ FETCH_SOURCE_GROUP_FAILED,
+ OPENING_FAILED,
+ ADD_CONTACT_FAILED,
+ ADD_TO_SOURCE_GROUP_FAILED,
+}
+
+public class EdsTest.Backend
+{
+ private string _addressbook_name;
+ private E.BookClient _addressbook;
+ private GLib.List<string> _e_contacts;
+ private GLib.List<Gee.HashMap<string, Value?>> _contacts;
+ E.SourceGroup _source_group;
+ E.Source _source;
+
+ public Backend ()
+ {
+ this._contacts = new GLib.List<Gee.HashMap<string, Value?>> ();
+ this._e_contacts = new GLib.List<string> ();
+ }
+
+ public void add_contact (owned Gee.HashMap<string, Value?> c)
+ {
+ this._contacts.prepend (c);
+ }
+
+ public async void update_contact (int contact_pos,
+ owned Gee.HashMap<string, Value?> updated_data)
+ {
+ var uid = this._e_contacts.nth_data (contact_pos);
+ E.Contact contact;
+ try
+ {
+ yield this._addressbook.get_contact (uid, out contact);
+ this._set_contact_fields (contact, updated_data);
+ yield this._addressbook.modify_contact (contact);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Couldn't update contact\n");
+ }
+ }
+
+ public async void remove_contact (int contact_pos)
+ {
+ var uid = this._e_contacts.nth_data (contact_pos);
+ E.Contact contact;
+ try
+ {
+ yield this._addressbook.get_contact (uid, out contact);
+ yield this._addressbook.remove_contact (contact);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Couldn't remove contact\n");
+ }
+ }
+
+ public void reset ()
+ {
+ this._contacts = new GLib.List<Gee.HashMap<string, Value?>> ();
+ this._e_contacts = new GLib.List<string> ();
+ }
+
+ /* Create a temporary addressbook */
+ public void set_up ()
+ {
+ try
+ {
+ this._prepare_source ();
+ this._addressbook = new BookClient (this._source);
+ this._addressbook.open_sync (false, null);
+ this._addressbook_name =
+ this._addressbook.get_source ().peek_name ();
+ Environment.set_variable ("FOLKS_BACKEND_EDS_USE_ADDRESSBOOKS",
+ this._addressbook_name, true);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Unable to create test data: %s\n", e.message);
+ }
+ }
+
+ private void _prepare_source ()
+ {
+ var base_uri = "local:";
+ this._source_group = new E.SourceGroup ("Test", base_uri);
+
+ this._source = new E.Source ("Test", "local://test");
+ if (this._source_group.add_source (this._source, -1))
+ {
+ try
+ {
+ SourceList sl;
+ BookClient.get_sources (out sl);
+ sl.add_group (this._source_group, 0);
+ sl.sync ();
+ }
+ catch (GLib.Error e)
+ {
+ // XXX
+ }
+ }
+ }
+
+ public async void commit_contacts_to_addressbook ()
+ {
+ this._contacts.reverse ();
+ foreach (var c in this._contacts)
+ {
+ E.Contact contact = new E.Contact ();
+
+ this._set_contact_fields (contact, c);
+
+ try
+ {
+ string added_uid;
+ yield this._addressbook.add_contact (contact,
+ out added_uid);
+ this._e_contacts.prepend ((owned) added_uid);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Couldn't add contact: %s\n",
+ e.message);
+ }
+ }
+ this._e_contacts.reverse ();
+ }
+
+ private void _set_contact_fields (E.Contact contact,
+ Gee.HashMap<string, Value?> c)
+ {
+ bool added_contact_name = false;
+ E.ContactName contact_name = new E.ContactName ();
+ string contact_field_name = "contact_name";
+ int min_len = contact_field_name.length;
+
+ foreach (var k in c.keys)
+ {
+ if (k.length > min_len && k.slice(0, min_len) == contact_field_name)
+ {
+ var v = c.get (k).get_string ();
+ if (k.index_of ("family") >= 0)
+ {
+ contact_name.family = v;
+ }
+ else if (k.index_of ("given") >= 0)
+ {
+ contact_name.given = v;
+ }
+ else if (k.index_of ("additional") >= 0)
+ {
+ contact_name.additional = v;
+ }
+ else if (k.index_of ("prefixes") >= 0)
+ {
+ contact_name.prefixes = v;
+ }
+ else if (k.index_of ("suffixes") >= 0)
+ {
+ contact_name.suffixes = v;
+ }
+
+ added_contact_name = true;
+ }
+ else if (k == "avatar")
+ {
+ var v = c.get (k).get_string ();
+ uint8[] photo_content;
+ var file = File.new_for_path (v);
+
+ try
+ {
+ file.load_contents (null, out photo_content);
+
+ var cp = new ContactPhoto ();
+ cp.type = ContactPhotoType.INLINED;
+ cp.set_inlined (photo_content);
+
+ contact.set (E.Contact.field_id ("photo"), cp);
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("\n\nCan't load avatar %s: %s\n\n", v,
+ e.message);
+ }
+ }
+ else if (k == "im_addresses")
+ {
+ var v = c.get (k).get_string ();
+ var addresses = this._parse_addrs (v);
+ foreach (var addr in addresses.keys)
+ {
+ var proto = addresses.get (addr);
+ contact.set (E.Contact.field_id (proto), addr);
+ }
+ }
+ else if (k == Edsf.Persona.address_fields[0])
+ {
+ var pa = (PostalAddress) c.get (k).get_object ();
+ var address = new E.ContactAddress ();
+ address.po = pa.po_box;
+ address.ext = pa.extension;
+ address.street = pa.street;
+ address.locality = pa.locality;
+ address.region = pa.region;
+ address.code = pa.postal_code;
+ address.country = pa.country;
+ address.address_format = pa.address_format;
+
+ contact.set (E.Contact.field_id (k), address);
+ }
+ else
+ {
+ var v = c.get (k).get_string ();
+ contact.set (E.Contact.field_id (k), v);
+ }
+ }
+ if (added_contact_name)
+ {
+ contact.set (E.Contact.field_id ("name"), contact_name);
+ }
+ }
+
+ public void tear_down ()
+ {
+ Environment.set_variable ("FOLKS_BACKEND_EDS_USE_ADDRESSBOOKS",
+ "", true);
+
+ try
+ {
+ var ret = this._addressbook.remove_sync (null);
+ if (ret == false)
+ {
+ GLib.warning ("remove() addressbook returned false on %s\n",
+ this._addressbook_name);
+ }
+
+ this._addressbook = null;
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Unable to remove addressbook %s because: %s\n",
+ this._addressbook_name, e.message);
+ }
+ }
+
+ private Gee.HashMap<string, string> _parse_addrs (string addr_s)
+ {
+ Gee.HashMap<string, string> ret = new Gee.HashMap<string, string> ();
+ string[] im_addrs = addr_s.split (",");
+
+ foreach (var a in im_addrs)
+ {
+ string[] info = a.split ("#");
+ string proto = info[0];
+ string addr = info[1];
+
+ ret.set ((owned) addr, (owned) proto);
+ }
+
+ return ret;
+ }
+}
\ No newline at end of file
diff --git a/tests/tools/eds.sh b/tests/tools/eds.sh
new file mode 100644
index 0000000..852ba2b
--- /dev/null
+++ b/tests/tools/eds.sh
@@ -0,0 +1,25 @@
+#
+# Helper functions to start your own e-d-s instance. This depends
+# on you having your own D-Bus session bus started (first).
+#
+#
+# Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+eds_tmpdir=$(mktemp -d)
+
+eds_init_settings () {
+ export XDG_DATA_HOME=$eds_tmpdir/.local
+ export XDG_CACHE_HOME=$eds_tmpdir/.cache
+ export XDG_CONFIG_HOME=$eds_tmpdir/.config
+}
+
+# This should be called on INT TERM and EXIT
+eds_stop () {
+ rm -rf $eds_tmpdir
+ rm -rf $eds_tmpdir
+}
+
diff --git a/tests/tools/with-session-bus-eds.sh b/tests/tools/with-session-bus-eds.sh
new file mode 100755
index 0000000..b5cab54
--- /dev/null
+++ b/tests/tools/with-session-bus-eds.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# with-session-bus-eds.sh - run a program with a temporary D-Bus session daemon
+#
+# interesting bits have been move into dbus to permit reusability
+#
+# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+
+cur_dir=`dirname $0`
+
+. $cur_dir"/dbus-session.sh"
+. $cur_dir"/eds.sh"
+
+dbus_parse_args $@
+while test "z$1" != "z--"; do
+ shift
+done
+shift
+if test "z$1" = "z"; then dbus_usage; fi
+
+cleanup ()
+{
+ eds_stop
+ dbus_stop
+}
+
+trap cleanup INT HUP TERM
+
+eds_init_settings
+dbus_init 0
+
+dbus_start
+
+e=0
+"$@" || e=$?
+
+trap - INT HUP TERM
+cleanup
+
+exit $e
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]