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

📄 clienttest.cpp

📁 This SDK allows to integrate a syncml stack in a C++ application on a variety of platforms. Current
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            sync(SYNC_TWO_WAY, ".deleteall.twoway", CheckSyncReport(0,0,0, 0,0,-1));
            break;
         case DELETE_ALL_REFRESH:
            // delete locally and then tell the server to "copy" the empty databases
            for (it = sources.begin(); it != sources.end(); ++it) {
                it->second->deleteAll(it->second->createSourceA);
            }
            sync(SYNC_REFRESH_FROM_CLIENT, ".deleteall.refreshserver", CheckSyncReport(0,0,0, 0,0,-1));
            break;
        }
    }

    /** get both clients in sync with empty server, then copy one item from client A to B */
    void doCopy() {
        // check requirements
        CPPUNIT_ASSERT(accessClientB);
        
        deleteAll();
        accessClientB->deleteAll();

        // insert into first database, copy to server
        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->testSimpleInsert();
        }
        sync(SYNC_TWO_WAY, ".send", CheckSyncReport(0,0,0, 1,0,0));

        // copy into second database
        accessClientB->sync(SYNC_TWO_WAY, ".recv", CheckSyncReport(1,0,0, 0,0,0));

        compareDatabases();
    }

    /**
     * replicate server database locally: same as SYNC_REFRESH_FROM_SERVER,
     * but done with explicit local delete and then a SYNC_SLOW because some
     * servers do no support SYNC_REFRESH_FROM_SERVER
     */
    void refreshClient() {
        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->deleteAll(it->second->createSourceA);
        }
        sync(SYNC_SLOW, ".refresh", CheckSyncReport(-1,0,0, 0,0,0));
    }

    // do a two-way sync without additional checks
    void testTwoWaySync() {
        sync(SYNC_TWO_WAY);
    }
    // do a slow sync without additional checks
    void testSlowSync() {
        sync(SYNC_SLOW);
    }
    // do a refresh from server sync without additional checks
    void testRefreshFromServerSync() {
        sync(SYNC_REFRESH_FROM_SERVER);
    }

    // do a refresh from client sync without additional checks
    void testRefreshFromClientSync() {
        sync(SYNC_REFRESH_FROM_CLIENT);
    }
    
    // delete all items, locally and on server using two-way sync
    void testDeleteAllSync() {
        deleteAll(DELETE_ALL_SYNC);
    }
    
    // delete all items, locally and on server using refresh-from-client sync
    void testDeleteAllRefresh() {
        source_it it;

        // copy something to server first; doesn't matter whether it has the
        // item already or not, as long as it exists there afterwards
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->testSimpleInsert();
        }
        sync(SYNC_SLOW, ".insert");

        // now ensure we can delete it
        deleteAll(DELETE_ALL_SYNC);
    
        // nothing stored locally?
        for (it = sources.begin(); it != sources.end(); ++it) {
            std::auto_ptr<SyncSource> source;
            SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(it->second->createSourceA()));
            SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
            SOURCE_ASSERT_EQUAL(source.get(), 0, countItems(source.get()));
            SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
            CPPUNIT_ASSERT_NO_THROW(source.reset());
        }

        // make sure server really deleted everything
        sync(SYNC_SLOW, ".check", CheckSyncReport(0,0,0, 0,0,0));
        for (it = sources.begin(); it != sources.end(); ++it) {
            std::auto_ptr<SyncSource> source;
            SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(it->second->createSourceA()));
            SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
            SOURCE_ASSERT_EQUAL(source.get(), 0, countItems(source.get()));
            SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
            CPPUNIT_ASSERT_NO_THROW(source.reset());
        }
    }

    // test that a refresh sync of an empty server leads to an empty datatbase
    void testRefreshSemantic() {
        source_it it;

        // clean client and server
        deleteAll();

        // insert item, then refresh from empty server
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->testSimpleInsert();
        }
        sync(SYNC_REFRESH_FROM_SERVER, "", CheckSyncReport(0,0,-1, 0,0,0));

        // check
        for (it = sources.begin(); it != sources.end(); ++it) {
            std::auto_ptr<SyncSource> source;
            SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(it->second->createSourceA()));
            SOURCE_ASSERT_EQUAL(source.get(), 0, source->beginSync());
            SOURCE_ASSERT_EQUAL(source.get(), 0, countItems(source.get()));
            SOURCE_ASSERT_EQUAL(source.get(), 0, source->endSync());
            CPPUNIT_ASSERT_NO_THROW(source.reset());
        }
    }

    // tests the following sequence of events:
    // - insert item
    // - delete all items
    // - insert one other item
    // - refresh from client
    // => no items should now be listed as new, updated or deleted for this client during another sync
    void testRefreshStatus() {
        source_it it;

        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->testSimpleInsert();
        }
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->deleteAll(it->second->createSourceA);
        }
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->testSimpleInsert();
        }
        sync(SYNC_REFRESH_FROM_CLIENT, ".refresh-from-client", CheckSyncReport(0,0,0 /* 1,0,0 - not sure exactly what the server will be told */));
        sync(SYNC_TWO_WAY, ".two-way", CheckSyncReport(0,0,0, 0,0,0));
    }

    // test that a two-way sync copies an item from one address book into the other
    void testCopy() {
        doCopy();
        compareDatabases();
    }

    // test that a two-way sync copies updates from database to the other client,
    // using simple data commonly supported by servers
    void testUpdate() {
        CPPUNIT_ASSERT(sources.begin() != sources.end());
        CPPUNIT_ASSERT(sources.begin()->second->config.updateItem);

        // setup client A, B and server so that they all contain the same item
        doCopy();

        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->update(it->second->createSourceA, it->second->config.updateItem);
        }

        sync(SYNC_TWO_WAY, ".update", CheckSyncReport(0,0,0, 0,1,0));
        accessClientB->sync(SYNC_TWO_WAY, ".update", CheckSyncReport(0,1,0, 0,0,0));

        compareDatabases();
    }

    // test that a two-way sync copies updates from database to the other client,
    // using data that some, but not all servers support, like adding a second
    // phone number to a contact
    void testComplexUpdate() {
        // setup client A, B and server so that they all contain the same item
        doCopy();

        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->update(it->second->createSourceA, it->second->config.complexUpdateItem);
        }

        sync(SYNC_TWO_WAY, ".update", CheckSyncReport(0,0,0, 0,1,0));
        accessClientB->sync(SYNC_TWO_WAY, ".update", CheckSyncReport(0,1,0, 0,0,0));

        compareDatabases();
    }

        
    // test that a two-way sync deletes the copy of an item in the other database
    void testDelete() {
        // setup client A, B and server so that they all contain the same item
        doCopy();

        // delete it on A
        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->deleteAll(it->second->createSourceA);
        }

        // transfer change from A to server to B
        sync(SYNC_TWO_WAY, ".delete", CheckSyncReport(0,0,0, 0,0,1));
        accessClientB->sync(SYNC_TWO_WAY, ".delete", CheckSyncReport(0,0,1, 0,0,0));

        // check client B: shouldn't have any items now
        for (it = sources.begin(); it != sources.end(); ++it) {
            std::auto_ptr<SyncSource> copy;
            SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(it->second->createSourceA()));
            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());
        }
    }
    
    // test what the server does when it finds that different
    // fields of the same item have been modified
    void testMerge() {
        // setup client A, B and server so that they all contain the same item
        doCopy();

        // update in client A
        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->update(it->second->createSourceA, it->second->config.mergeItem1);
        }

        // update in client B
        for (it = accessClientB->sources.begin(); it != accessClientB->sources.end(); ++it) {
            it->second->update(it->second->createSourceA, it->second->config.mergeItem2);
        }

        // send change to server from client A (no conflict), then from B (conflict)
        sync(SYNC_TWO_WAY, ".send", CheckSyncReport(0,0,0, 0,1,0));
        sync(SYNC_TWO_WAY, ".recv");

        // figure out how the conflict during ".recv" was handled
        for (it = accessClientB->sources.begin(); it != accessClientB->sources.end(); ++it) {
            std::auto_ptr<SyncSource> copy;
            SOURCE_ASSERT_NO_FAILURE(copy.get(), copy.reset(it->second->createSourceA()));
            SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->beginSync());
            int numItems;
            SOURCE_ASSERT_NO_FAILURE(copy.get(), numItems = countItems(copy.get()));
            SOURCE_ASSERT_EQUAL(copy.get(), 0, copy->endSync());
            CPPUNIT_ASSERT(numItems >= 1);
            CPPUNIT_ASSERT(numItems <= 2);
            std::cout << " " << it->second->config.sourceName << ": " << (numItems == 1 ? "conflicting items were merged" : "both of the conflicting items were preserved") << " ";
            std::cout.flush();
            CPPUNIT_ASSERT_NO_THROW(copy.reset());
        }
    }

    // test what the server does when it has to execute a slow sync
    // with identical data on client and server:
    // expected behaviour is that nothing changes
    void testTwinning() {
        // clean server and client A
        deleteAll();

        // import test data
        source_it it;
        for (it = sources.begin(); it != sources.end(); ++it) {
            it->second->testImport();
        }

        // send to server
        sync(SYNC_TWO_WAY, ".send");

        // ensure that client has the same data, thus ignoring data conversion
        // issues (those are covered by testItems())
        refreshClient();

        // copy to client B to have another copy
        accessClientB->refreshClient();

        // slow sync should not change anything
        sync(SYNC_TWO_WAY, ".twinning");

        // check
        compareDatabases();
    }

    // tests one-way sync from server:
    // - get both clients and server in sync with no items anywhere
    // - add one item on first client, copy to server
    // - add a different item on second client, one-way-from-server
    // - two-way sync with first client
    // => one item on first client, two on second
    // - delete on first client, sync that to second client
    //   via two-way sync + one-way-from-server

⌨️ 快捷键说明

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