buteo testing: enable buteo testing in client-test
To enable it in configuration, use '--enable-buteo-tests'. To test client-test with buteo to do sync, make sure the environment variable 'CLIENT_TEST_BUTEO=1' is set. Three main steps to support buteo testing in client-test, 1) pre-run: storage preparation, clean up buteo logging files and set corresponding keys in meego-sync-conf.xml. For qtcontacts, switch backend database files for each client; For calendar/todo/note, specify different notebook names for each client. 2) run: re-implement ClientTest.doSync function, which dbus-calls 'msyncd', the dbus daemon of buteo to do sync. Listen to needed signals to track its status. 3) post-run: collect its status and summarize its statistics and convert to internal sync report. Buteo doesn't support explicit slow-sync mode and refresh- from-server mode. Add two workarounds for them: For slow-sync mode, wipe out anchors; For refresh-from-server, wipe out anchors and clean all local data and do two-way sync. To enable buteo testing in your environment, you have to: 1) Add read/write privilege for the directory /etc/sync for current testing user 2) To test one remote server, make sure the profile xml is put in $HOME/.sync/profiles/sync. The name of the profile xml should be set as the server name.
This commit is contained in:
parent
d3284d72a8
commit
c7e47d8d3c
|
@ -80,6 +80,17 @@ AC_ARG_ENABLE(integration-tests,
|
|||
[enables tests outside of the library (can be used together with normal builds of the library)]),
|
||||
enable_integration_tests="$enableval", enable_integration_tests="no")
|
||||
|
||||
AC_ARG_ENABLE(buteo-tests,
|
||||
AS_HELP_STRING([--enable-buteo-tests],
|
||||
[enables tests for Buteo sync framework. Not enabled when neither '--enable-unit-tests' nor '--enable-integration-tests' is specified]),
|
||||
[ if test "$enable_unit_tests" = "yes" || test "$enable_integration_tests" = "yes" ; then
|
||||
enable_buteo_tests="$enableval"
|
||||
else
|
||||
enable_buteo_tests="no"
|
||||
fi], enable_buteo_tests="no")
|
||||
PKG_CHECK_MODULES(BUTEOSYNCPROFILE, [syncprofile], HAVE_SYNCPROFILE=yes, HAVE_SYNCPROFILE=no)
|
||||
PKG_CHECK_MODULES(BUTEOSYNCCOMMON, [synccommon], HAVE_SYNCCOMMON=yes, HAVE_SYNCCOMMON=no)
|
||||
|
||||
AC_ARG_ENABLE(static-cxx,
|
||||
AS_HELP_STRING([--enable-static-cxx],
|
||||
[build executables which contain libstdc++ instead of requiring suitable libstdc++.so to run]),
|
||||
|
@ -122,8 +133,17 @@ fi
|
|||
if test "$enable_integration_tests" = "yes"; then
|
||||
AC_DEFINE(ENABLE_INTEGRATION_TESTS, 1, [enable integration tests inside the final library])
|
||||
fi
|
||||
if test "$enable_buteo_tests" = "yes"; then
|
||||
AC_DEFINE(ENABLE_BUTEO_TESTS, 1, [enable buteo tests])
|
||||
need_qt_modules="$need_qt_modules dbus xml"
|
||||
AC_PATH_PROG(SQLITE3, sqlite3)
|
||||
if test -z "$SQLITE3"; then
|
||||
AC_ERROR([sqlite3 not found, is required for buteo testing])
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_UNIT_TESTS], [test "$enable_unit_tests" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_TESTING], [test "$enable_unit_tests" = "yes" || test "$enable_integration_tests" = "yes" ])
|
||||
AM_CONDITIONAL([ENABLE_BUTEO_TESTS], [test "$enable_buteo_tests" = "yes"])
|
||||
|
||||
if test $enable_static_cxx == "yes"; then
|
||||
LIBS="$LIBS -L."
|
||||
|
@ -413,6 +433,10 @@ AC_SUBST(KEYRING_LIBS)
|
|||
AC_SUBST(LIBNOTIFY_CFLAGS)
|
||||
AC_SUBST(LIBNOTIFY_LIBS)
|
||||
AC_SUBST(LIBEXECDIR)
|
||||
AC_SUBST(BUTEOSYNCPROFILE_LIBS)
|
||||
AC_SUBST(BUTEOSYNCPROFILE_CFLAGS)
|
||||
AC_SUBST(BUTEOSYNCCOMMON_LIBS)
|
||||
AC_SUBST(BUTEOSYNCCOMMON_CFLAGS)
|
||||
|
||||
DBUS_SERVICES_DIR="${datadir}/dbus-1/services"
|
||||
AC_SUBST(DBUS_SERVICES_DIR)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
include $(top_srcdir)/m4-repo/autotroll.mk
|
||||
|
||||
BACKENDS = @BACKENDS@
|
||||
|
||||
# start with building nothing and add more targets below
|
||||
|
@ -209,6 +211,12 @@ client_test_SOURCES = \
|
|||
$(CORE_SOURCES)
|
||||
nodist_client_test_SOURCES = ../test/test.cpp
|
||||
|
||||
if ENABLE_BUTEO_TESTS
|
||||
client_test_SOURCES += client-test-buteo.h
|
||||
client_test_SOURCES += client-test-buteo.cpp
|
||||
nodist_client_test_SOURCES += client-test-buteo.moc.cpp
|
||||
endif
|
||||
|
||||
# list of test file base files
|
||||
#
|
||||
# Generated files (testcases/ical20.ics.funambol.tem) are derived from
|
||||
|
@ -235,10 +243,10 @@ TEST_FILES_PATCHED = $(wildcard testcases/*.tem)
|
|||
# add files created via patches
|
||||
CLIENT_LIB_TEST_FILES += $(TEST_FILES_GENERATED)
|
||||
|
||||
client_test_CPPFLAGS = -DHAVE_CONFIG_H -DENABLE_INTEGRATION_TESTS -DENABLE_UNIT_TESTS $(AM_CPPFLAGS)
|
||||
client_test_CXXFLAGS = `cppunit-config --cflags` $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(KEYRING_CFLAGS)
|
||||
client_test_LDFLAGS = `cppunit-config --libs` `nm syncevo/.libs/libsyncevolution.a | grep funambolAutoRegisterRegistry | sed -e 's/.* /-u /'` $(CORE_LD_FLAGS) $(KEYRING_LIBS)
|
||||
client_test_LDADD = $(CORE_LDADD) $(SYNTHESIS_ENGINE)
|
||||
client_test_CPPFLAGS = -DHAVE_CONFIG_H -DENABLE_INTEGRATION_TESTS -DENABLE_UNIT_TESTS $(AM_CPPFLAGS) $(BUTEOSYNCPROFILE_CFLAGS) $(BUTEOSYNCCOMMON_CFLAGS) $(QT_CPPFLAGS)
|
||||
client_test_CXXFLAGS = `cppunit-config --cflags` $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(KEYRING_CFLAGS) $(BUTEOSYNCPROFILE_CFLAGS) $(BUTEOSYNCCOMMON_CFLAGS) $(filter-out -O2 -g -W -Wall, $(QT_CXXFLAGS))
|
||||
client_test_LDFLAGS = `cppunit-config --libs` `nm syncevo/.libs/libsyncevolution.a | grep funambolAutoRegisterRegistry | sed -e 's/.* /-u /'` $(CORE_LD_FLAGS) $(KEYRING_LIBS) $(BUTEOSYNCPROFILE_LIBS) $(BUTEOSYNCCOMMON_LIBS) $(QT_LDFLAGS)
|
||||
client_test_LDADD = $(CORE_LDADD) $(SYNTHESIS_ENGINE) $(BUTEOSYNCPROFILE_LIBS) $(BUTEOSYNCCOMMON_LIBS) $(QT_LIBS)
|
||||
# These dependencies are intentionally a bit too broad:
|
||||
# they ensure that all files are in place to *run* client-test.
|
||||
|
||||
|
@ -288,6 +296,8 @@ $(filter-out %.tem, $(filter testcases/%, $(subst $(srcdir)/../test/,,$(CLIENT_L
|
|||
# runs the binary with out-dated auxiliary files.
|
||||
client_test_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare templates
|
||||
|
||||
CLEANFILES += client-test-buteo.moc.cpp
|
||||
|
||||
# copy template directory into current working directory, if not there
|
||||
# yet
|
||||
.PHONY: templates
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
#include <syncevo/VolatileConfigNode.h>
|
||||
|
||||
#include <syncevo/declarations.h>
|
||||
|
||||
#ifdef ENABLE_BUTEO_TESTS
|
||||
#include "client-test-buteo.h"
|
||||
#endif
|
||||
|
||||
SE_BEGIN_CXX
|
||||
|
||||
/*
|
||||
|
@ -319,14 +324,41 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BUTEO_TESTS
|
||||
virtual void setup() {
|
||||
QtContactsSwitcher::prepare(*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual SyncMLStatus doSync(const int *sources,
|
||||
const std::string &logbase,
|
||||
const SyncOptions &options)
|
||||
{
|
||||
// check whether using buteo to do sync
|
||||
const char *buteo = getenv("CLIENT_TEST_BUTEO");
|
||||
bool useButeo = false;
|
||||
if (buteo &&
|
||||
(boost::equals(buteo, "1") || boost::iequals(buteo, "t"))) {
|
||||
useButeo = true;
|
||||
}
|
||||
|
||||
string server = getenv("CLIENT_TEST_SERVER") ? getenv("CLIENT_TEST_SERVER") : "funambol";
|
||||
server += "_";
|
||||
server += m_clientID;
|
||||
|
||||
|
||||
if (useButeo) {
|
||||
#ifdef ENABLE_BUTEO_TESTS
|
||||
ButeoTest buteo(*this, server, logbase, options);
|
||||
buteo.prepareSources(sources, m_syncSource2Config);
|
||||
SyncReport report;
|
||||
SyncMLStatus status = buteo.doSync(&report);
|
||||
options.m_checkReport.check(status, report);
|
||||
return status;
|
||||
#else
|
||||
throw runtime_error("This client-test was built without enabling buteo testing.");
|
||||
#endif
|
||||
}
|
||||
class ClientTest : public CmdlineSyncClient {
|
||||
public:
|
||||
ClientTest(const string &server,
|
||||
|
|
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
* Copyright (C) 2010 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 "syncevo/util.h"
|
||||
#include "client-test-buteo.h"
|
||||
#include <libsyncprofile/SyncResults.h>
|
||||
#include <libsyncprofile/ProfileEngineDefs.h>
|
||||
#include <libsyncprofile/Profile.h>
|
||||
#include <libsyncprofile/SyncProfile.h>
|
||||
#include <syncmlcommon/SyncMLCommon.h>
|
||||
#include <QDomDocument>
|
||||
#include <QtDBus>
|
||||
|
||||
using namespace Buteo;
|
||||
using namespace SyncEvo;
|
||||
|
||||
// execute a command. If 'check' is true, throw an exception when
|
||||
// execution encounters error(s)
|
||||
static void execCmd(const std::string &cmd, bool check = true)
|
||||
{
|
||||
int result = Execute(cmd, ExecuteFlags(EXECUTE_NO_STDERR | EXECUTE_NO_STDOUT));
|
||||
if (result < 0 && check) {
|
||||
throw runtime_error("failed to excute command: " + cmd);
|
||||
}
|
||||
}
|
||||
|
||||
bool ButeoTest::m_inited = false;
|
||||
QString ButeoTest::m_deviceIds[2];
|
||||
map<string, string> ButeoTest::m_source2storage;
|
||||
|
||||
ButeoTest::ButeoTest(ClientTest &client,
|
||||
const string &server,
|
||||
const string &logbase,
|
||||
const SyncEvo::SyncOptions &options) :
|
||||
m_client(client), m_server(server), m_logbase(logbase), m_options(options)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void ButeoTest::init()
|
||||
{
|
||||
if (!m_inited) {
|
||||
m_inited = true;
|
||||
// generate device ids
|
||||
for(int i = 0; i < sizeof(m_deviceIds)/sizeof(m_deviceIds[0]); i++) {
|
||||
QString id;
|
||||
UUID uuid;
|
||||
QTextStream(&id) << "sc-pim-" << uuid.c_str();
|
||||
m_deviceIds[i] = id;
|
||||
}
|
||||
|
||||
// insert source -> storage mappings
|
||||
m_source2storage.insert(std::make_pair("qt_vcard30", "hcontacts"));
|
||||
m_source2storage.insert(std::make_pair("kcal_ical20", "hcalendar"));
|
||||
m_source2storage.insert(std::make_pair("kcal_itodo20", "htodo"));
|
||||
m_source2storage.insert(std::make_pair("kcal_text", "hnotes"));
|
||||
|
||||
//init qcoreapplication to use qt
|
||||
static const char *argv[] = { "SyncEvolution" };
|
||||
static int argc = 1;
|
||||
new QCoreApplication(argc, (char **)argv);
|
||||
}
|
||||
}
|
||||
|
||||
void ButeoTest::prepareSources(const int *sources,
|
||||
const vector<string> &source2Config)
|
||||
{
|
||||
for(int i = 0; sources[i] >= 0; i++) {
|
||||
string source = source2Config[sources[i]];
|
||||
map<string, string>::iterator it = m_source2storage.find(source);
|
||||
if (it != m_source2storage.end()) {
|
||||
m_configedSources.insert(it->second);
|
||||
} else {
|
||||
throw runtime_error("unsupported source '" + source + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SyncMLStatus ButeoTest::doSync(SyncReport *report)
|
||||
{
|
||||
SyncMLStatus status = STATUS_OK;
|
||||
|
||||
// kill msyncd
|
||||
killAllMsyncd();
|
||||
//set sync options
|
||||
setupOptions();
|
||||
// restore qtcontacts if needed
|
||||
if (inclContacts()) {
|
||||
QtContactsSwitcher::restoreStorage(m_client);
|
||||
}
|
||||
|
||||
//start msyncd
|
||||
int pid = startMsyncd();
|
||||
//kill 'sh' process which is the parent of 'msyncd'
|
||||
stringstream cmd;
|
||||
cmd << "kill -9 " << pid;
|
||||
//run sync
|
||||
if (!run()) {
|
||||
execCmd(cmd.str(), false);
|
||||
killAllMsyncd();
|
||||
return STATUS_FATAL;
|
||||
}
|
||||
|
||||
execCmd(cmd.str(), false);
|
||||
killAllMsyncd();
|
||||
// save qtcontacts if needed
|
||||
if (inclContacts()) {
|
||||
QtContactsSwitcher::backupStorage(m_client);
|
||||
}
|
||||
//get sync results
|
||||
genSyncResults(m_syncResults, report);
|
||||
return report->getStatus();
|
||||
}
|
||||
|
||||
void ButeoTest::setupOptions()
|
||||
{
|
||||
// 1. set deviceid, max-message-size options to /etc/sync/meego-sync-conf.xml
|
||||
QString meegoSyncmlConf = "/etc/sync/meego-syncml-conf.xml";
|
||||
QFile syncmlFile(meegoSyncmlConf);
|
||||
if (!syncmlFile.open(QIODevice::ReadOnly)) {
|
||||
throw runtime_error("can't open syncml config");
|
||||
}
|
||||
// don't invoke buteo-syncml API for it doesn't support flushing
|
||||
QString syncmlContent(syncmlFile.readAll());
|
||||
syncmlFile.close();
|
||||
int id = 0;
|
||||
if (!boost::ends_with(m_server, "_1")) {
|
||||
id = 1;
|
||||
}
|
||||
|
||||
//specify the db path which saves anchors related info, then we can wipe
|
||||
//out it if want to slow sync.
|
||||
replaceElement(syncmlContent, "dbpath", QString((m_server + ".db").c_str()));
|
||||
replaceElement(syncmlContent, "local-device-name", m_deviceIds[id]);
|
||||
|
||||
QString msgSize;
|
||||
QTextStream(&msgSize) << m_options.m_maxMsgSize;
|
||||
replaceElement(syncmlContent, "max-message-size", msgSize);
|
||||
|
||||
writeToFile(meegoSyncmlConf, syncmlContent);
|
||||
|
||||
// 2. set storage 'Notebook Name' for calendar, todo and notes
|
||||
// for contacts, we have to set corresponding tracker db
|
||||
string storageDir = getHome() + "/.sync/profiles/storage/";
|
||||
BOOST_FOREACH(const string &source, m_configedSources) {
|
||||
if (boost::iequals(source, "hcalendar") ||
|
||||
boost::iequals(source, "htodo") ||
|
||||
boost::iequals(source, "hnotes")) {
|
||||
string filePath = storageDir + source + ".xml";
|
||||
QDomDocument doc(m_server.c_str());
|
||||
buildDomFromFile(doc, filePath.c_str());
|
||||
QString notebookName;
|
||||
QTextStream(¬ebookName) << "client_test_" << id;
|
||||
Profile profile(doc.documentElement());
|
||||
profile.setKey("Notebook Name", notebookName);
|
||||
writeToFile(filePath.c_str(), profile.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. set wbxml option, sync mode, enabled selected sources and disable other sources
|
||||
QDomDocument doc(m_server.c_str());
|
||||
//copy profile
|
||||
string profileDir = getHome() + "/.sync/profiles/sync/";
|
||||
string profilePath = profileDir + m_server + ".xml";
|
||||
size_t pos = m_server.rfind('_');
|
||||
if (pos != m_server.npos) {
|
||||
string prefix = m_server.substr(0, pos);
|
||||
stringstream cmd;
|
||||
cmd << "cp " << profileDir
|
||||
<< prefix << ".xml "
|
||||
<< profilePath;
|
||||
execCmd(cmd.str());
|
||||
}
|
||||
buildDomFromFile(doc, profilePath.c_str());
|
||||
SyncProfile syncProfile(doc.documentElement());
|
||||
syncProfile.setName(m_server.c_str());
|
||||
QList<Profile *> storages = syncProfile.storageProfilesNonConst();
|
||||
QListIterator<Profile *> it(storages);
|
||||
while (it.hasNext()) {
|
||||
Profile * profile = it.next();
|
||||
set<string>::iterator configedIt = m_configedSources.find(profile->name().toStdString());
|
||||
if (configedIt != m_configedSources.end()) {
|
||||
profile->setKey(KEY_ENABLED, "true");
|
||||
} else {
|
||||
profile->setKey(KEY_ENABLED, "false");
|
||||
}
|
||||
}
|
||||
|
||||
// set syncml client
|
||||
Profile * syncml = syncProfile.subProfile("syncml", "client");
|
||||
if (syncml) {
|
||||
// set whether using wbxml
|
||||
syncml->setBoolKey(PROF_USE_WBXML, m_options.m_isWBXML);
|
||||
// set sync mode
|
||||
QString syncMode;
|
||||
switch(m_options.m_syncMode) {
|
||||
case SYNC_NONE:
|
||||
break;
|
||||
case SYNC_TWO_WAY:
|
||||
syncMode = VALUE_TWO_WAY;
|
||||
break;
|
||||
case SYNC_ONE_WAY_FROM_CLIENT:
|
||||
// work around here since buteo doesn't support refresh mode now
|
||||
syncMode = VALUE_TO_REMOTE;
|
||||
break;
|
||||
case SYNC_REFRESH_FROM_CLIENT:
|
||||
// don't support, no workaround here
|
||||
throw runtime_error("Buteo doesn't support refresh mode");
|
||||
case SYNC_ONE_WAY_FROM_SERVER:
|
||||
syncMode = VALUE_FROM_REMOTE;
|
||||
break;
|
||||
case SYNC_REFRESH_FROM_SERVER: {
|
||||
//workaround here since buteo doesn't support refresh-from-server
|
||||
//wipe out anchors and remove tracker database
|
||||
//so we will do refresh-from-server by slow sync
|
||||
stringstream cmd1;
|
||||
cmd1 << "rm -f " << m_server << ".db";
|
||||
execCmd(cmd1.str(), false);
|
||||
if (inclContacts()) {
|
||||
execCmd("tracker-control -r", false);
|
||||
stringstream cmd2;
|
||||
cmd2 << "rm -f "
|
||||
<< getHome() << "/.cache/tracker/*.db "
|
||||
<< getHome() << "/.cache/tracker/*.db_"
|
||||
<< m_client.getClientB() ? "1" : "2";
|
||||
execCmd(cmd2.str(), false);
|
||||
}
|
||||
syncMode = VALUE_TWO_WAY;
|
||||
break;
|
||||
}
|
||||
case SYNC_SLOW: {
|
||||
//workaround here since buteo doesn't support explicite slow-sync
|
||||
//wipe out anchors so we will do slow sync
|
||||
stringstream cmd;
|
||||
cmd << "rm -f " << m_server << ".db";
|
||||
execCmd(cmd.str(), false);
|
||||
syncMode = VALUE_TWO_WAY;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
syncml->setKey(KEY_SYNC_DIRECTION, syncMode);
|
||||
}
|
||||
writeToFile(profilePath.c_str(), syncProfile.toString());
|
||||
}
|
||||
|
||||
void ButeoTest::killAllMsyncd()
|
||||
{
|
||||
execCmd("killall -9 msyncd", false);
|
||||
}
|
||||
|
||||
int ButeoTest::startMsyncd()
|
||||
{
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
//child
|
||||
stringstream cmd;
|
||||
cmd << "msyncd >" << m_logbase << ".log 2>&1";
|
||||
if (execlp("sh", "sh", "-c", cmd.str().c_str(), (char *)0) < 0 ) {
|
||||
exit(1);
|
||||
}
|
||||
} else if (pid < 0) {
|
||||
throw runtime_error("can't fork process");
|
||||
}
|
||||
// wait for msyncd get prepared
|
||||
execCmd("sleep 2", false);
|
||||
return pid;
|
||||
}
|
||||
|
||||
bool ButeoTest::run()
|
||||
{
|
||||
static const QString msyncdService = "com.meego.msyncd";
|
||||
static const QString msyncdObject = "/synchronizer";
|
||||
static const QString msyncdInterface = "com.meego.msyncd";
|
||||
|
||||
QDBusConnection conn = QDBusConnection::sessionBus();
|
||||
std::auto_ptr<QDBusInterface> interface(new QDBusInterface(msyncdService, msyncdObject, msyncdInterface, conn));
|
||||
if (!interface->isValid()) {
|
||||
QString error = interface->lastError().message();
|
||||
return false;
|
||||
}
|
||||
|
||||
// add watcher for watching unregistering service
|
||||
std::auto_ptr<QDBusServiceWatcher> dbusWatcher(new QDBusServiceWatcher(msyncdService, conn, QDBusServiceWatcher::WatchForUnregistration));
|
||||
dbusWatcher->connect(dbusWatcher.get(), SIGNAL(serviceUnregistered(QString)),
|
||||
this, SLOT(serviceUnregistered(QString)));
|
||||
|
||||
//connect signals
|
||||
interface->connect(interface.get(), SIGNAL(syncStatus(QString, int, QString, int)),
|
||||
this, SLOT(syncStatus(QString, int, QString, int)));
|
||||
interface->connect(interface.get(), SIGNAL(resultsAvailable(QString, QString)),
|
||||
this, SLOT(resultsAvailable(QString, QString)));
|
||||
|
||||
// start sync
|
||||
QDBusReply<bool> reply = interface->call(QString("startSync"), m_server.c_str());
|
||||
if (reply.isValid() && !reply.value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait sync completed
|
||||
return QCoreApplication::exec() == 0;
|
||||
}
|
||||
|
||||
void ButeoTest::genSyncResults(const QString &text, SyncReport *report)
|
||||
{
|
||||
QDomDocument domResults;
|
||||
if (domResults.setContent(text, true)) {
|
||||
SyncResults syncResults(domResults.documentElement());
|
||||
switch(syncResults.majorCode()) {
|
||||
case SyncResults::SYNC_RESULT_SUCCESS:
|
||||
report->setStatus(STATUS_OK);
|
||||
break;
|
||||
case SyncResults::SYNC_RESULT_FAILED:
|
||||
report->setStatus(STATUS_FATAL);
|
||||
break;
|
||||
case SyncResults::SYNC_RESULT_CANCELLED:
|
||||
report->setStatus(STATUS_FATAL);
|
||||
break;
|
||||
};
|
||||
QList<TargetResults> targetResults = syncResults.targetResults();
|
||||
QListIterator<TargetResults> it(targetResults);
|
||||
while (it.hasNext()) {
|
||||
// get item sync info
|
||||
TargetResults target = it.next();
|
||||
SyncSourceReport targetReport;
|
||||
// temporary set this mode due to no this information in report
|
||||
targetReport.recordFinalSyncMode(m_options.m_syncMode);
|
||||
ItemCounts itemCounts = target.localItems();
|
||||
targetReport.setItemStat(SyncSourceReport::ITEM_LOCAL,
|
||||
SyncSourceReport::ITEM_ADDED,
|
||||
SyncSourceReport::ITEM_TOTAL,
|
||||
itemCounts.added);
|
||||
targetReport.setItemStat(SyncSourceReport::ITEM_LOCAL,
|
||||
SyncSourceReport::ITEM_UPDATED,
|
||||
SyncSourceReport::ITEM_TOTAL,
|
||||
itemCounts.modified);
|
||||
targetReport.setItemStat(SyncSourceReport::ITEM_LOCAL,
|
||||
SyncSourceReport::ITEM_REMOVED,
|
||||
SyncSourceReport::ITEM_TOTAL,
|
||||
itemCounts.deleted);
|
||||
|
||||
// get item info for remote
|
||||
itemCounts = target.remoteItems();
|
||||
targetReport.setItemStat(SyncSourceReport::ITEM_REMOTE,
|
||||
SyncSourceReport::ITEM_ADDED,
|
||||
SyncSourceReport::ITEM_TOTAL,
|
||||
itemCounts.added);
|
||||
targetReport.setItemStat(SyncSourceReport::ITEM_REMOTE,
|
||||
SyncSourceReport::ITEM_UPDATED,
|
||||
SyncSourceReport::ITEM_TOTAL,
|
||||
itemCounts.modified);
|
||||
targetReport.setItemStat(SyncSourceReport::ITEM_REMOTE,
|
||||
SyncSourceReport::ITEM_REMOVED,
|
||||
SyncSourceReport::ITEM_TOTAL,
|
||||
itemCounts.deleted);
|
||||
// set to sync report
|
||||
report->addSyncSourceReport(target.targetName().toStdString(), targetReport);
|
||||
}
|
||||
} else {
|
||||
report->setStatus(STATUS_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
void ButeoTest::syncStatus(QString profile, int status, QString message, int moreDetails)
|
||||
{
|
||||
if (profile == m_server.c_str()) {
|
||||
switch(status) {
|
||||
case 0: // QUEUED
|
||||
case 1: // STARTED
|
||||
case 2: // PROGRESS
|
||||
break;
|
||||
case 3: // ERROR
|
||||
case 5: // ABORTED
|
||||
QCoreApplication::exit(1);
|
||||
break;
|
||||
case 4: // DONE
|
||||
QCoreApplication::exit(0);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButeoTest::resultsAvailable(QString profile, QString syncResults)
|
||||
{
|
||||
if (profile == m_server.c_str()) {
|
||||
m_syncResults = syncResults;
|
||||
}
|
||||
}
|
||||
|
||||
void ButeoTest::serviceUnregistered(QString service)
|
||||
{
|
||||
QCoreApplication::exit(1);
|
||||
}
|
||||
|
||||
bool ButeoTest::inclContacts()
|
||||
{
|
||||
set<string>::iterator sit = m_configedSources.find("hcontacts");
|
||||
if (sit != m_configedSources.end()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ButeoTest::writeToFile(const QString &filePath, const QString &content)
|
||||
{
|
||||
// clear tempoary file firstly
|
||||
stringstream rmCmd;
|
||||
rmCmd << "rm -f " << filePath.toStdString() << "_tmp";
|
||||
execCmd(rmCmd.str(), false);
|
||||
|
||||
// open temporary file and serialize dom to the file
|
||||
QFile file(filePath + "_tmp");
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
stringstream msg;
|
||||
msg << "can't open file '" << filePath.toStdString() << "' with 'write' mode";
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
if (file.write(content.toUtf8()) == -1) {
|
||||
file.close();
|
||||
stringstream msg;
|
||||
msg << "can't write file '" << filePath.toStdString() << "'";
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
file.close();
|
||||
|
||||
// move temp file to destination file
|
||||
stringstream mvCmd;
|
||||
mvCmd << "mv " << filePath.toStdString() << "_tmp "
|
||||
<< filePath.toStdString();
|
||||
execCmd(mvCmd.str());
|
||||
}
|
||||
|
||||
void ButeoTest::replaceElement(QString &xml, const QString &elem, const QString &value)
|
||||
{
|
||||
// TODO: use DOM to parse xml
|
||||
// currently this could work
|
||||
QString startTag = "<" + elem +">";
|
||||
QString endTag = "</" + elem +">";
|
||||
|
||||
int start = xml.indexOf(startTag);
|
||||
if ( start == -1) {
|
||||
return;
|
||||
}
|
||||
int end = xml.indexOf(endTag, start);
|
||||
int pos = start + startTag.size();
|
||||
|
||||
xml.replace(pos, end - pos, value);
|
||||
}
|
||||
|
||||
void ButeoTest::buildDomFromFile(QDomDocument &doc, const QString &filePath)
|
||||
{
|
||||
// open it
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
stringstream msg;
|
||||
msg << "can't open profile file '" << filePath.toStdString() << "'";
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
// parse it
|
||||
if (!doc.setContent(&file)) {
|
||||
file.close();
|
||||
stringstream msg;
|
||||
msg << "can't parse profile file '" << filePath.toStdString() << "'";
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
static bool isButeo()
|
||||
{
|
||||
static bool checked = false;
|
||||
static bool useButeo = false;
|
||||
|
||||
if (!checked) {
|
||||
const char *buteo = getenv("CLIENT_TEST_BUTEO");
|
||||
if (buteo &&
|
||||
(boost::equals(buteo, "1") || boost::iequals(buteo, "t"))) {
|
||||
useButeo = true;
|
||||
}
|
||||
checked = true;
|
||||
}
|
||||
|
||||
return useButeo;
|
||||
}
|
||||
|
||||
// 3 databases used by tracker to store contacts
|
||||
// empty string is used as separator
|
||||
string QtContactsSwitcher::m_databases[] = {"meta.db",
|
||||
"contents.db",
|
||||
"fulltext.db", // 3 databases used by tracker
|
||||
"", // separator
|
||||
"hcontacts.db" // database to record deleted contact items
|
||||
};
|
||||
string QtContactsSwitcher::m_dirs[] = {"/.cache/tracker/",
|
||||
"/.sync/sync-app/"};
|
||||
|
||||
string QtContactsSwitcher::getId(ClientTest &client) {
|
||||
if (client.getClientB()) {
|
||||
return "1";
|
||||
}
|
||||
return "2";
|
||||
}
|
||||
|
||||
void QtContactsSwitcher::prepare(ClientTest &client) {
|
||||
int index = 0;
|
||||
for (int i = 0; i < sizeof(m_databases)/sizeof(m_databases[0]); i++) {
|
||||
if (m_databases[i].empty()) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
stringstream cmd;
|
||||
cmd << "rm -f " << getDatabasePath(index) << m_databases[i]
|
||||
<< "_";
|
||||
execCmd(cmd.str() + "1", false);
|
||||
execCmd(cmd.str() + "2", false);
|
||||
}
|
||||
execCmd("tracker-control -r", false);
|
||||
}
|
||||
|
||||
void QtContactsSwitcher::restoreStorage(ClientTest &client)
|
||||
{
|
||||
// if CLIENT_TEST_BUTEO is not enabled, skip it for LocalTests may also use it
|
||||
if (!isButeo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
string id = getId(client);
|
||||
terminate();
|
||||
copyDatabases(client, false);
|
||||
start();
|
||||
}
|
||||
|
||||
void QtContactsSwitcher::backupStorage(ClientTest &client)
|
||||
{
|
||||
// if CLIENT_TEST_BUTEO is not enabled, skip it for LocalTests may also use it
|
||||
if (!isButeo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
string id = getId(client);
|
||||
terminate();
|
||||
copyDatabases(client);
|
||||
start();
|
||||
}
|
||||
|
||||
string QtContactsSwitcher::getDatabasePath(int index)
|
||||
{
|
||||
string m_path = getHome() + m_dirs[index];
|
||||
return m_path;
|
||||
}
|
||||
|
||||
void QtContactsSwitcher::copyDatabases(ClientTest &client, bool fromDefault)
|
||||
{
|
||||
static string m_cmds[] = {"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"\"delete from deleteditems;\""};
|
||||
|
||||
string id = getId(client);
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < sizeof(m_databases)/sizeof(m_databases[0]); i++) {
|
||||
if (m_databases[i].empty()) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
string src = getDatabasePath(index) + m_databases[i];
|
||||
string dest = src + "_" + id;
|
||||
if (!fromDefault) {
|
||||
// in this case, we copy *_1/2.db to default db
|
||||
// if *_1/2.db doesn't exist, we copy default with initial commands
|
||||
if (access(dest.c_str(), F_OK) < 0) {
|
||||
if (access(src.c_str(), F_OK) >= 0) {
|
||||
if (!m_cmds[i].empty()) {
|
||||
stringstream temp;
|
||||
temp << "sqlite3 " << src << " " << m_cmds[i];
|
||||
execCmd(temp.str(), false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
string tmp = src;
|
||||
src = dest;
|
||||
dest = tmp;
|
||||
}
|
||||
}
|
||||
stringstream cmd;
|
||||
cmd << "cp -f " << src << " " << dest;
|
||||
execCmd(cmd.str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void QtContactsSwitcher::terminate()
|
||||
{
|
||||
execCmd("tracker-control -t");
|
||||
}
|
||||
|
||||
void QtContactsSwitcher::start()
|
||||
{
|
||||
// sleep one second to let tracker daemon get prepared
|
||||
execCmd("tracker-control -s");
|
||||
execCmd("sleep 2");
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (C) 2010 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
|
||||
*/
|
||||
#ifndef INCL_SYNC_BUTEOTEST
|
||||
#define INCL_SYNC_BUTEOTEST
|
||||
|
||||
#include <syncevo/util.h>
|
||||
#include <syncevo/declarations.h>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QtDBus>
|
||||
#include <QDomDocument>
|
||||
#include "ClientTest.h"
|
||||
|
||||
using namespace SyncEvo;
|
||||
|
||||
/**
|
||||
* ButeoTest is used to invoke buteo to do client test with the help
|
||||
* of client test framework. The basic idea is to implement doSync and
|
||||
* replace with invocation of buteo's dbus server - 'msyncd'.
|
||||
* The main steps are:
|
||||
* 1) pre-run: This may include set up sync options for local client
|
||||
* and target server, prepare local databases
|
||||
* 2) run: run sync by sending dbus calls to 'msyncd' and wait until
|
||||
* it finishes
|
||||
* 3) post-run: collect sync result and statistics
|
||||
*/
|
||||
class ButeoTest : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ButeoTest(ClientTest &client,
|
||||
const string &server,
|
||||
const string &logbase,
|
||||
const SyncEvo::SyncOptions &options);
|
||||
|
||||
// prepare sync sources
|
||||
void prepareSources(const int *sources, const vector<string> &source2Config);
|
||||
|
||||
// do actually sync
|
||||
SyncEvo::SyncMLStatus doSync(SyncEvo::SyncReport *report);
|
||||
|
||||
private slots:
|
||||
void syncStatus(QString, int, QString, int);
|
||||
void resultsAvailable(QString, QString);
|
||||
void serviceUnregistered(QString);
|
||||
|
||||
private:
|
||||
|
||||
/** initialize
|
||||
*/
|
||||
static void init();
|
||||
|
||||
/**
|
||||
* 1. set deviceid, max-message-size options to /etc/sync/meego-sync-conf.xml
|
||||
* 2. set wbxml option, sync mode, enabled selected sources and disable other sources
|
||||
*/
|
||||
void setupOptions();
|
||||
|
||||
// kill all msyncd
|
||||
void killAllMsyncd();
|
||||
|
||||
// start msyncd
|
||||
int startMsyncd();
|
||||
|
||||
// do actually running
|
||||
bool run();
|
||||
|
||||
// get sync results from buteo and set them to sync report
|
||||
void genSyncResults(const QString &text, SyncEvo::SyncReport *report);
|
||||
|
||||
// whether configured sources include contacts
|
||||
bool inclContacts();
|
||||
|
||||
// truncate file and write content to file
|
||||
static void writeToFile(const QString &filePath, const QString &content );
|
||||
|
||||
//replace the element value with a new value
|
||||
static void replaceElement(QString &xml, const QString &elem, const QString &value);
|
||||
|
||||
// build a dom tree from file
|
||||
static void buildDomFromFile(QDomDocument &doc, const QString &filePath);
|
||||
|
||||
ClientTest &m_client;
|
||||
string m_server;
|
||||
string m_logbase;
|
||||
SyncEvo::SyncOptions m_options;
|
||||
std::set<string> m_configedSources;
|
||||
QString m_syncResults;
|
||||
|
||||
//device ids
|
||||
static QString m_deviceIds[2];
|
||||
//mappings for syncevolution source and buteo storage
|
||||
static map<string, string> m_source2storage;
|
||||
//flag for initialization
|
||||
static bool m_inited;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Qtcontacts use tracker to store data. However, it can't specify
|
||||
* the place where to store them. Since we have to separate client A
|
||||
* and B's data, restore and backup their databases
|
||||
*/
|
||||
class QtContactsSwitcher {
|
||||
public:
|
||||
/** do preparation */
|
||||
static void prepare(ClientTest &client);
|
||||
|
||||
static string getId(ClientTest &client);
|
||||
|
||||
/**
|
||||
* prepare storage:
|
||||
* 1. terminate tracker
|
||||
* 2. copy tracker databases from backup to its default place
|
||||
* according to id
|
||||
* 3. restart tracker
|
||||
*/
|
||||
static void restoreStorage(ClientTest &client);
|
||||
|
||||
/**
|
||||
* backup storage:
|
||||
* 1. terminate tracker
|
||||
* 2. copy tracker databases from default place to backup
|
||||
* 3. restart tracker
|
||||
*/
|
||||
static void backupStorage(ClientTest &client);
|
||||
private:
|
||||
// get the file path of databases
|
||||
static std::string getDatabasePath(int index = 0);
|
||||
|
||||
//terminate tracker daemons
|
||||
static void terminate();
|
||||
|
||||
//start tracker daemons
|
||||
static void start();
|
||||
|
||||
//copy databases between default place and backup place
|
||||
static void copyDatabases(ClientTest &client, bool fromDefault = true);
|
||||
|
||||
//databases used by tracker
|
||||
static std::string m_databases[];
|
||||
static std::string m_dirs[];
|
||||
};
|
||||
#endif
|
|
@ -55,6 +55,11 @@
|
|||
#include <boost/bind.hpp>
|
||||
|
||||
#include <syncevo/declarations.h>
|
||||
|
||||
#ifdef ENABLE_BUTEO_TESTS
|
||||
#include "client-test-buteo.h"
|
||||
#endif
|
||||
|
||||
SE_BEGIN_CXX
|
||||
|
||||
static set<ClientTest::Cleanup_t> cleanupSet;
|
||||
|
@ -170,6 +175,24 @@ static std::string importItem(TestingSyncSource *source, const ClientTestConfig
|
|||
}
|
||||
}
|
||||
|
||||
static void restoreStorage(const ClientTest::Config &config, ClientTest &client)
|
||||
{
|
||||
#ifdef ENABLE_BUTEO_TESTS
|
||||
if (boost::iequals(config.sourceName,"qt_vcard30")) {
|
||||
QtContactsSwitcher::restoreStorage(client);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void backupStorage(const ClientTest::Config &config, ClientTest &client)
|
||||
{
|
||||
#ifdef ENABLE_BUTEO_TESTS
|
||||
if (boost::iequals(config.sourceName,"qt_vcard30")) {
|
||||
QtContactsSwitcher::backupStorage(client);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** adds the supported tests to the instance itself */
|
||||
void LocalTests::addTests() {
|
||||
if (config.createSourceA) {
|
||||
|
@ -236,6 +259,8 @@ void LocalTests::addTests() {
|
|||
}
|
||||
|
||||
std::string LocalTests::insert(CreateSource createSource, const char *data, bool relaxed, std::string *inserted) {
|
||||
restoreStorage(config, client);
|
||||
|
||||
// create source
|
||||
TestingSyncSourcePtr source(createSource());
|
||||
|
||||
|
@ -264,6 +289,7 @@ std::string LocalTests::insert(CreateSource createSource, const char *data, bool
|
|||
CPPUNIT_ASSERT(countUpdatedItems(source.get()) == 0);
|
||||
CPPUNIT_ASSERT(countDeletedItems(source.get()) == 0);
|
||||
}
|
||||
backupStorage(config, client);
|
||||
|
||||
return res.m_luid;
|
||||
}
|
||||
|
@ -305,6 +331,8 @@ void LocalTests::update(CreateSource createSource, const char *data, bool check)
|
|||
CPPUNIT_ASSERT(createSource.createSource);
|
||||
CPPUNIT_ASSERT(data);
|
||||
|
||||
restoreStorage(config, client);
|
||||
|
||||
// create source
|
||||
TestingSyncSourcePtr source(createSource());
|
||||
|
||||
|
@ -330,23 +358,29 @@ void LocalTests::update(CreateSource createSource, const char *data, bool check)
|
|||
SOURCE_ASSERT_NO_FAILURE(source.get(), it = source->getAllItems().begin());
|
||||
CPPUNIT_ASSERT(it != source->getAllItems().end());
|
||||
CPPUNIT_ASSERT_EQUAL(luid, *it);
|
||||
|
||||
backupStorage(config, client);
|
||||
}
|
||||
|
||||
void LocalTests::update(CreateSource createSource, const char *data, const std::string &luid) {
|
||||
CPPUNIT_ASSERT(createSource.createSource);
|
||||
CPPUNIT_ASSERT(data);
|
||||
|
||||
restoreStorage(config, client);
|
||||
// create source
|
||||
TestingSyncSourcePtr source(createSource());
|
||||
|
||||
// update it
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), source->insertItemRaw(luid, config.mangleItem(data).c_str()));
|
||||
|
||||
backupStorage(config, client);
|
||||
}
|
||||
|
||||
/** deletes all items locally via sync source */
|
||||
void LocalTests::deleteAll(CreateSource createSource) {
|
||||
CPPUNIT_ASSERT(createSource.createSource);
|
||||
|
||||
restoreStorage(config, client);
|
||||
// create source
|
||||
TestingSyncSourcePtr source(createSource());
|
||||
|
||||
|
@ -363,6 +397,7 @@ void LocalTests::deleteAll(CreateSource createSource) {
|
|||
CPPUNIT_ASSERT_EQUAL( 0, countNewItems(source.get()) );
|
||||
CPPUNIT_ASSERT_EQUAL( 0, countUpdatedItems(source.get()) );
|
||||
CPPUNIT_ASSERT_EQUAL( 0, countDeletedItems(source.get()) );
|
||||
backupStorage(config, client);
|
||||
}
|
||||
|
||||
/** deletes specific item locally via sync source */
|
||||
|
@ -543,6 +578,7 @@ std::list<std::string> LocalTests::insertManyItems(CreateSource createSource, in
|
|||
CPPUNIT_ASSERT(config.templateItem);
|
||||
CPPUNIT_ASSERT(config.uniqueProperties);
|
||||
|
||||
restoreStorage(config, client);
|
||||
TestingSyncSourcePtr source;
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceA()));
|
||||
CPPUNIT_ASSERT(startIndex > 1 || !countItems(source.get()));
|
||||
|
@ -556,6 +592,7 @@ std::list<std::string> LocalTests::insertManyItems(CreateSource createSource, in
|
|||
std::string data = createItem(item, "", size);
|
||||
luids.push_back(importItem(source.get(), config, data));
|
||||
}
|
||||
backupStorage(config, client);
|
||||
|
||||
return luids;
|
||||
}
|
||||
|
@ -753,8 +790,10 @@ void LocalTests::testImport() {
|
|||
// import via sync source A
|
||||
TestingSyncSourcePtr source;
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceA()));
|
||||
restoreStorage(config, client);
|
||||
std::string testcases;
|
||||
SOURCE_ASSERT_EQUAL(source.get(), 0, config.import(client, *source.get(), config, config.testcases, testcases));
|
||||
backupStorage(config, client);
|
||||
CPPUNIT_ASSERT_NO_THROW(source.reset());
|
||||
|
||||
// export again and compare against original file
|
||||
|
@ -2648,9 +2687,16 @@ void SyncTests::testComplexRefreshFromServerSemantic()
|
|||
testCopy();
|
||||
|
||||
// check refresh with one item on server
|
||||
accessClientB->doSync("refresh-one",
|
||||
SyncOptions(SYNC_REFRESH_FROM_SERVER,
|
||||
CheckSyncReport(1,0,1, 0,0,0, true, SYNC_REFRESH_FROM_SERVER)));
|
||||
const char *value = getenv ("CLIENT_TEST_NOREFRESH");
|
||||
// If refresh_from_server or refresh_from_client (depending on this is a
|
||||
// server or client) is not supported, we can still test via slow sync.
|
||||
if (value) {
|
||||
accessClientB->refreshClient();
|
||||
} else {
|
||||
accessClientB->doSync("refresh-one",
|
||||
SyncOptions(SYNC_REFRESH_FROM_SERVER,
|
||||
CheckSyncReport(1,0,1, 0,0,0, true, SYNC_REFRESH_FROM_SERVER)));
|
||||
}
|
||||
|
||||
// delete that item via A, check again
|
||||
BOOST_FOREACH(source_array_t::value_type &source_pair, sources) {
|
||||
|
@ -2659,9 +2705,13 @@ void SyncTests::testComplexRefreshFromServerSemantic()
|
|||
doSync("delete-item",
|
||||
SyncOptions(SYNC_TWO_WAY,
|
||||
CheckSyncReport(0,0,0, 0,0,1, true, SYNC_TWO_WAY)));
|
||||
accessClientB->doSync("refresh-none",
|
||||
SyncOptions(SYNC_REFRESH_FROM_SERVER,
|
||||
CheckSyncReport(0,0,1, 0,0,0, true, SYNC_REFRESH_FROM_SERVER)));
|
||||
if (value) {
|
||||
accessClientB->refreshClient();
|
||||
} else {
|
||||
accessClientB->doSync("refresh-none",
|
||||
SyncOptions(SYNC_REFRESH_FROM_SERVER,
|
||||
CheckSyncReport(0,0,1, 0,0,0, true, SYNC_REFRESH_FROM_SERVER)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -225,6 +225,9 @@ class ClientTest {
|
|||
ClientTest(int serverSleepSec = 0, const std::string &serverLog= "");
|
||||
virtual ~ClientTest();
|
||||
|
||||
/** set up before running a test */
|
||||
virtual void setup() { }
|
||||
|
||||
/** cleanup function to be called when shutting down testing */
|
||||
typedef void (*Cleanup_t)(void);
|
||||
|
||||
|
@ -462,6 +465,9 @@ public:
|
|||
createSourceB(co.createSourceB, cl, sourceParam, false)
|
||||
{}
|
||||
|
||||
/** set up before running a test */
|
||||
virtual void setUp() { client.setup(); }
|
||||
|
||||
/**
|
||||
* adds the supported tests to the instance itself;
|
||||
* this is the function that a derived class can override
|
||||
|
@ -587,6 +593,9 @@ public:
|
|||
/** adds the supported tests to the instance itself */
|
||||
virtual void addTests();
|
||||
|
||||
/** set up before running a test */
|
||||
virtual void setUp() { client.setup(); }
|
||||
|
||||
protected:
|
||||
/** list with all local test classes for manipulating the sources and their index in the client */
|
||||
typedef std::vector< std::pair<int, LocalTests *> > source_array_t;
|
||||
|
|
Loading…
Reference in New Issue