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

📄 clienttest.cpp

📁 This SDK allows to integrate a syncml stack in a C++ application on a variety of platforms. Current
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
        SOURCE_ASSERT_EQUAL(source.get(), 1, countItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countNewItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countUpdatedItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countDeletedItems(source.get()));
        std::auto_ptr<SyncItem> item;
        SOURCE_ASSERT_NO_FAILURE(source.get(), item.reset(source->getFirstItem()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
        CPPUNIT_ASSERT_NO_THROW(source.reset());

        // delete item again via sync source A
        deleteAll(createSourceA);
        SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceB()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
        SOURCE_ASSERT_EQUAL(source.get(), 0, countItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countNewItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countUpdatedItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 1, countDeletedItems(source.get()));
        std::auto_ptr<SyncItem> deletedItem;
        SOURCE_ASSERT_NO_FAILURE(source.get(), deletedItem.reset(source->getFirstDeletedItem()));
        CPPUNIT_ASSERT( wcslen( item->getKey() ) );
        CPPUNIT_ASSERT( wcslen( deletedItem->getKey() ) );
        CPPUNIT_ASSERT( !wcscmp( item->getKey(), deletedItem->getKey() ) );
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
        CPPUNIT_ASSERT_NO_THROW(source.reset());

        // insert another item via sync source A
        testSimpleInsert();
        SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceB()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
        SOURCE_ASSERT_EQUAL(source.get(), 1, countItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 1, countNewItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countUpdatedItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countDeletedItems(source.get()));
        SOURCE_ASSERT_NO_FAILURE(source.get(), item.reset(source->getFirstItem()));
        std::auto_ptr<SyncItem> newItem;
        SOURCE_ASSERT_NO_FAILURE(source.get(), newItem.reset(source->getFirstNewItem()));
        CPPUNIT_ASSERT( wcslen( item->getKey() ) );
        CPPUNIT_ASSERT( wcslen( newItem->getKey() ) );
        CPPUNIT_ASSERT( !wcscmp( item->getKey(), newItem->getKey() ) );
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
        CPPUNIT_ASSERT_NO_THROW(source.reset());

        // update item via sync source A
        update(createSourceA, config.updateItem);
        SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceB()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
        SOURCE_ASSERT_EQUAL(source.get(), 1, countItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countNewItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 1, countUpdatedItems(source.get()));
        SOURCE_ASSERT_EQUAL(source.get(), 0, countDeletedItems(source.get()));
        std::auto_ptr<SyncItem> updatedItem;
        SOURCE_ASSERT_NO_FAILURE(source.get(), updatedItem.reset(source->getFirstUpdatedItem()));
        CPPUNIT_ASSERT( wcslen( item->getKey() ) );
        CPPUNIT_ASSERT( wcslen( updatedItem->getKey() ) );
        CPPUNIT_ASSERT( !wcscmp( item->getKey(), updatedItem->getKey() ) );
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
        CPPUNIT_ASSERT_NO_THROW(source.reset());
    }

    // clean database, import file, then export again and compare
    void testImport() {
        // check additional requirements
        CPPUNIT_ASSERT(config.import);
        CPPUNIT_ASSERT(config.dump);
        CPPUNIT_ASSERT(config.compare);
        CPPUNIT_ASSERT(config.testcases);
        
        testLocalDeleteAll();

        // import via sync source A
        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.import(client, *source.get(), config.testcases));
        SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
        CPPUNIT_ASSERT_NO_THROW(source.reset());

        // export again and compare against original file
        std::auto_ptr<SyncSource> copy;
        SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceA()));
        compareDatabases(config.testcases, *copy.get());
        CPPUNIT_ASSERT_NO_THROW(source.reset());
    }

    // same as testImport() with immediate delete
    void testImportDelete() {
        testImport();

        // delete again, because it was observed that this did not
        // work right with calendars in SyncEvolution
        testLocalDeleteAll();
    }

    // test change tracking with large number of items
    void testManyChanges() {
        // check additional requirements
        CPPUNIT_ASSERT(config.templateItem);
        CPPUNIT_ASSERT(config.uniqueProperties);
        
        deleteAll(createSourceA);

        // check that everything is empty, also resets change counter of sync source B
        std::auto_ptr<SyncSource> copy;
        SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceB()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->beginSync());
        SOURCE_ASSERT_EQUAL(copy.get(), 0, countItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->endSync());
        CPPUNIT_ASSERT_NO_THROW(copy.reset());

        // now insert plenty of items
        int numItems = insertManyItems(createSourceA);

        // check that exactly this number of items is listed as new
        SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceB()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->beginSync());
        SOURCE_ASSERT_EQUAL(copy.get(), numItems, countItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), numItems, countNewItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, countUpdatedItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, countDeletedItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->endSync());
        CPPUNIT_ASSERT_NO_THROW(copy.reset());

        // delete all items
        deleteAll(createSourceA);

        // verify again
        SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(createSourceB()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, countItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, countNewItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, countUpdatedItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), numItems, countDeletedItems(copy.get()));
        SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->endSync());
        CPPUNIT_ASSERT_NO_THROW(copy.reset());
    }
};

/**
 * Tests synchronization with one or more sync sources enabled.
 * When testing multiple sources at once only the first config
 * is checked to see which tests can be executed.
 */
class SyncTests : public CppUnit::TestSuite, public CppUnit::TestFixture {
public:
    /** the client we are testing */
    ClientTest &client;

