/* * Copyright (C) 2008-2009 Patrick Ohly * Copyright (C) 2009 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "ActiveSyncSource.h" #include "ActiveSyncCalendarSource.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef ENABLE_UNIT_TESTS # include # include #endif #include #include SE_BEGIN_CXX static SyncSource *createSource(const SyncSourceParams ¶ms) { SourceType sourceType = SyncSource::getSourceType(params.m_nodes); bool isMe; isMe = sourceType.m_backend == "ActiveSync Address Book"; if (isMe) { return #ifdef ENABLE_ACTIVESYNC new ActiveSyncContactSource(params) #else RegisterSyncSource::InactiveSource(params) #endif ; } isMe = sourceType.m_backend == "ActiveSync Events"; if (isMe) { return #ifdef ENABLE_ACTIVESYNC new ActiveSyncCalendarSource(params, EAS_ITEM_CALENDAR) #else RegisterSyncSource::InactiveSource(params) #endif ; } isMe = sourceType.m_backend == "ActiveSync Todos"; if (isMe) { return #ifdef ENABLE_ACTIVESYNC new ActiveSyncCalFormatSource(params, EAS_ITEM_TODO) #else RegisterSyncSource::InactiveSource(params) #endif ; } isMe = sourceType.m_backend == "ActiveSync Memos"; if (isMe) { return #ifdef ENABLE_ACTIVESYNC new ActiveSyncCalFormatSource(params, EAS_ITEM_JOURNAL) #else RegisterSyncSource::InactiveSource(params) #endif ; } return NULL; } static RegisterSyncSource registerMe("ActiveSync", #ifdef ENABLE_ACTIVESYNC true, #else false, #endif createSource, "ActiveSync Address Book = eas-contacts\n" "ActiveSync Events = eas-events\n" "ActiveSync Todos = eas-todos\n" "ActiveSync Memos = eas-memos", Values() + (Aliases("ActiveSync Address Book") + "eas-contacts") + (Aliases("ActiveSync Events") + "eas-events") + (Aliases("ActiveSync Todos") + "eas-todos") + (Aliases("ActiveSync Memos") + "eas-memos")); #ifdef ENABLE_ACTIVESYNC #ifdef ENABLE_UNIT_TESTS class ActiveSyncsTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ActiveSyncsTest); CPPUNIT_TEST(testInstantiate); CPPUNIT_TEST_SUITE_END(); protected: void testInstantiate() { boost::shared_ptr source; source.reset(SyncSource::createTestingSource("contacts", "ActiveSync Address Book", true)); source.reset(SyncSource::createTestingSource("events", "ActiveSync Events", true)); source.reset(SyncSource::createTestingSource("todos", "ActiveSync Todos", true)); source.reset(SyncSource::createTestingSource("memos", "ActiveSync Memos", true)); } }; SYNCEVOLUTION_TEST_SUITE_REGISTRATION(ActiveSyncsTest); #endif // ENABLE_UNIT_TESTS namespace { #if 0 } #endif /** * Takes all existing items in the source and writes them into the file, * separated by a blank line. beginSync() with the previous sync key was * already called. * * Used for testing and thus should better not rely on cached information, * but ActiveSync doesn't offer an independent "list and/or retrieve all items" * operation. Using the cached information implies that we won't find bugs in * the handling of that information. */ static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::string &file, bool forceBaseReadItem) { ActiveSyncSource &eassource = static_cast(source); ofstream out(file.c_str()); // find all ActiveSync server IDs: in ActiveSyncCalendarSource, // each server ID might appear multiple times, once for each // recurrence associated with it std::set easids; BOOST_FOREACH (const std::string &luid, eassource.getAllItems()) { // slight hack: we know that luids in ActiveSyncSource base // class pass through this method unmodified, so no need to // avoid it StringPair ids = ActiveSyncCalendarSource::splitLUID(luid); easids.insert(ids.first); } BOOST_FOREACH(const std::string &easid, easids) { std::string item; if (forceBaseReadItem) { // This bypasses the more specialized // ActiveSyncCalendarSource::readItem(), which helps // reveal potential bugs in it. However, it depends on a // working Fetch operation in the ActiveSync server, which // Google doesn't seem to provide (404 error). eassource.ActiveSyncSource::readItem(easid, item); } else { // Normal readItem() works with Google by using the cached // item. However, the source must have done a beginSync() // with empty sync key, because otherwise the cache is // not guaranteed to be complete. eassource.readItem(easid, item); } out << item << '\n'; if (!boost::ends_with(item, "\n")) { out << '\n'; } } return 0; } static TestingSyncSource *createEASSource(const ClientTestConfig::createsource_t &create, ClientTest &client, const std::string &clientID, int source, bool isSourceA) { std::auto_ptr res(create(client, clientID, source, isSourceA)); // Mangle username: if the base username in the config is account // "foo", then source B uses "foo_B", because otherwise it'll end // up sharing change tracking with source A. if (!isSourceA) { ActiveSyncSource *eassource = static_cast(res.get()); std::string account = eassource->getSyncConfig().getSyncUser().toString(); account += "_B"; eassource->getSyncConfig().setSyncUsername(account, true); } if (res->getDatabaseID().empty()) { return res.release(); } else { // sorry, no database SE_LOG_ERROR(NULL, "cannot create EAS datastore for database %s, check config", res->getDatabaseID().c_str()); return NULL; } } // common settings for all kinds of data static void updateConfigEAS(const RegisterSyncSourceTest */* me */, ClientTestConfig &config, EasItemType type) { // cannot run tests involving a second database: // wrap orginal source creation, set default database for // database #0 and refuse to return a source for database #1 config.m_createSourceA = boost::bind(createEASSource, config.m_createSourceA, _1, _2, _3, _4); config.m_createSourceB = boost::bind(createEASSource, config.m_createSourceB, _1, _2, _3, _4); config.m_dump = boost::bind(DumpItems, _1, _2, _3, type == EAS_ITEM_CONTACT || // need to read from our cache for Google Calendar, // because it does not support Fetch strcmp(getEnv("CLIENT_TEST_SERVER", ""), "googleeas") ); config.m_sourceLUIDsAreVolatile = true; // TODO: find out how ActiveSync/Exchange handle children without parent; // at the moment, the child is stored as if it was a stand-alone event // and the RECURRENCE-ID is lost (BMC #22831). config.m_linkedItemsRelaxedSemantic = false; } static class ActiveSyncContactTest : public RegisterSyncSourceTest { public: ActiveSyncContactTest() : RegisterSyncSourceTest("eas_contact", // name of test => Client::Source::eas_contact" "eds_contact" // name of test cases: inherit from EDS, override below ) {} virtual void updateConfig(ClientTestConfig &config) const { // override default eds_contact test config config.m_type = "eas-contacts"; // TODO: provide comprehensive set of vCard 3.0 contacts as they are understood by the ActiveSync library // config.testcases = "testcases/eas_contact.vcf"; updateConfigEAS(this, config, EAS_ITEM_CONTACT); } } ActiveSyncContactTest; static class ActiveSyncEventTest : public RegisterSyncSourceTest { public: ActiveSyncEventTest() : RegisterSyncSourceTest("eas_event", "eds_event") {} virtual void updateConfig(ClientTestConfig &config) const { config.m_type = "eas-events"; updateConfigEAS(this, config, EAS_ITEM_CALENDAR); } } ActiveSyncEventTest; static class ActiveSyncTodoTest : public RegisterSyncSourceTest { public: ActiveSyncTodoTest() : RegisterSyncSourceTest("eas_task", "eds_task") {} virtual void updateConfig(ClientTestConfig &config) const { config.m_type = "eas-todos"; updateConfigEAS(this, config, EAS_ITEM_TODO); } } ActiveSyncTodoTest; static class ActiveSyncMemoTest : public RegisterSyncSourceTest { public: ActiveSyncMemoTest() : RegisterSyncSourceTest("eas_memo", "eds_memo") {} virtual void updateConfig(ClientTestConfig &config) const { config.m_type = "eas-memos"; updateConfigEAS(this, config, EAS_ITEM_JOURNAL); } } ActiveSyncMemoTest; } // anonymous namespace #endif // ENABLE_ACTIVESYNC SE_END_CXX