From 9f9ae6243cceb4a06d1d903cc0fd2738abc22e8b Mon Sep 17 00:00:00 2001 From: Filip Bucek Date: Wed, 4 Dec 2019 16:30:59 +0100 Subject: [PATCH] WIP: ColnodAPI::downloadData ( solving memory leaks ) Problem with ASSERT: "dataCount < 5" in file /Users/fbucek/Documents/Spaceti/acs/colnod-connector/src/colnod/colnodapi.cpp, line 80 --- src/colnod/colnodapi.cpp | 113 ++++++++++++++++++++--------- src/colnod/colnodapi.h | 11 +-- src/colnod/data.cpp | 12 ++- src/colnod/data.h | 6 +- src/colnod/syncmanager.cpp | 3 +- test/auto/colnod/tst_colnodapi.cpp | 15 +++- 6 files changed, 112 insertions(+), 48 deletions(-) diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp index 863b283..728b868 100644 --- a/src/colnod/colnodapi.cpp +++ b/src/colnod/colnodapi.cpp @@ -24,6 +24,7 @@ void ColnodAPI::downloadData(const qint64 &time) { // Have to get Login auto login = requestLogin(); + Q_ASSERT(login); connect(login.get(), &serversdk::Request::finished, this, [=](){ // Get login token if (login->status() != 200) { @@ -46,19 +47,20 @@ void ColnodAPI::downloadData(const qint64 &time) return; } - auto data = std::make_shared(); - auto errorHandler = [=](const std::shared_ptr& request){ - if (!checkRequest(request)) { - qWarning(colnod) << "ERROR during calling" << request->url() << ", request unsuccessful"; - mValid = false; - emit downloadDataFinished(nullptr); // TODO: think about it, will the other if passed? - } - else if (!checkResponse(request->responseData())) { - qWarning(colnod) << "Data from" << request->url() << "are invalid"; - mValid = false; - } - }; + + // NOTE: why? +// auto errorHandler = [=](const std::shared_ptr& request){ +// if (!checkRequest(request)) { +// qWarning(colnod) << "ERROR during calling" << request->url() << ", request unsuccessful"; +// mValid = false; +// emit downloadDataFinished(nullptr); // TODO: think about it, will the other if passed? +// } +// else if (!checkResponse(request->responseData())) { +// qWarning(colnod) << "Data from" << request->url() << "are invalid"; +// mValid = false; +// } +// }; // if I have all data emit downloadDataFinished @@ -67,32 +69,67 @@ void ColnodAPI::downloadData(const qint64 &time) Timestamp timestamp; timestamp.setTimestamp(time); + auto data = std::make_shared(); + int dataCount = 0; + + auto checkData = [&dataCount, &data, this]() { + qDebug() << "check data" << dataCount; + if (dataCount > 5) { + qCCritical(colnod) << "check data cannnot be higher then 4"; + } + Q_ASSERT(dataCount < 5); + if (dataCount == 4) + emit downloadDataFinished(data); + }; + auto tokensRequest = getTokensUpdated(timestamp); - connect(tokensRequest.get(), &serversdk::Request::finished, errorHandler); - connect(tokensRequest.get(), &serversdk::Request::finished, [=](){ - saveUpdatedTokens(data, tokensRequest->responseData()); - emit partOfDataReady(data); +// connect(tokensRequest.get(), &serversdk::Request::finished, errorHandler); + connect(tokensRequest.get(), &serversdk::Request::finished, [=, &dataCount](){ + qDebug(colnod) << "tokens finished"; + if (!saveUpdatedTokens(data, tokensRequest->responseData())) { + emit downloadDataFinished(nullptr); + return; + } + ++dataCount; + checkData(); + //saveUpdatedTokens(data, tokensRequest->responseData()); + //emit partOfDataReady(data); }); auto deletedTokensRequest = getTokensDeleted(timestamp); - connect(deletedTokensRequest.get(), &serversdk::Request::finished, errorHandler); - connect(deletedTokensRequest.get(), &serversdk::Request::finished, [=](){ - saveDeletedTokens(data, deletedTokensRequest->responseData()); - emit partOfDataReady(data); +// connect(deletedTokensRequest.get(), &serversdk::Request::finished, errorHandler); + connect(deletedTokensRequest.get(), &serversdk::Request::finished, [=, &dataCount](){ + qDebug(colnod) << "tokens finished"; + if (!saveDeletedTokens(data, deletedTokensRequest->responseData())) { + emit downloadDataFinished(nullptr); + return; + } + ++dataCount; + checkData(); + + //emit partOfDataReady(data); }); auto subjectsRequest = getSubjectsUpdated(timestamp); - connect(subjectsRequest.get(), &serversdk::Request::finished, errorHandler); - connect(subjectsRequest.get(), &serversdk::Request::finished, [=](){ - saveUpdatedSubjects(data, subjectsRequest->responseData()); - emit partOfDataReady(data); +// connect(subjectsRequest.get(), &serversdk::Request::finished, errorHandler); + connect(subjectsRequest.get(), &serversdk::Request::finished, [=, &dataCount](){ + qDebug(colnod) << "tokens finished"; + if (!saveUpdatedSubjects(data, subjectsRequest->responseData())) { + emit downloadDataFinished(nullptr); + return; + } + ++dataCount; + checkData(); }); auto deletedSubjectsRequest = getSubjectsDeleted(timestamp); - connect(deletedSubjectsRequest.get(), &serversdk::Request::finished, errorHandler); - connect(deletedSubjectsRequest.get(), &serversdk::Request::finished, [=](){ +// connect(deletedSubjectsRequest.get(), &serversdk::Request::finished, errorHandler); + connect(deletedSubjectsRequest.get(), &serversdk::Request::finished, [=, &dataCount](){ + qDebug(colnod) << "tokens finished"; saveDeletedSubjects(data, deletedSubjectsRequest->responseData()); - emit partOfDataReady(data); + ++dataCount; + checkData(); +// emit partOfDataReady(data); }); }); } @@ -294,32 +331,42 @@ void ColnodAPI::isDataProcessFinished() } } -void ColnodAPI::saveUpdatedTokens(const std::shared_ptr& data, const QByteArray &responseData) +bool ColnodAPI::saveUpdatedTokens(const std::shared_ptr& data, const QByteArray &responseData) { - data->loadTokensFromJson(responseData); + Q_ASSERT(data); + return data->loadTokensFromJson(responseData); } -void ColnodAPI::saveDeletedTokens(const std::shared_ptr& data, const QByteArray &responseData) +bool ColnodAPI::saveDeletedTokens(const std::shared_ptr& data, const QByteArray &responseData) { + Q_ASSERT(data); + if (responseData.isEmpty()) + return false; QJsonDocument doc = QJsonDocument::fromJson(responseData); QJsonArray items = doc.object()["items"].toArray(); for (QJsonValueRef item : items) { data->deletedTokens.append(item.toString()); } + return true; } -void ColnodAPI::saveUpdatedSubjects(const std::shared_ptr& data, const QByteArray &responseData) +bool ColnodAPI::saveUpdatedSubjects(const std::shared_ptr& data, const QByteArray &responseData) { - data->loadSubjectsFormJson(responseData); + Q_ASSERT(data); + return data->loadSubjectsFormJson(responseData); } -void ColnodAPI::saveDeletedSubjects(const std::shared_ptr& data, const QByteArray &responseData) +bool ColnodAPI::saveDeletedSubjects(const std::shared_ptr& data, const QByteArray &responseData) { + Q_ASSERT(data); + if (responseData.isEmpty()) + return false; QJsonDocument doc = QJsonDocument::fromJson(responseData); QJsonArray items = doc.object()["items"].toArray(); for (QJsonValueRef item : items) { data->deletedSubjects.append(item.toString()); } + return true; } void ColnodAPI::newData() diff --git a/src/colnod/colnodapi.h b/src/colnod/colnodapi.h index 859f2fc..fc5a0b1 100644 --- a/src/colnod/colnodapi.h +++ b/src/colnod/colnodapi.h @@ -39,6 +39,7 @@ public: class ColnodAPI: public QObject { Q_OBJECT + friend class ColnodTest; public: ColnodAPI() = default; ColnodAPI(serversdk::RequestManager* reqManconst, const bool &dryMode = false, QString userName = "spaceti", QString password = "spaceti1"); @@ -73,10 +74,10 @@ private: Q_SLOT void isDataProcessFinished(); private: - 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); + bool saveUpdatedTokens(const std::shared_ptr& data, const QByteArray &responseData); + bool saveUpdatedSubjects(const std::shared_ptr& data, const QByteArray &responseData); + bool saveDeletedTokens(const std::shared_ptr& data, const QByteArray &responseData); + bool saveDeletedSubjects(const std::shared_ptr& data, const QByteArray &responseData); void newData(); @@ -103,7 +104,7 @@ private: QString mPassword; Timestamp mLastSync; bool mDryMode = false; - bool mValid = true; + bool mValid = false; std::shared_ptr mData; diff --git a/src/colnod/data.cpp b/src/colnod/data.cpp index 990a5ab..c211341 100644 --- a/src/colnod/data.cpp +++ b/src/colnod/data.cpp @@ -9,8 +9,11 @@ void Data::clear() deletedSubjects.clear(); } -void Data::loadTokensFromJson(const QByteArray &data) +bool Data::loadTokensFromJson(const QByteArray &data) { + if (data.isEmpty()) + return false; + auto doc = QJsonDocument::fromJson(data); auto items = doc.object()["items"].toArray(); for (auto item : items) { @@ -19,10 +22,14 @@ void Data::loadTokensFromJson(const QByteArray &data) token->fromJson(doc.toJson()); updatedTokens.insert(token->id(), token); } + return true; } -void Data::loadSubjectsFormJson(const QByteArray &data) +bool Data::loadSubjectsFormJson(const QByteArray &data) { + if (!data.isEmpty()) + return false; + auto doc = QJsonDocument::fromJson(data); auto items = doc.object()["items"].toArray(); for (auto item : items) { @@ -31,4 +38,5 @@ void Data::loadSubjectsFormJson(const QByteArray &data) subject->fromJson(doc.toJson()); updatedSubjects.insert(subject->id(), subject); } + return true; } diff --git a/src/colnod/data.h b/src/colnod/data.h index 868bc03..dbc2601 100644 --- a/src/colnod/data.h +++ b/src/colnod/data.h @@ -30,8 +30,8 @@ public: void clear(); - void loadTokensFromJson(const QByteArray &data); - void loadSubjectsFormJson(const QByteArray &data); + bool loadTokensFromJson(const QByteArray &data); + bool loadSubjectsFormJson(const QByteArray &data); QHash> updatedTokens; QList deletedTokens; @@ -44,7 +44,7 @@ struct PreparedData public: PreparedData() = default; PreparedData(const std::shared_ptr &database, const std::shared_ptr &colnod) - :databaseData(std::move(database)), colnodData(std::move(colnod)) + :databaseData(database), colnodData(colnod) { } diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index 442a23b..8557671 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -36,6 +36,7 @@ bool SyncManager::databaseInitialization() bool SyncManager::startSynchronization() { + Q_ASSERT(database); // I have to current time from database qint64 syncBegin = database->getNow(); if (syncBegin == -1) { @@ -61,7 +62,7 @@ bool SyncManager::startSynchronization() // NOW I HAVE DATA FROM DATABASE colnod->downloadData(mlastSync.timestamp()); - connect(colnod.get(), &ColnodAPI::downloadDataFinished, [=](std::shared_ptr colnodData) { + connect(colnod.get(), &ColnodAPI::downloadDataFinished, [=](const std::shared_ptr &colnodData) { qInfo(syncmanager) << "DOWNLOADING DATA -> FINISHED"; qInfo(syncmanager) << equals; diff --git a/test/auto/colnod/tst_colnodapi.cpp b/test/auto/colnod/tst_colnodapi.cpp index 9ad3914..3124576 100644 --- a/test/auto/colnod/tst_colnodapi.cpp +++ b/test/auto/colnod/tst_colnodapi.cpp @@ -21,7 +21,7 @@ public: private slots: void login(); void getTokens(); - void download_data_test(); + void download_test(); void download_data_test_now(); void download_data_fail_test(); @@ -56,16 +56,23 @@ void ColnodTest::getTokens() colnod.getTokensUpdated(time); } -void ColnodTest::download_data_test() +void ColnodTest::download_test() { serversdk::RequestManager reqMan; - //reqMan.setIgnoreSsl(true); + reqMan.setIgnoreSsl(true); ColnodAPI colnod(&reqMan); + QVERIFY(!colnod.mData); + QVERIFY(!colnod.mValid); + QVERIFY(!colnod.amountData); + QVERIFY(!colnod.amountProccessesFinished); + QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); QVERIFY(spy.isValid()); colnod.downloadData(1570190399259); QVERIFY(spy.wait()); + QVERIFY(colnod.amountData == 0); + auto data = qvariant_cast>(spy.at(0).at(0)); QVERIFY(data); @@ -83,8 +90,8 @@ void ColnodTest::download_data_test_now() QSignalSpy spy(&colnod, &ColnodAPI::downloadDataFinished); QVERIFY(spy.wait()); auto data = qvariant_cast>(spy.at(0).at(0)); + // No latest data QVERIFY(data); - QVERIFY(data->updatedTokens.isEmpty()); }