    SyncTests(const std::string &name, ClientTest &cl, std::vector<int> sourceIndices, bool isClientA = true) :
        CppUnit::TestSuite(name),
        client(cl) {
        sourceArray = new int[sourceIndices.size() + 1];
        for (std::vector<int>::iterator it = sourceIndices.begin();
             it != sourceIndices.end();
             ++it) {
            ClientTest::Config config;
            client.getSourceConfig(*it, config);

            if (config.sourceName) {
                sourceArray[sources.size()] = *it;
                sources.push_back(std::pair<int,LocalTests *>(*it, new LocalTests(config.sourceName, cl, *it, config)));
            }
        }
        sourceArray[sources.size()] = -1;

        // check whether we have a second client
        ClientTest *clientB = cl.getClientB();
        if (clientB) {
            accessClientB = new SyncTests(name, *clientB, sourceIndices, false);
        } else {
            accessClientB = 0;
        }
    }

    ~SyncTests() {
        for (source_it it = sources.begin();
             it != sources.end();
             ++it) {
            delete it->second;
        }
        delete [] sourceArray;
        if (accessClientB) {
            delete accessClientB;
        }
    }

    /** adds the supported tests to the instance itself */
    void addTests() {
        if (sources.size()) {
            const ClientTest::Config &config(sources[0].second->config);

            // run this test first, even if it is more complex:
            // if it works, all the following tests will run with
            // the server in a deterministic state
            if (config.createSourceA) {
                if (config.insertItem) {
                    ADD_TEST(SyncTests, testDeleteAllRefresh);
                }
            }

            ADD_TEST(SyncTests, testTwoWaySync);
            ADD_TEST(SyncTests, testSlowSync);
            ADD_TEST(SyncTests, testRefreshFromServerSync);
            ADD_TEST(SyncTests, testRefreshFromClientSync);

            if (config.createSourceA) {
                if (config.insertItem) {
                    ADD_TEST(SyncTests, testRefreshSemantic);
                    ADD_TEST(SyncTests, testRefreshStatus);

                    if (accessClientB &&
                        config.dump &&
                        config.compare) {
                        ADD_TEST(SyncTests, testCopy);
                        ADD_TEST(SyncTests, testDelete);
                        ADD_TEST(SyncTests, testAddUpdate);
                        ADD_TEST(SyncTests, testManyItems);

                        if (config.updateItem) {
                            ADD_TEST(SyncTests, testUpdate);
                        }
                        if (config.complexUpdateItem) {
                            ADD_TEST(SyncTests, testComplexUpdate);
                        }
                        if (config.mergeItem1 && config.mergeItem2) {
                            ADD_TEST(SyncTests, testMerge);
                        }
                        if (config.import) {
                            ADD_TEST(SyncTests, testTwinning);
                            ADD_TEST(SyncTests, testItems);
                        }
                        if (config.templateItem) {
                            ADD_TEST(SyncTests, testMaxMsg);
                            ADD_TEST(SyncTests, testLargeObject);
                            ADD_TEST(SyncTests, testLargeObjectBin);
                            if (client.isB64Enabled()) {
                                ADD_TEST(SyncTests, testLargeObjectEncoded);
                            }
                            ADD_TEST(SyncTests, testOneWayFromServer);
                            ADD_TEST(SyncTests, testOneWayFromClient);
                        }
                    }
                }
            }
        }
    }

private:
    /** list with all local test classes for manipulating the sources and their index in the client */
    std::vector< std::pair<int, LocalTests *> > sources;
    typedef std::vector< std::pair<int, LocalTests *> >::iterator source_it;

    /** the indices from sources, terminated by -1 (for sync()) */
    int *sourceArray;

    /** utility functions for second client */
    SyncTests *accessClientB;

    enum DeleteAllMode {
        DELETE_ALL_SYNC,   /**< make sure client and server are in sync,
                              delete locally,
                              sync again */
        DELETE_ALL_REFRESH /**< delete locally, refresh server */
    };

    /** compare databases of first and second client */
    void compareDatabases() {
        source_it it1;
        source_it it2;

        CPPUNIT_ASSERT(accessClientB);
        for (it1 = sources.begin(), it2 = accessClientB->sources.begin();
             it1 != sources.end() && it2 != accessClientB->sources.end();
             ++it1, ++it2) {
            std::auto_ptr<SyncSource> copy;
            SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(it2->second->createSourceB()));
            it1->second->compareDatabases(NULL, *copy.get());
            CPPUNIT_ASSERT_NO_THROW(copy.reset());
        }
        CPPUNIT_ASSERT(it1 == sources.end());
        CPPUNIT_ASSERT(it2 == accessClientB->sources.end());
    }
    
    /** deletes all items locally and on server */
    void deleteAll(DeleteAllMode mode = DELETE_ALL_SYNC) {
        source_it it;
        
        switch(mode) {
         case DELETE_ALL_SYNC:
            // a refresh from server would slightly reduce the amount of data exchanged, but not all servers support it
            for (it = sources.begin(); it != sources.end(); ++it) {
                it->second->deleteAll(it->second->createSourceA);
            }
            sync(SYNC_SLOW, ".deleteall.init");
            // now that client and server are in sync, delete locally and sync again
            for (it = sources.begin(); it != sources.end(); ++it) {
                it->second->deleteAll(it->second->createSourceA);
            }

⌨️ 快捷键说明

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