From 108eefcf1668bac09efe11bc7451ab311c90eeaa Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Thu, 28 Nov 2019 15:55:54 +0100 Subject: [PATCH 1/7] adding method to use old algorithm using cloning --- src/colnod/syncmanager.cpp | 99 +++++++++++++++++++++++ src/colnod/syncmanager.h | 1 + test/auto/syncmanager/tst_syncmanager.cpp | 3 +- 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index cccecec..8a20701 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -136,6 +136,105 @@ std::unique_ptr SyncManager::prepareDataNew(const std::shared_ptr< return nullptr; } +std::unique_ptr SyncManager::prepareDataUsindOld(const std::shared_ptr &databaseData, const std::shared_ptr &colnodData) +{ + Q_UNUSED(databaseData); + Q_UNUSED(colnodData); + + qInfo(syncmanager) << equals; + qInfo(syncmanager) << "PREPARING DATA -> BEGIN"; + qInfo(syncmanager) << dash; + qInfo(syncmanager) << "Resolve conflicts ( changes on same item on both Colnod and DB ):"; + qInfo(syncmanager) << dash; + + + Q_ASSERT(colnodData); + Q_ASSERT(databaseData); + + + // TODO: why copy data? + std::shared_ptr cloneColnodDataToProcess = std::make_shared(*colnodData); + std::shared_ptr cloneDatabaseDataToProcess = std::make_shared(*databaseData); + + QList conflicts; + QList alreadySynced; + + // check modifed tokens from colnod, dont want update token, if it was edited in db after or has been already synced + for (const auto &colnodToken : cloneColnodDataToProcess->updatedTokens) { + if (cloneDatabaseDataToProcess->updatedTokens.contains(colnodToken->id())) { + // updated in db later + if (cloneDatabaseDataToProcess->updatedTokens.value(colnodToken->id()) > colnodToken) { + conflicts.append(colnodToken->id()); + } + continue; + } + auto token = database->getToken(colnodToken->id()); + if ( token ) + // alredy synced ( tokens are same ) + if (token == colnodToken) + alreadySynced.append(colnodToken->id()); + } + // remove tokens which should be not updated + for (const auto &id : conflicts) + cloneColnodDataToProcess->updatedTokens.remove(id); + for (const auto &id : alreadySynced) + cloneColnodDataToProcess->updatedTokens.remove(id); + + qInfo(syncmanager) << tab << "-> COLNOD DATA - CHANGES:"; + qInfo(syncmanager) << tab << tab << conflicts.size() << "TOKENS WERE ADDED/UPDATED IN DATABASE TOO"; + qInfo(syncmanager) << tab << tab << alreadySynced.size() << "TOKENS WERE ALREADY SYNCED"; + + + + conflicts.clear(); + + // chech for already deleted ( in previous synced tokens were deleted from colnod, so it come to this sync but we dont want to sync it again + for (const auto &id : cloneColnodDataToProcess->deletedTokens) { + if (database->isAlreadyDeleted(id)) { + conflicts.append(id); + } + } + for (const auto &id : conflicts) { + cloneColnodDataToProcess->deletedTokens.removeOne(id); + } + + qInfo(syncmanager) << tab << tab << conflicts.size() << "TOKENS WERE ALREADY DELETED"; + qInfo(syncmanager) << dash; + + conflicts.clear(); + + // chech modified from db, remove token if it was edited in colnod later + for (const auto &databaseToken : cloneDatabaseDataToProcess->updatedTokens) { + if (cloneColnodDataToProcess->updatedTokens.contains(databaseToken->id())) { + if (databaseToken < cloneColnodDataToProcess->updatedTokens.value(databaseToken->id())) + conflicts.append(databaseToken->id()); + } + else { + // restriction cauesed by colnod rest api + if (databaseToken->description() != "mobile") { + qCritical(syncmanager) << "Token:" << databaseToken->id() << "doesn't have 'mobile' in description, can't be "; + conflicts.append(databaseToken->id()); + } + } + } + for (const auto &id : conflicts) + cloneColnodDataToProcess->updatedTokens.remove(id); + + qInfo(syncmanager) << tab << "-> DATABASE DATA - CHANGES:"; + qInfo(syncmanager) << tab << tab << conflicts.size() << "TOKENS WERE ADDED/UPDATED IN IN COLNOD TOO"; + qInfo(syncmanager) << dash; + + qInfo(syncmanager) << "PREPARING DATA -> FINISHED"; + qInfo(syncmanager) << equals; + + // Prepare data + auto preparedData = std::make_unique(); + preparedData->colnodData = cloneColnodDataToProcess; + preparedData->databaseData = databaseDataToProcess; + + return preparedData; +} + bool SyncManager::downloadData() { bool res = true; diff --git a/src/colnod/syncmanager.h b/src/colnod/syncmanager.h index 5fbfa31..21a9749 100644 --- a/src/colnod/syncmanager.h +++ b/src/colnod/syncmanager.h @@ -26,6 +26,7 @@ private: * @todo rename when removed old aproach */ std::unique_ptr prepareDataNew(const std::shared_ptr &databaseData, const std::shared_ptr &colnodData); + std::unique_ptr prepareDataUsindOld(const std::shared_ptr &databaseData, const std::shared_ptr &colnodData); private: bool downloadData(); diff --git a/test/auto/syncmanager/tst_syncmanager.cpp b/test/auto/syncmanager/tst_syncmanager.cpp index ff3fbaf..b190c83 100644 --- a/test/auto/syncmanager/tst_syncmanager.cpp +++ b/test/auto/syncmanager/tst_syncmanager.cpp @@ -18,12 +18,13 @@ void SyncManagerTest::sync_init_test() QVERIFY(sync.databaseInitialization()); } + void SyncManagerTest::prepareData_test() { SyncManager sync(true); auto dbData = std::make_shared(); auto colnodData = std::make_shared(); - QVERIFY2(sync.prepareDataNew(dbData, colnodData), "finish unitest"); + QVERIFY2(sync.prepareDataUsindOld(dbData, colnodData), "finish unitest"); } QTEST_MAIN(SyncManagerTest) From aeb2782920f2c11d10f10fdb65a6387bd76f4515 Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Mon, 2 Dec 2019 10:03:13 +0100 Subject: [PATCH 2/7] clang: fixing warnings --- src/app/main.cpp | 4 ++-- src/colnod/colnodapi.cpp | 23 +++++++++++------------ src/colnod/colnodapi.h | 12 ++++++------ src/colnod/data.h | 8 +++++--- src/colnod/databaseapi.cpp | 9 +++------ src/colnod/databaseapi.h | 10 +++++----- src/colnod/syncmanager.cpp | 4 ++-- src/colnod/syncmanager.h | 2 +- test/auto/colnod/tst_colnodapi.cpp | 4 ++-- test/auto/syncmanager/tst_syncmanager.cpp | 8 +++++++- 10 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index 34b50bf..3b35c33 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -45,13 +45,13 @@ int main(int argc, char *argv[]) // Initialize database and colnod API if (!syncManager.databaseInitialization()) { - qCritical("Not possible to initialize sync application"); + qCritical() << "Not possible to initialize sync application"; return -1; } // Synchronizaiton if (!syncManager.startSynchronization()) { - qCritical("Not possible to start synchronization"); + qCritical() << "Not possible to start synchronization"; return -1; } diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp index 1433581..fc283d8 100644 --- a/src/colnod/colnodapi.cpp +++ b/src/colnod/colnodapi.cpp @@ -1,10 +1,12 @@ #include "colnodapi.h" +#include + Q_LOGGING_CATEGORY(colnod, "colnod.api"); -ColnodAPI::ColnodAPI(serversdk::RequestManager* reqMan, const bool &dryMode, const QString &userName, const QString &password) - :mReqMan(reqMan), mUserName(userName), mPassword(password), mDryMode(dryMode) +ColnodAPI::ColnodAPI(serversdk::RequestManager* reqMan, const bool &dryMode, QString userName, QString password) + :mReqMan(reqMan), mUserName(std::move(userName)), mPassword(std::move(password)), mDryMode(dryMode) { // ----------------------------------- mReqMan->setIgnoreSsl(true); @@ -35,7 +37,7 @@ void ColnodAPI::downloadData(const Timestamp &time) auto data = std::make_shared(); - auto errorHandler = [=](std::shared_ptr request){ + auto errorHandler = [=](const std::shared_ptr& request){ if (!checkRequest(request)) { qWarning(colnod) << "ERROR during calling" << request->url() << ", request unsuccessful"; mValid = false; @@ -215,10 +217,7 @@ std::shared_ptr ColnodAPI::composeRequest(const QString &end bool ColnodAPI::checkRequest(const std::shared_ptr &request) { - if (request->status() == 200) { - return true; - } - return false; + return request->status() == 200; } bool ColnodAPI::isValid() @@ -257,7 +256,7 @@ void ColnodAPI::setUserName(const QString &userName) mUserName = userName; } -void ColnodAPI::areDataReady(std::shared_ptr data) +void ColnodAPI::areDataReady(const std::shared_ptr& data) { if (++amountData == 4) { @@ -280,12 +279,12 @@ void ColnodAPI::isDataProcessFinished() } } -void ColnodAPI::saveUpdatedTokens(std::shared_ptr data, const QByteArray &responseData) +void ColnodAPI::saveUpdatedTokens(const std::shared_ptr& data, const QByteArray &responseData) { data->loadTokensFromJson(responseData); } -void ColnodAPI::saveDeletedTokens(std::shared_ptr data, const QByteArray &responseData) +void ColnodAPI::saveDeletedTokens(const std::shared_ptr& data, const QByteArray &responseData) { QJsonDocument doc = QJsonDocument::fromJson(responseData); QJsonArray items = doc.object()["items"].toArray(); @@ -294,12 +293,12 @@ void ColnodAPI::saveDeletedTokens(std::shared_ptr data, const QByteArray & } } -void ColnodAPI::saveUpdatedSubjects(std::shared_ptr data, const QByteArray &responseData) +void ColnodAPI::saveUpdatedSubjects(const std::shared_ptr& data, const QByteArray &responseData) { data->loadSubjectsFormJson(responseData); } -void ColnodAPI::saveDeletedSubjects(std::shared_ptr data, const QByteArray &responseData) +void ColnodAPI::saveDeletedSubjects(const std::shared_ptr& data, const QByteArray &responseData) { QJsonDocument doc = QJsonDocument::fromJson(responseData); QJsonArray items = doc.object()["items"].toArray(); diff --git a/src/colnod/colnodapi.h b/src/colnod/colnodapi.h index 68ed360..300208b 100644 --- a/src/colnod/colnodapi.h +++ b/src/colnod/colnodapi.h @@ -48,7 +48,7 @@ class ColnodAPI: public QObject Q_OBJECT public: ColnodAPI() = default; - ColnodAPI(serversdk::RequestManager* reqManconst, const bool &dryMode = false, const QString &userName = "spaceti", const QString &password = "spaceti1"); + ColnodAPI(serversdk::RequestManager* reqManconst, const bool &dryMode = false, QString userName = "spaceti", QString password = "spaceti1"); void downloadData(const Timestamp &time); void processData(const std::shared_ptr &data); @@ -76,14 +76,14 @@ public: bool isValid(); private: - Q_SLOT void areDataReady(std::shared_ptr data); + Q_SLOT void areDataReady(const std::shared_ptr& data); Q_SLOT void isDataProcessFinished(); private: - void saveUpdatedTokens(std::shared_ptr data, const QByteArray &responseData); - void saveUpdatedSubjects(std::shared_ptr data, const QByteArray &responseData); - void saveDeletedTokens(std::shared_ptr data, const QByteArray &responseData); - void saveDeletedSubjects(std::shared_ptr data, const QByteArray &responseData); + void saveUpdatedTokens(const std::shared_ptr& data, const QByteArray &responseData); + void saveUpdatedSubjects(const std::shared_ptr& data, const QByteArray &responseData); + void saveDeletedTokens(const std::shared_ptr& data, const QByteArray &responseData); + void saveDeletedSubjects(const std::shared_ptr& data, const QByteArray &responseData); void newData(); diff --git a/src/colnod/data.h b/src/colnod/data.h index a0f607a..bfc1eef 100644 --- a/src/colnod/data.h +++ b/src/colnod/data.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "token.h" #include "subject.h" @@ -13,7 +15,7 @@ constexpr auto tab = "\t"; class Message { public: - static QString massageTemplate(QString action, QString item, QString source, QString itemInfo) + static QString massageTemplate(const QString& action, const QString& item, const QString& source, const QString& itemInfo) { return action + " " + item + " in " + source + ", " + item + ": '" + itemInfo + "'"; } @@ -41,8 +43,8 @@ struct PreparedData { public: PreparedData() = default; - PreparedData(const std::shared_ptr &database, const std::shared_ptr &colnod) - :databaseData(database), colnodData(colnod) + PreparedData(std::shared_ptr database, std::shared_ptr colnod) + :databaseData(std::move(database)), colnodData(std::move(colnod)) { } diff --git a/src/colnod/databaseapi.cpp b/src/colnod/databaseapi.cpp index 7c4b695..b32d23c 100644 --- a/src/colnod/databaseapi.cpp +++ b/src/colnod/databaseapi.cpp @@ -12,7 +12,7 @@ DatabaseAPI::DatabaseAPI(serversdk::DatabaseManager *dbMan, bool dryMode) mDbMan->setDryMode(dryMode); } -bool DatabaseAPI::open(QString host, QString name, QString user, QString password) +bool DatabaseAPI::open(const QString& host, const QString& name, const QString& user, const QString& password) { return mDbMan->openPostgres(host, name, user, password); } @@ -135,7 +135,7 @@ void DatabaseAPI::setLastUpdate(const QHash> &to qInfo(database) << equals; } -void DatabaseAPI::setLastUpdate(const QList ids) +void DatabaseAPI::setLastUpdate(const QList& ids) { auto query = mDbMan->createQuery(); for (const auto &id : ids){ @@ -299,10 +299,7 @@ bool DatabaseAPI::isAlreadyDeleted(const QString &id) qWarning(database) << "Token deleted in colnod doesn't exists in db, will be noted as already deleted in stats"; return true; } - if (token->deleted()) - return true; - return false; - + return token->deleted(); } bool DatabaseAPI::isValid() diff --git a/src/colnod/databaseapi.h b/src/colnod/databaseapi.h index 8668b2f..f127a9d 100644 --- a/src/colnod/databaseapi.h +++ b/src/colnod/databaseapi.h @@ -20,10 +20,10 @@ class DatabaseAPI : public QObject public: explicit DatabaseAPI(serversdk::DatabaseManager *dbMan, bool dryMode); - bool open(QString host = "192.168.1.94", - QString name = "deloitte", - QString user = "postgres", - QString password = "34rjkciea12"); + bool open(const QString& host = "192.168.1.94", + const QString& name = "deloitte", + const QString& user = "postgres", + const QString& password = "34rjkciea12"); bool executeQuery(QSqlQuery &query, const QString &statement = QString()); @@ -32,7 +32,7 @@ public: qint64 getLastSync(); void setLastSync(qint64 timestamp); void setLastUpdate(const QHash > &tokens); - void setLastUpdate(const QList ids); + void setLastUpdate(const QList& ids); qint64 getNow(); void initNewTokens(); diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index 6e025dd..a84a7e0 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -63,7 +63,7 @@ bool SyncManager::startSynchronization() colnod->downloadData(Timestamp(syncBegin)); - connect(colnod.get(), &ColnodAPI::downloadDataFinished, [=](std::shared_ptr colnodData) { + connect(colnod.get(), &ColnodAPI::downloadDataFinished, [=](const std::shared_ptr& colnodData) { if (!colnodData) { qCritical(syncmanager) << "Not possible to get correct data from colnod"; QCoreApplication::exit(-1); @@ -202,7 +202,7 @@ std::unique_ptr SyncManager::prepareDataNew(const std::shared_ptr< return preparedData; } -void SyncManager::initNewToken(std::shared_ptr token) +void SyncManager::initNewToken(const std::shared_ptr& token) { qint16 num = database->getNumOfTokensOfSubject(token->subjectId()); token->setName(database->getSubjectNameByTokenId(token->id()) + "_mobile_" + QString::number(num + 1)); diff --git a/src/colnod/syncmanager.h b/src/colnod/syncmanager.h index 2d9478d..267efc0 100644 --- a/src/colnod/syncmanager.h +++ b/src/colnod/syncmanager.h @@ -29,7 +29,7 @@ private: std::unique_ptr prepareDataUsindOld(const std::shared_ptr &databaseData, const std::shared_ptr &colnodData); private: - void initNewToken(std::shared_ptr token); + void initNewToken(const std::shared_ptr& token); bool downloadData(); bool prepareData(); diff --git a/test/auto/colnod/tst_colnodapi.cpp b/test/auto/colnod/tst_colnodapi.cpp index dedd554..5c2fffb 100644 --- a/test/auto/colnod/tst_colnodapi.cpp +++ b/test/auto/colnod/tst_colnodapi.cpp @@ -68,7 +68,7 @@ void ColnodTest::download_data_test() auto data = qvariant_cast>(spy.at(0).at(0)); QVERIFY(data); - QVERIFY(data->updatedTokens.size() > 0); + QVERIFY(! data->updatedTokens.isEmpty()); QVERIFY(data->updatedTokens.contains("5e2f1260-da1c-441f-9644-24dfe3b97b2a")); } { @@ -79,7 +79,7 @@ void ColnodTest::download_data_test() auto data = qvariant_cast>(spy.at(0).at(0)); QVERIFY(data); - QVERIFY(data->updatedTokens.size() == 0); + QVERIFY(! data->updatedTokens.isEmpty()); } } diff --git a/test/auto/syncmanager/tst_syncmanager.cpp b/test/auto/syncmanager/tst_syncmanager.cpp index b190c83..bd244f0 100644 --- a/test/auto/syncmanager/tst_syncmanager.cpp +++ b/test/auto/syncmanager/tst_syncmanager.cpp @@ -24,7 +24,13 @@ void SyncManagerTest::prepareData_test() SyncManager sync(true); auto dbData = std::make_shared(); auto colnodData = std::make_shared(); - QVERIFY2(sync.prepareDataUsindOld(dbData, colnodData), "finish unitest"); + + auto oldPreparedData = sync.prepareDataUsindOld(dbData, colnodData); + auto newPreparedData = sync.prepareDataNew(dbData, colnodData); + + QCOMPARE(newPreparedData, oldPreparedData); + + } QTEST_MAIN(SyncManagerTest) From 9afde747c8b022e9c9eecb405b09eb25d8ec2c8c Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Mon, 2 Dec 2019 10:06:56 +0100 Subject: [PATCH 3/7] server-sdk: clang-checks fix --- server-sdk | 2 +- test/auto/colnod/tst_colnodapi.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/server-sdk b/server-sdk index a818055..031b6c2 160000 --- a/server-sdk +++ b/server-sdk @@ -1 +1 @@ -Subproject commit a818055b75dc0de97e26be44cbbfd2e94516c09e +Subproject commit 031b6c2535408bce18a5d7bbc5842f9ee4384328 diff --git a/test/auto/colnod/tst_colnodapi.cpp b/test/auto/colnod/tst_colnodapi.cpp index 5c2fffb..fd91abc 100644 --- a/test/auto/colnod/tst_colnodapi.cpp +++ b/test/auto/colnod/tst_colnodapi.cpp @@ -62,6 +62,7 @@ void ColnodTest::download_data_test() ColnodAPI colnod(&reqMan); { QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); + QVERIFY(spy.isValid()); colnod.downloadData(Timestamp(1570190399259)); QVERIFY(spy.wait()); From f3077d9f0afeda3ef998df8df5ece5f676b62ed1 Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Mon, 2 Dec 2019 13:18:46 +0100 Subject: [PATCH 4/7] unittest: adding multiple checks for prepareData_test --- src/colnod/syncmanager.cpp | 5 ++- test/auto/colnod/tst_colnodapi.cpp | 43 +++++++++++++---------- test/auto/syncmanager/tst_syncmanager.cpp | 17 ++++++--- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index a84a7e0..148a311 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -204,6 +204,8 @@ std::unique_ptr SyncManager::prepareDataNew(const std::shared_ptr< void SyncManager::initNewToken(const std::shared_ptr& token) { + Q_ASSERT(database); + Q_ASSERT(token); qint16 num = database->getNumOfTokensOfSubject(token->subjectId()); token->setName(database->getSubjectNameByTokenId(token->id()) + "_mobile_" + QString::number(num + 1)); token->setDescription("mobile"); @@ -214,9 +216,6 @@ void SyncManager::initNewToken(const std::shared_ptr& token) std::unique_ptr SyncManager::prepareDataUsindOld(const std::shared_ptr &databaseData, const std::shared_ptr &colnodData) { - Q_UNUSED(databaseData); - Q_UNUSED(colnodData); - qInfo(syncmanager) << equals; qInfo(syncmanager) << "PREPARING DATA -> BEGIN"; qInfo(syncmanager) << dash; diff --git a/test/auto/colnod/tst_colnodapi.cpp b/test/auto/colnod/tst_colnodapi.cpp index fd91abc..2ae370e 100644 --- a/test/auto/colnod/tst_colnodapi.cpp +++ b/test/auto/colnod/tst_colnodapi.cpp @@ -21,6 +21,7 @@ private slots: void login(); void getTokens(); void download_data_test(); + void download_data_test_now(); void download_data_fail_test(); private: @@ -60,28 +61,32 @@ void ColnodTest::download_data_test() { serversdk::RequestManager reqMan; ColnodAPI colnod(&reqMan); - { - QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); - QVERIFY(spy.isValid()); - colnod.downloadData(Timestamp(1570190399259)); - QVERIFY(spy.wait()); - auto data = qvariant_cast>(spy.at(0).at(0)); - QVERIFY(data); + QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); + QVERIFY(spy.isValid()); + colnod.downloadData(Timestamp(1570190399259)); + QVERIFY(spy.wait()); - QVERIFY(! data->updatedTokens.isEmpty()); - QVERIFY(data->updatedTokens.contains("5e2f1260-da1c-441f-9644-24dfe3b97b2a")); - } - { - Timestamp time(QDateTime::currentMSecsSinceEpoch()); - colnod.downloadData(time); - QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); - QVERIFY(spy.wait()); - auto data = qvariant_cast>(spy.at(0).at(0)); - QVERIFY(data); + auto data = qvariant_cast>(spy.at(0).at(0)); + QVERIFY(data); - QVERIFY(! data->updatedTokens.isEmpty()); - } + QVERIFY(! data->updatedTokens.isEmpty()); + QVERIFY(data->updatedTokens.contains("5e2f1260-da1c-441f-9644-24dfe3b97b2a")); +} + +void ColnodTest::download_data_test_now() +{ + serversdk::RequestManager reqMan; + ColnodAPI colnod(&reqMan); + + Timestamp time(QDateTime::currentMSecsSinceEpoch()); + colnod.downloadData(time); + QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); + QVERIFY(spy.wait()); + auto data = qvariant_cast>(spy.at(0).at(0)); + QVERIFY(data); + + QVERIFY(data->updatedTokens.isEmpty()); } void ColnodTest::download_data_fail_test() diff --git a/test/auto/syncmanager/tst_syncmanager.cpp b/test/auto/syncmanager/tst_syncmanager.cpp index bd244f0..95a43ce 100644 --- a/test/auto/syncmanager/tst_syncmanager.cpp +++ b/test/auto/syncmanager/tst_syncmanager.cpp @@ -25,12 +25,21 @@ void SyncManagerTest::prepareData_test() auto dbData = std::make_shared(); auto colnodData = std::make_shared(); + auto token = std::make_shared(); + token->setId("id1"); + dbData->updatedTokens.insert("id1", token); + + auto oldPreparedData = sync.prepareDataUsindOld(dbData, colnodData); auto newPreparedData = sync.prepareDataNew(dbData, colnodData); - - QCOMPARE(newPreparedData, oldPreparedData); - - + QVERIFY(oldPreparedData->databaseData->updatedTokens.contains("id1")); + QVERIFY(newPreparedData->databaseData->updatedTokens.contains("id1")); + QVERIFY(oldPreparedData->databaseData->updatedSubjects.isEmpty()); + QVERIFY(newPreparedData->databaseData->updatedSubjects.isEmpty()); + QVERIFY(oldPreparedData->databaseData->deletedTokens.isEmpty()); + QVERIFY(newPreparedData->databaseData->deletedTokens.isEmpty()); + QVERIFY(oldPreparedData->databaseData->deletedSubjects.isEmpty()); + QVERIFY(newPreparedData->databaseData->deletedSubjects.isEmpty()); } QTEST_MAIN(SyncManagerTest) From e8e8184add6d11f5783e3b305025237bdcb54264 Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Mon, 2 Dec 2019 14:23:36 +0100 Subject: [PATCH 5/7] unittest: data driven testing for tokens and prepareData ( failing ) --- src/colnod/syncmanager.cpp | 108 +-------------------- src/colnod/syncmanager.h | 8 +- test/auto/syncmanager/tst_syncmanager.cpp | 109 +++++++++++++++++++++- 3 files changed, 114 insertions(+), 111 deletions(-) diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index 148a311..58e9ac3 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -92,7 +92,7 @@ bool SyncManager::startSynchronization() connect(this, &SyncManager::dataReady, [=](){ - prepareData(); + //prepareData(); connect(this, &SyncManager::dataProcessFinished, [=](){ @@ -305,7 +305,7 @@ std::unique_ptr SyncManager::prepareDataUsindOld(const std::shared // Prepare data auto preparedData = std::make_unique(); preparedData->colnodData = cloneColnodDataToProcess; - preparedData->databaseData = databaseDataToProcess; + preparedData->databaseData = cloneDatabaseDataToProcess; return preparedData; } @@ -319,7 +319,7 @@ bool SyncManager::downloadData() qInfo(syncmanager).noquote() << "Modified data since last synchronization (" << mlastSync.toDateString() << "):"; qInfo(syncmanager) << dash; - connect(colnod.get(), &ColnodAPI::downloadDataFinished, this, &SyncManager::saveColnodData); + //connect(colnod.get(), &ColnodAPI::downloadDataFinished, this, &SyncManager::saveColnodData); //connect(database.get(), &DatabaseAPI::downloadDataFinished, this, &SyncManager::saveDatabaseData); //database->downloadData(); //colnod->downloadData(); @@ -327,96 +327,6 @@ bool SyncManager::downloadData() return res; } -// finds conflicts -> changes on both sides (colnod and DB), apply newer change -bool SyncManager::prepareData() -{ - qInfo(syncmanager) << equals; - qInfo(syncmanager) << "PREPARING DATA -> BEGIN"; - qInfo(syncmanager) << dash; - qInfo(syncmanager) << "Resolve conflicts ( changes on same item on both Colnod and DB ):"; - qInfo(syncmanager) << dash; - - - Q_ASSERT(colnodData); - Q_ASSERT(databaseData); - - - // TODO: why copy data? - colnodDataToProcess = std::make_shared(*colnodData); - databaseDataToProcess = std::make_shared(*databaseData); - - QList conflicts; - QList alreadySynced; - - // check modifed tokens from colnod, dont want update token, if it was edited in db after or has been already synced - for (const auto &colnodToken : colnodDataToProcess->updatedTokens) { - if (databaseDataToProcess->updatedTokens.contains(colnodToken->id())) { - // updated in db later - if (databaseDataToProcess->updatedTokens.value(colnodToken->id()) > colnodToken) { - conflicts.append(colnodToken->id()); - } - continue; - } - auto token = database->getToken(colnodToken->id()); - if ( token ) - // alredy synced ( tokens are same ) - if (token == colnodToken) - alreadySynced.append(colnodToken->id()); - } - // remove tokens which should be not updated - for (const auto &id : conflicts) - colnodDataToProcess->updatedTokens.remove(id); - for (const auto &id : alreadySynced) - colnodDataToProcess->updatedTokens.remove(id); - - qInfo(syncmanager) << tab << "-> COLNOD DATA - CHANGES:"; - qInfo(syncmanager) << tab << tab << conflicts.size() << "TOKENS WERE ADDED/UPDATED IN DATABASE TOO"; - qInfo(syncmanager) << tab << tab << alreadySynced.size() << "TOKENS WERE ALREADY SYNCED"; - - - - conflicts.clear(); - - // chech for already deleted ( in previous synced tokens were deleted from colnod, so it come to this sync but we dont want to sync it again - for (const auto &id : colnodDataToProcess->deletedTokens) { - if (database->isAlreadyDeleted(id)) { - conflicts.append(id); - } - } - for (const auto &id : conflicts) { - colnodDataToProcess->deletedTokens.removeOne(id); - } - - qInfo(syncmanager) << tab << tab << conflicts.size() << "TOKENS WERE ALREADY DELETED"; - qInfo(syncmanager) << dash; - - conflicts.clear(); - - // chech modified from db, remove token if it was edited in colnod later - for (const auto &databaseToken : databaseDataToProcess->updatedTokens) { - if (colnodDataToProcess->updatedTokens.contains(databaseToken->id())) { - if (databaseToken < colnodDataToProcess->updatedTokens.value(databaseToken->id())) - conflicts.append(databaseToken->id()); - } - else { - // restriction cauesed by colnod rest api - if (databaseToken->description() != "mobile") { - qCritical(syncmanager) << "Token:" << databaseToken->id() << "doesn't have 'mobile' in description, can't be "; - conflicts.append(databaseToken->id()); - } - } - } - for (const auto &id : conflicts) - colnodDataToProcess->updatedTokens.remove(id); - - qInfo(syncmanager) << tab << "-> DATABASE DATA - CHANGES:"; - qInfo(syncmanager) << tab << tab << conflicts.size() << "TOKENS WERE ADDED/UPDATED IN IN COLNOD TOO"; - qInfo(syncmanager) << dash; - - qInfo(syncmanager) << "PREPARING DATA -> FINISHED"; - qInfo(syncmanager) << equals; - return true; -} bool SyncManager::processData() { @@ -454,15 +364,3 @@ void SyncManager::areDataReady() emit dataReady(); } } - -void SyncManager::saveColnodData(const std::shared_ptr &data) -{ - colnodData = data; - areDataReady(); -} - -void SyncManager::saveDatabaseData(const std::shared_ptr &data) -{ - databaseData = data; - areDataReady(); -} diff --git a/src/colnod/syncmanager.h b/src/colnod/syncmanager.h index 267efc0..4276d7e 100644 --- a/src/colnod/syncmanager.h +++ b/src/colnod/syncmanager.h @@ -32,14 +32,12 @@ private: void initNewToken(const std::shared_ptr& token); bool downloadData(); - bool prepareData(); + //bool prepareData(); bool processData(); void updateLastUpdate(qint64 syncBegin); private: - Q_SLOT void saveColnodData(const std::shared_ptr &data); - Q_SLOT void saveDatabaseData(const std::shared_ptr &data); Q_SLOT void areDataReady(); signals: @@ -56,8 +54,8 @@ private: serversdk::DatabaseManager dbMan; Timestamp mlastSync; - std::shared_ptr colnodData; - std::shared_ptr databaseData; +// std::shared_ptr colnodData; +// std::shared_ptr databaseData; std::shared_ptr colnodDataToProcess; std::shared_ptr databaseDataToProcess; diff --git a/test/auto/syncmanager/tst_syncmanager.cpp b/test/auto/syncmanager/tst_syncmanager.cpp index 95a43ce..ff45e89 100644 --- a/test/auto/syncmanager/tst_syncmanager.cpp +++ b/test/auto/syncmanager/tst_syncmanager.cpp @@ -6,12 +6,37 @@ class SyncManagerTest : public QObject { Q_OBJECT +private: + std::shared_ptr tokenFromString(const QString &text); private slots: + void tokenFromString_test(); void sync_init_test(); void prepareData_test(); + void prepareData_tokens(); + void prepareData_tokens_data(); }; +std::shared_ptr SyncManagerTest::tokenFromString(const QString &text) +{ + auto split = text.split(","); + if (split.count() != 2) + return nullptr; + + auto token = std::make_shared(); + token->setId(split.first()); + token->setDescription("mobile"); + token->setLastUpdate(QDateTime::fromString(split.last(), "yyyyMMdd:HHmmss")); + return token; +} + +void SyncManagerTest::tokenFromString_test() +{ + auto token = tokenFromString("id1,20191010:232300"); + QCOMPARE(token->id(), QStringLiteral("id1")); + QCOMPARE(token->lastUpdate(), QDateTime::fromString("20191010:232300", "yyyyMMdd:HHmmss")); +} + void SyncManagerTest::sync_init_test() { SyncManager sync(true); @@ -22,14 +47,15 @@ void SyncManagerTest::sync_init_test() void SyncManagerTest::prepareData_test() { SyncManager sync(true); + QVERIFY(sync.databaseInitialization()); auto dbData = std::make_shared(); auto colnodData = std::make_shared(); auto token = std::make_shared(); + token->setDescription("mobile"); token->setId("id1"); dbData->updatedTokens.insert("id1", token); - auto oldPreparedData = sync.prepareDataUsindOld(dbData, colnodData); auto newPreparedData = sync.prepareDataNew(dbData, colnodData); QVERIFY(oldPreparedData->databaseData->updatedTokens.contains("id1")); @@ -42,6 +68,87 @@ void SyncManagerTest::prepareData_test() QVERIFY(newPreparedData->databaseData->deletedSubjects.isEmpty()); } +void SyncManagerTest::prepareData_tokens() +{ + SyncManager sync(true); + QVERIFY(sync.databaseInitialization()); + + + + QFETCH(QString, db_token_updated); + QFETCH(QString, db_token_deleted); + QFETCH(QString, colnod_token_updated); + QFETCH(QString, colnod_token_deleted); + QFETCH(QString, expected_db_tokens_toupdate); + QFETCH(QString, expected_db_tokens_todelete); + QFETCH(QString, expected_colnod_tokens_toupdate); + QFETCH(QString, expected_colnod_tokens_todelete); + + // fake data + auto dbData = std::make_shared(); + auto colnodData = std::make_shared(); + + // Database + auto utoken = tokenFromString(db_token_updated); + if ( utoken ) + dbData->updatedTokens.insert(utoken->id(), utoken); + auto dtoken = tokenFromString(db_token_deleted); + if ( dtoken ) + dbData->deletedTokens.append(dtoken->id()); + + // Colnod + auto colnod_utoken = tokenFromString(colnod_token_updated); + if ( colnod_utoken ) + colnodData->updatedTokens.insert(colnod_utoken->id(), colnod_utoken); + auto colnod_dtoken = tokenFromString(colnod_token_deleted); + if ( colnod_dtoken ) + colnodData->deletedTokens.append(colnod_dtoken->id()); + + auto oldPreparedData = sync.prepareDataUsindOld(dbData, colnodData); + auto newPreparedData = sync.prepareDataNew(dbData, colnodData); + + QVERIFY(newPreparedData->databaseData->updatedTokens.contains(expected_db_tokens_toupdate)); + QVERIFY(newPreparedData->databaseData->deletedTokens.contains(expected_db_tokens_todelete)); + QVERIFY(newPreparedData->colnodData->updatedTokens.contains(expected_colnod_tokens_toupdate)); + QVERIFY(newPreparedData->colnodData->deletedTokens.contains(expected_colnod_tokens_todelete)); + + QVERIFY(oldPreparedData->databaseData->updatedTokens.contains(expected_db_tokens_toupdate)); + QVERIFY(oldPreparedData->databaseData->deletedTokens.contains(expected_db_tokens_todelete)); + QVERIFY(oldPreparedData->colnodData->updatedTokens.contains(expected_colnod_tokens_toupdate)); + QVERIFY(oldPreparedData->colnodData->deletedTokens.contains(expected_colnod_tokens_todelete)); + +} + +void SyncManagerTest::prepareData_tokens_data() +{ + QTest::addColumn("db_token_updated"); + QTest::addColumn("db_token_deleted"); + QTest::addColumn("colnod_token_updated"); + QTest::addColumn("colnod_token_deleted"); + QTest::addColumn("expected_db_tokens_toupdate"); + QTest::addColumn("expected_db_tokens_todelete"); + QTest::addColumn("expected_colnod_tokens_toupdate"); + QTest::addColumn("expected_colnod_tokens_todelete"); + + // in: db 1 new token + // out: 1 db token must be updated in colnod + QTest::newRow("db 1 update") << "id1,20191010:23:23:00" << "" + << "" << "" + // expected database: toupdate << todelete + << "id1" << "" + // expected colnod: toupdate << todelete + << "" << ""; + // in: id1 in database new/updated + // in: id1 deleted in colnod + // out: 1 colnod token must be deleted from database + QTest::newRow("delete 1 existing token in database") << "id1,20191010:23:23:00" << "" + << "" << "id1,20191010:23:23:00" + // expected database: toupdate << todelete + << "" << "id1" + // expected colnod: toupdate << todelete + << "" << ""; +} + QTEST_MAIN(SyncManagerTest) #include "tst_syncmanager.moc" From 79cebf913057ee0745038926ef224ce01aa149e9 Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Mon, 2 Dec 2019 15:05:02 +0100 Subject: [PATCH 6/7] fix warning: qRegisterMetaType --- test/auto/colnod/tst_colnodapi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/auto/colnod/tst_colnodapi.cpp b/test/auto/colnod/tst_colnodapi.cpp index 2ae370e..c480e59 100644 --- a/test/auto/colnod/tst_colnodapi.cpp +++ b/test/auto/colnod/tst_colnodapi.cpp @@ -7,6 +7,7 @@ Q_DECLARE_METATYPE(std::shared_ptr) Q_DECLARE_METATYPE(std::shared_ptr); + class ColnodTest : public QObject { Q_OBJECT @@ -14,7 +15,7 @@ public: ColnodTest() { qRegisterMetaType>(); - qRegisterMetaType>(); + qRegisterMetaType>("std::shared_ptr"); } private slots: @@ -60,6 +61,7 @@ void ColnodTest::getTokens() void ColnodTest::download_data_test() { serversdk::RequestManager reqMan; + //reqMan.setIgnoreSsl(true); ColnodAPI colnod(&reqMan); QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); From 443a76e50ffe658c10e7efab40be639b434e6f12 Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Mon, 2 Dec 2019 15:07:24 +0100 Subject: [PATCH 7/7] trying to solve unittest crash ( adding more checks ) fixed cppcheck warning --- src/colnod/colnodapi.cpp | 16 ++++++++++++++-- src/colnod/data.h | 3 +-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp index fc283d8..8314b77 100644 --- a/src/colnod/colnodapi.cpp +++ b/src/colnod/colnodapi.cpp @@ -26,14 +26,26 @@ void ColnodAPI::downloadData(const Timestamp &time) auto login = requestLogin(); connect(login.get(), &serversdk::Request::finished, this, [=](){ // Get login token - if (!checkRequest(login)) { + if (login->status() != 200) { emit downloadDataFinished(nullptr); return; } AuthToken token; - token.fromJson(login->responseData()); + auto responseData = login->responseData(); + if (responseData.isEmpty()) { + qCWarning(colnod) << "empty response data when logging in"; + emit downloadDataFinished(nullptr); + return; + } + + token.fromJson(responseData); authToken = token.id(); + if (authToken.isEmpty()) { + qCCritical(colnod) << "Token uuid is empty"; + emit downloadDataFinished(nullptr); + return; + } auto data = std::make_shared(); diff --git a/src/colnod/data.h b/src/colnod/data.h index bfc1eef..868bc03 100644 --- a/src/colnod/data.h +++ b/src/colnod/data.h @@ -43,12 +43,11 @@ struct PreparedData { public: PreparedData() = default; - PreparedData(std::shared_ptr database, std::shared_ptr colnod) + PreparedData(const std::shared_ptr &database, const std::shared_ptr &colnod) :databaseData(std::move(database)), colnodData(std::move(colnod)) { } - // TODO: make unique_ptr ( neeed because of ColnodAPI ) std::shared_ptr databaseData; std::shared_ptr colnodData;