⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clienttest.cpp

📁 funambol windows mobile plugin source code, the source code is taken from the funambol site
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (C) 2003-2007 Funambol, Inc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307  USA
 */

/** @cond API */
/** @addtogroup ClientTest */
/** @{ */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifdef ENABLE_INTEGRATION_TESTS

#include "ClientTest.h"
#include "base/test.h"
#include "base/util/StringBuffer.h"

#include <memory>
#include <vector>
#include <utility>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <iostream>
#include <algorithm>

/** utility function to iterate over different kinds of items in a sync source */
static int countAnyItems(
    SyncSource *source,
    SyncItem * (SyncSource::*first)(),
    SyncItem * (SyncSource::*next)() )
{
    SyncItem *item;
    int count = 0;

    CPPUNIT_ASSERT(source);
    CPPUNIT_ASSERT(!source->getReport() || source->getReport()->getState() != SOURCE_ERROR);
    SOURCE_ASSERT_NO_FAILURE(source, item = (source->*first)());
    while ( item ) {
        count++;
        delete item;
        SOURCE_ASSERT_NO_FAILURE(source, item = (source->*next)());
    }

    return count;
}

static int countNewItems( SyncSource *source )
{
    int res = countAnyItems(
        source,
        &SyncSource::getFirstNewItem,
        &SyncSource::getNextNewItem );
    return res;
}

static int countUpdatedItems( SyncSource *source )
{
    int res = countAnyItems(
        source,
        &SyncSource::getFirstUpdatedItem,
        &SyncSource::getNextUpdatedItem );
    return res;
}

static int countDeletedItems( SyncSource *source )
{
    int res = countAnyItems(
        source,
        &SyncSource::getFirstDeletedItem,
        &SyncSource::getNextDeletedItem );
    return res;
}

static int countItems( SyncSource *source )
{
    int res = countAnyItems(
        source,
        &SyncSource::getFirstItem,
        &SyncSource::getNextItem );
    return res;
}

int countItemsOfType(SyncSource *source, itemType type)
{
    int res = 0;
    
    switch(type) {
     case NEW_ITEMS:
        res = countNewItems(source);
        break;
     case UPDATED_ITEMS:
        res = countUpdatedItems(source);
        break;
     case DELETED_ITEMS:
        res = countDeletedItems(source);
        break;
     case TOTAL_ITEMS:
        res = countItems(source);
        break;
     default:
        CPPUNIT_ASSERT(false);
        break;
    }
    return res;
}

static void importItem(SyncSource *source, std::string &data)
{
    CPPUNIT_ASSERT(source);
    if (data.size()) {
        SyncItem item;
        item.setData( data.c_str(), (long)data.size() );
        item.setDataType( TEXT("raw") );
        int status;
        SOURCE_ASSERT_NO_FAILURE(source, status = source->addItem(item));
        CPPUNIT_ASSERT(status == STC_OK || status == STC_ITEM_ADDED);
        CPPUNIT_ASSERT(item.getKey() != 0);
        CPPUNIT_ASSERT(wcslen(item.getKey()) > 0);
    }
}

/** adds the supported tests to the instance itself */
void LocalTests::addTests() {
    if (config.createSourceA) {
        ADD_TEST(LocalTests, testOpen);
        ADD_TEST(LocalTests, testIterateTwice);
        if (config.insertItem) {
            ADD_TEST(LocalTests, testSimpleInsert);
            ADD_TEST(LocalTests, testLocalDeleteAll);
            ADD_TEST(LocalTests, testComplexInsert);

            if (config.updateItem) {
                ADD_TEST(LocalTests, testLocalUpdate);

                if (config.createSourceB) {
                    ADD_TEST(LocalTests, testChanges);
                }
            }

            if (config.import &&
                config.dump &&
                config.compare &&
                config.testcases) {
                ADD_TEST(LocalTests, testImport);
                ADD_TEST(LocalTests, testImportDelete);
            }

            if (config.templateItem &&
                config.uniqueProperties) {
                ADD_TEST(LocalTests, testManyChanges);
            }
        }
    }
}

/**
 * opens source and inserts the given item; can be called
 * regardless whether the data source already contains items or not
 *
 * The type of the item is unset; it is assumed that the source
 * can handle that.
 */
void LocalTests::insert(CreateSource createSource, const char *data) {
    // create source
    std::auto_ptr<SyncSource> source(createSource());
    CPPUNIT_ASSERT(source.get() != 0);

    // count number of already existing items
    SOURCE_ASSERT(source.get(), source->beginSync() == 0);
    int numItems;
    CPPUNIT_ASSERT_NO_THROW(numItems = countItems(source.get()));
    SyncItem item;
    item.setData(data, (long)strlen(data));
    int status;
    SOURCE_ASSERT_NO_FAILURE(source.get(), status = source->addItem(item));
    CPPUNIT_ASSERT(item.getKey() != 0);
    CPPUNIT_ASSERT(wcslen(item.getKey()) > 0);
    SOURCE_ASSERT(source.get(), source->endSync() == 0);

    // delete source again
    CPPUNIT_ASSERT_NO_THROW(source.reset());

    // two possible results:
    // - a new item was added
    // - the item was matched against an existing one
    CPPUNIT_ASSERT_NO_THROW(source.reset(createSource()));
    CPPUNIT_ASSERT(source.get() != 0);
    SOURCE_ASSERT(source.get(), source->beginSync() == 0);
    CPPUNIT_ASSERT(status == STC_OK || status == STC_ITEM_ADDED || status == STC_CONFLICT_RESOLVED_WITH_MERGE);
    CPPUNIT_ASSERT_EQUAL(numItems + (status == STC_CONFLICT_RESOLVED_WITH_MERGE ? 0 : 1),
                         countItems(source.get()));
    CPPUNIT_ASSERT(countNewItems(source.get()) == 0);
    CPPUNIT_ASSERT(countUpdatedItems(source.get()) == 0);
    CPPUNIT_ASSERT(countDeletedItems(source.get()) == 0);
    SOURCE_ASSERT(source.get(), source->endSync() == 0 );
    CPPUNIT_ASSERT_NO_THROW(source.reset());

#if 0
    /* source.createItem() is a SyncEvolution extension which cannot be used here */
    SyncItem *sameItem;
    SOURCE_ASSERT_NO_FAILURE(
        source,
        sameItem = source.createItem(item.getKey(), item.getState()));
    CPPUNIT_ASSERT(sameItem != 0);
    CPPUNIT_ASSERT(!strcmp( sameItem->getKey(), item.getKey()));
    delete sameItem;
#endif
}

