/** @short Check that the STATUS processing does not break offline "sync" */
void OfflineTest::testStatusVsExistsCached()
{
    QString mailbox = QLatin1String("a");

    // Push the data to the cache
    existsA = 10;
    uidNextA = 11;
    uidValidityA = 666;
    SyncState sync;
    sync.setExists(existsA);
    sync.setUidValidity(uidValidityA);
    sync.setUidNext(uidNextA);
    for (uint i = 1; i <= existsA; ++i)
        uidMapA << i;
    model->cache()->setMailboxSyncState(mailbox, sync);
    model->cache()->setUidMapping(mailbox, uidMapA);

    // Request the STATUS command to see how many messages are in there. This is not a synchronization, though
    // -- Trojita is *not* opening that mailbox, so the previously cached data remain.
    QCOMPARE(idxA.data(RoleTotalMessageCount).toInt(), 0);
    cClient(t.mk("STATUS a (MESSAGES UNSEEN RECENT)\r\n"));
    cServer("* STATUS a (MESSAGES 42 UNSEEN 2 RECENT 3)\r\n" + t.last("OK status\r\n"));
    QCOMPARE(idxA.data(RoleTotalMessageCount).toInt(), 42);
    LibMailboxSync::setModelNetworkPolicy(model, NETWORK_OFFLINE);
    cClient(t.mk("LOGOUT\r\n"));
    cServer(t.last("OK logged out\r\n") + "* BYE see ya\r\n");
    model->resyncMailbox(idxA);
    for (int i = 0; i < 10; ++i)
        QCoreApplication::processEvents();
    QCOMPARE(model->rowCount(msgListA), static_cast<int>(existsA));
    helperVerifyUidMapA();
    helperCheckCache();
}
Exemple #2
0
/** @short Helper: verify that values recorded in the cache are valid */
void LibMailboxSync::helperCheckCache(bool ignoreUidNext)
{
    using namespace Imap::Mailbox;

    // Check the cache
    SyncState syncState = model->cache()->mailboxSyncState(QLatin1String("a"));
    QCOMPARE(syncState.exists(), existsA);
    QCOMPARE(syncState.isUsableForSyncing(), true);
    if (!ignoreUidNext) {
        QCOMPARE(syncState.uidNext(), uidNextA);
    }
    QCOMPARE(syncState.uidValidity(), uidValidityA);
    QCOMPARE(model->cache()->uidMapping(QLatin1String("a")), uidMapA);
    QCOMPARE(static_cast<uint>(uidMapA.size()), existsA);

    SyncState ssFromTree = model->findMailboxByName(QLatin1String("a"))->syncState;
    SyncState ssFromCache = syncState;
    if (ignoreUidNext) {
        ssFromTree.setUidNext(0);
        ssFromCache.setUidNext(0);
    }
    QCOMPARE(ssFromCache, ssFromTree);

    if (model->isNetworkAvailable()) {
        // when offline, calling cEmpty would assert fail
        cEmpty();
    }

    QVERIFY(errorSpy->isEmpty());
}
Exemple #3
0
void
Dispatcher::Did_SyncLog_StateChange_Execute(SyncStateMsgPtr stateMsg)
{
  int size = stateMsg->state_size();
  int index = 0;
  // iterate and fetch the actions
  for (; index < size; index++) {
    SyncState state = stateMsg->state(index);
    if (state.has_old_seq() && state.has_seq()) {
      uint64_t oldSeq = state.old_seq();
      uint64_t newSeq = state.seq();
      Name userName(reinterpret_cast<const unsigned char*>(state.name().c_str()),
                    state.name().size());

      // fetch actions with oldSeq + 1 to newSeq (inclusive)
      Name actionNameBase = Name("/")(userName)(CHRONOSHARE_APP)("action")(m_sharedFolder);

      m_actionFetcher->Enqueue(userName, actionNameBase, std::max<uint64_t>(oldSeq + 1, 1), newSeq,
                               FetchManager::PRIORITY_HIGH);
    }
  }
}
void SyncStateUpdater::UpdateSyncState(MojSignal<>::SlotRef slot, const SyncState& syncState, bool clearSyncState)
{
	m_doneSignal.connect(slot);

	MojErr err;
	MojObject batchPayload;
	MojObject batchOperations;

	// Delete old sync state

	MojObject delPayload;

	MojDbQuery query;

	err = query.from(SyncStateAdapter::SYNC_STATE_KIND);
	ErrorToException(err);

	MojString capabilityProvider;
	capabilityProvider.assign(m_capabilityProvider.c_str());
	err = query.where(SyncStateAdapter::CAPABILITY_PROVIDER, MojDbQuery::OpEq, capabilityProvider);
	ErrorToException(err);

	err = query.where(SyncStateAdapter::ACCOUNT_ID, MojDbQuery::OpEq, syncState.GetAccountId());
	ErrorToException(err);

	err = query.where(SyncStateAdapter::COLLECTION_ID, MojDbQuery::OpEq, syncState.GetCollectionId());
	ErrorToException(err);

	MojObject queryObj;
	err = query.toObject(queryObj);
	ErrorToException(err);

	err = delPayload.put("query", queryObj);
	ErrorToException(err);

	MojObject delOperation;
	err = delOperation.putString("method", "del");
	ErrorToException(err);
	err = delOperation.put("params", delPayload);
	ErrorToException(err);

	err = batchOperations.push(delOperation);
	ErrorToException(err);

	if(!clearSyncState) { // Store new sync state
		MojObject putPayload;

		MojObject syncStateObj;
		SyncStateAdapter::SerializeToDatabaseObject(syncState, syncStateObj, m_capabilityProvider.c_str(), m_busAddress.c_str());

		MojObject objects;
		err = objects.push(syncStateObj);
		ErrorToException(err);

		err = putPayload.put("objects", objects);
		ErrorToException(err);

		MojObject putOperation;
		err = putOperation.putString("method", "put");
		ErrorToException(err);
		err = putOperation.put("params", putPayload);
		ErrorToException(err);

		err = batchOperations.push(putOperation);
		ErrorToException(err);
	}

	err = batchPayload.put("operations", batchOperations);
	ErrorToException(err);

	// Note: batch operations are not atomic, this is just for convenience and performance
	m_busClient.SendRequest(m_updateSlot, "com.palm.tempdb", "batch", batchPayload);
}
/** @short Check that cached mailboxes do not send away STATUS when they are going to be immediately replaced anyway */
void ImapModelListChildMailboxesTest::testNoStatusForCachedItems()
{
    using namespace Imap::Mailbox;

    // Remember two mailboxes
    model->cache()->setChildMailboxes(QString(), QList<MailboxMetadata>()
                                      << MailboxMetadata(QStringLiteral("a"), QStringLiteral("."), QStringList())
                                      << MailboxMetadata(QStringLiteral("b"), QStringLiteral("."), QStringList())
                                      );
    // ... and the numbers for the first of them
    SyncState s;
    s.setExists(10);
    s.setRecent(1);
    s.setUnSeenCount(2);
    QVERIFY(s.isUsableForNumbers());
    model->cache()->setMailboxSyncState(QStringLiteral("b"), s);

    // touch the network
    QCOMPARE(model->rowCount(QModelIndex()), 1);
    cClient(t.mk("LIST \"\" \"%\"\r\n"));
    // ...but the data gets refreshed from cache immediately
    QCOMPARE(model->rowCount(QModelIndex()), 3);

    // just settings up indexes
    idxA = model->index(1, 0, QModelIndex());
    QVERIFY(idxA.isValid());
    QCOMPARE(idxA.data(RoleMailboxName).toString(), QString::fromUtf8("a"));
    idxB = model->index(2, 0, QModelIndex());
    QVERIFY(idxB.isValid());
    QCOMPARE(idxB.data(RoleMailboxName).toString(), QString::fromUtf8("b"));

    // Request message counts; this should not lead to network activity even though the actual number
    // is not stored in the cache for mailbox "a", simply because the whole mailbox will get replaced
    // after the LIST finishes anyway
    QCOMPARE(idxA.data(RoleTotalMessageCount), QVariant());
    QCOMPARE(idxA.data(RoleMailboxNumbersFetched).toBool(), false);
    QCOMPARE(idxB.data(RoleTotalMessageCount).toInt(), 10);
    QCOMPARE(idxB.data(RoleMailboxNumbersFetched).toBool(), false);
    cEmpty();

    cServer("* LIST (\\HasNoChildren) \".\" a\r\n"
            "* LIST (\\HasNoChildren) \".\" b\r\n"
            + t.last("OK listed\r\n"));
    cEmpty();

    // The mailboxes are replaced now -> rebuild the indexes
    QVERIFY(!idxA.isValid());
    QVERIFY(!idxB.isValid());
    idxA = model->index(1, 0, QModelIndex());
    QVERIFY(idxA.isValid());
    QCOMPARE(idxA.data(RoleMailboxName).toString(), QString::fromUtf8("a"));
    idxB = model->index(2, 0, QModelIndex());
    QVERIFY(idxB.isValid());
    QCOMPARE(idxB.data(RoleMailboxName).toString(), QString::fromUtf8("b"));

    // Ask for the numbers again
    QCOMPARE(idxA.data(RoleTotalMessageCount), QVariant());
    QCOMPARE(idxB.data(RoleTotalMessageCount), QVariant());
    QByteArray c1 = t.mk("STATUS a (MESSAGES UNSEEN RECENT)\r\n");
    QByteArray r1 = t.last("OK status\r\n");
    QByteArray c2 = t.mk("STATUS b (MESSAGES UNSEEN RECENT)\r\n");
    QByteArray r2 = t.last("OK status\r\n");
    cClient(c1 + c2);
    cServer("* STATUS a (MESSAGES 1 RECENT 2 UNSEEN 3)\r\n"
            "* STATUS b (MESSAGES 666 RECENT 33 UNSEEN 2)\r\n");
    QCOMPARE(idxA.data(RoleTotalMessageCount).toInt(), 1);
    QCOMPARE(idxA.data(RoleMailboxNumbersFetched).toBool(), true);
    QCOMPARE(idxB.data(RoleTotalMessageCount).toInt(), 666);
    QCOMPARE(idxB.data(RoleMailboxNumbersFetched).toBool(), true);
    QCOMPARE(model->cache()->mailboxSyncState(QLatin1String("a")).unSeenCount(), 3u);
    QCOMPARE(model->cache()->mailboxSyncState(QLatin1String("a")).recent(), 2u);
    // the "EXISTS" is missing, though
    QVERIFY(!model->cache()->mailboxSyncState(QLatin1String("a")).isUsableForNumbers());
    QCOMPARE(model->cache()->mailboxSyncState(QLatin1String("b")).unSeenCount(), 2u);
    QCOMPARE(model->cache()->mailboxSyncState(QLatin1String("b")).recent(), 33u);
    // The mailbox state for mailbox "b" must be preserved
    QCOMPARE(model->cache()->mailboxSyncState(QLatin1String("b")).exists(), 10u);
    QVERIFY(model->cache()->mailboxSyncState(QLatin1String("b")).isUsableForNumbers());
    cServer(r2 + r1);
    cEmpty();
}