/**
 * assumes that exactly one element is currently inserted and updates it with the given item
 *
 * The type of the item is cleared, as in insert() above.
 */
void LocalTests::update(CreateSource createSource, const char *data, bool check) {
    CPPUNIT_ASSERT(createSource.createSource);
    CPPUNIT_ASSERT(data);

    // create source
    std::auto_ptr<SyncSource> source(createSource());
    CPPUNIT_ASSERT(source.get() != 0);
    SOURCE_ASSERT(source.get(), source->beginSync() == 0);

    // get existing item, then update it
    SOURCE_ASSERT(source.get(), source->beginSync() == 0 );
    std::auto_ptr<SyncItem> item;
    SOURCE_ASSERT_NO_FAILURE(source.get(), item.reset(source->getFirstItem()) );
    CPPUNIT_ASSERT(item.get());
    item->setData(data, (long)strlen(data) + 1);
    item->setDataType(TEXT(""));
    SOURCE_ASSERT_EQUAL(source.get(), (int)STC_OK, source->updateItem(*item));
    SOURCE_ASSERT(source.get(), source->endSync() == 0);
    CPPUNIT_ASSERT_NO_THROW(source.reset());

    if (!check) {
        return;
    }

    // check that the right changes are reported when reopening the source
    SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSource()));
    SOURCE_ASSERT(source.get(), source->beginSync() == 0 );
    CPPUNIT_ASSERT_EQUAL(1, countItems(source.get()));
    CPPUNIT_ASSERT_EQUAL(0, countNewItems(source.get()));
    CPPUNIT_ASSERT_EQUAL(0, countUpdatedItems(source.get()));
    CPPUNIT_ASSERT_EQUAL(0, countDeletedItems(source.get()));
    std::auto_ptr<SyncItem> modifiedItem;
    SOURCE_ASSERT_NO_FAILURE(source.get(), modifiedItem.reset(source->getFirstItem()) );
    CPPUNIT_ASSERT(modifiedItem.get());
    CPPUNIT_ASSERT( wcslen( item->getKey() ) );
    CPPUNIT_ASSERT( !wcscmp( item->getKey(), modifiedItem->getKey() ) );
}

/** deletes all items locally via sync source */
void LocalTests::deleteAll(CreateSource createSource) {
    CPPUNIT_ASSERT(createSource.createSource);

    // create source
    std::auto_ptr<SyncSource> source(createSource());
    CPPUNIT_ASSERT(source.get() != 0);
    SOURCE_ASSERT(source.get(), source->beginSync() == 0);

    // delete all items
    std::auto_ptr<SyncItem> item;
    SOURCE_ASSERT_NO_FAILURE(source.get(), item.reset(source->getFirstItem()));
    while (item.get()) {
        SOURCE_ASSERT_EQUAL(source.get(), (int)STC_OK, source->deleteItem(*item));
        SOURCE_ASSERT_NO_FAILURE(source.get(), item.reset(source->getNextItem()));
    }
    SOURCE_ASSERT(source.get(), source->endSync() == 0);
    CPPUNIT_ASSERT_NO_THROW(source.reset());

    // check that all items are gone
    SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSource()));
    SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
    SOURCE_ASSERT_MESSAGE(
        "should be empty now",
        source.get(),
        countItems(source.get()) == 0);
    CPPUNIT_ASSERT_EQUAL( 0, countNewItems(source.get()) );
    CPPUNIT_ASSERT_EQUAL( 0, countUpdatedItems(source.get()) );
    CPPUNIT_ASSERT_EQUAL( 0, countDeletedItems(source.get()) );
    SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
    CPPUNIT_ASSERT_NO_THROW(source.reset());
}

/**
 * takes two databases, exports them,
 * then compares them using synccompare
 *
 * @param refFile      existing file with source reference items, NULL uses a dump of sync source A instead
 * @param copy         a sync source which contains the copied items, begin/endSync will be called
 * @param raiseAssert  raise assertion if comparison yields differences (defaults to true)
 */
void LocalTests::compareDatabases(const char *refFile, SyncSource &copy, bool raiseAssert) {
    CPPUNIT_ASSERT(config.dump);

    std::string sourceFile, copyFile;

    if (refFile) {
        sourceFile = refFile;
    } else {
        sourceFile = getCurrentTest() + ".source.test.dat";
        simplifyFilename(sourceFile);
        std::auto_ptr<SyncSource> source;
        SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceA()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
        SOURCE_ASSERT_EQUAL(source.get(), 0, config.dump(client, *source.get(), sourceFile.c_str()));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -