Fix memory leaks and add error handling

This commit is contained in:
Ondřej Fischer 2019-11-04 11:07:11 +01:00
parent 8d6dc6714c
commit 8f16ac06a6
19 changed files with 176 additions and 143 deletions

View File

@ -1,7 +1,7 @@
#include <QCoreApplication>
#include "datamanager.h"
#include "colnodapi.h"
#include "syncmanager.h"
#include <QCommandLineParser>
int main(int argc, char *argv[])
@ -15,15 +15,19 @@ int main(int argc, char *argv[])
QCommandLineOption dryModeOption("dryMode", "ColnodAPI", "Read-only mode, prints changes which would normally be made");
parser.addOption(dryModeOption);
parser.process(app);
auto *api = new ColnodAPI(parser.isSet(dryModeOption));
api->loadDataFromDB();
api->loadDataFromColnod();
QObject::connect(api, &ColnodAPI::dataDownloaded, [=](){
api->syncDataFromColnodToDB();
api->syncDataFromDBToColnod();
QObject::connect(api, &ColnodAPI::syncFinished, [=](){
SyncManager api(parser.isSet(dryModeOption));
api.loadDataFromDB();
api.loadDataFromColnod();
QObject::connect(&api, &SyncManager::dataDownloaded, [&](){
api.syncDataFromColnodToDB();
api.syncDataFromDBToColnod();
QObject::connect(&api, &SyncManager::syncFinished, [](){
qDebug() << "Quit";
QCoreApplication::exit();
});
});
QObject::connect(&api, &SyncManager::error, [](){
QCoreApplication::exit(1);
});
return QCoreApplication::exec();
}

View File

@ -2,7 +2,6 @@ INCLUDEPATH += $$PWD
#SRC_DIR = $$PWD
message($$PWD)
SOURCES += \
$$PWD/colnodapi.cpp \
$$PWD/databasemanager.cpp \
$$PWD/datamanager.cpp \
$$PWD/entity.cpp \
@ -10,10 +9,10 @@ SOURCES += \
$$PWD/requestmanager.cpp \
$$PWD/response.cpp \
$$PWD/subject.cpp \
$$PWD/syncmanager.cpp \
$$PWD/token.cpp
HEADERS += \
$$PWD/colnodapi.h \
$$PWD/databasemanager.h \
$$PWD/datamanager.h \
$$PWD/entity.h \
@ -21,5 +20,6 @@ HEADERS += \
$$PWD/requestmanager.h \
$$PWD/response.h \
$$PWD/subject.h \
$$PWD/syncmanager.h \
$$PWD/token.h
message($$SOURCES)

View File

@ -9,14 +9,15 @@ DatabaseManager::DatabaseManager(const QString& host, const QString& dbName, con
db.setPassword(password);
if (!db.open())
{
qDebug() << "Opening error" + db.lastError().text();
log("Opening error" + db.lastError().text());
emit error();
}
query = QSqlQuery("query", db);
this->dryMode = dryMode;
}
// add or update subject to db
int DatabaseManager::saveSubject(Subject* subject, const QString& table)
int DatabaseManager::saveSubject(std::shared_ptr<Subject> subject, const QString& table)
{
QString id = subject->idToStringWithoutBraces();
if (checkIfExists(id, table))
@ -46,7 +47,7 @@ int DatabaseManager::saveSubject(Subject* subject, const QString& table)
}
// add or update token to DB
int DatabaseManager::saveToken(Token* token, const QString& table)
int DatabaseManager::saveToken(std::shared_ptr<Token> token, const QString& table)
{
QString id = token->idToStringWithoutBraces();
if (checkIfExists(id, table))
@ -93,7 +94,7 @@ int DatabaseManager::saveToken(Token* token, const QString& table)
}
// add of update subject attributes
void DatabaseManager::saveSubjectAttributes(Subject *subject, const QString& table)
void DatabaseManager::saveSubjectAttributes(std::shared_ptr<Subject> subject, const QString& table)
{
auto attributes = subject->getAtr();
for (const auto& attribute : attributes){
@ -123,10 +124,10 @@ void DatabaseManager::saveSubjectAttributes(Subject *subject, const QString& tab
void DatabaseManager::setDeleted(const QString& id, const QString& table, quint64 time)
{
//quint64 now = getNow();
//QString nowString = QDateTime::fromMSecsSinceEpoch(now).toString("yyyy-MM-dd hh:mm:ss.zzz");
QString nowString = QDateTime::fromMSecsSinceEpoch(time).toString("yyyy-MM-dd hh:mm:ss.zzz");
query.prepare(QString("UPDATE %1 SET deleted = true, last_update = :now, last_modified = :now WHERE id = :id").arg(table));
query.bindValue(":id", id);
query.bindValue(":now", time);
query.bindValue(":now", nowString);
executeQuery(query);
}
@ -151,31 +152,37 @@ QString DatabaseManager::getLastQuery(const QSqlQuery& query) const
return str;
}
void DatabaseManager::executeNonPreperedQuery(const QString &statement, QSqlQuery &query) const
void DatabaseManager::executeNonPreperedQuery(const QString &statement, QSqlQuery &query)
{
if (dryMode){
QString sqlStatement = getLastQuery(query);
qDebug() << sqlStatement;
if (statement.startsWith("SELECT"))
query.exec(statement);
}
else{
query.exec(statement);
if (!dryMode || statement.startsWith("SELECT")){
if (!query.exec(statement)){
QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text());
log(QString(msg));
emit error();
}
}
}
bool DatabaseManager::executeQuery(QSqlQuery &query) const
bool DatabaseManager::executeQuery(QSqlQuery &query)
{
if (dryMode){
QString sqlStatement = getLastQuery(query);
qDebug() << sqlStatement;
if (sqlStatement.startsWith("SELECT"))
query.exec();
return true;
}
bool res = query.exec();
return res;
if (!dryMode || query.isSelect()){
if (!query.exec()){
QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text());
log(QString(msg));
emit error();
}
}
return true;
}
void DatabaseManager::dropTables()
@ -285,7 +292,7 @@ QString DatabaseManager::getSubjectNameByTokenId(const QString &tokenId)
if (query.next())
return query.value(0).toString();
qWarning() << "Token:" << tokenId << "is not assigned to any subject";
return "No Subject";
return "(No subject)";
}
QString DatabaseManager::getSubjectNameById(const QString &id)
@ -296,7 +303,7 @@ QString DatabaseManager::getSubjectNameById(const QString &id)
if (query.next())
return query.value(0).toString();
qWarning() << "Subject:" << id << "doesn't exists";
return "No Subject";
return "(No subject)";
}
bool DatabaseManager::checkDeletedToken(const QString &id)

View File

@ -19,9 +19,9 @@ class DatabaseManager : public QObject
public:
DatabaseManager(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool& dryMode = false);
int saveSubject(Subject* subject, const QString& table);
int saveToken(Token* token, const QString& table);
void saveSubjectAttributes(Subject* subject, const QString& table);
int saveSubject(std::shared_ptr<Subject> subject, const QString& table);
int saveToken(std::shared_ptr<Token> token, const QString& table);
void saveSubjectAttributes(std::shared_ptr<Subject> subject, const QString& table);
void setDeleted(const QString& id, const QString& table, quint64 time);
void dropTables();
@ -44,9 +44,12 @@ public:
private:
bool checkIfExists(const QString& id, const QString& table);
bool executeQuery(QSqlQuery &query) const;
bool executeQuery(QSqlQuery &query);
QString getLastQuery(const QSqlQuery &query) const;
void executeNonPreperedQuery(const QString &statement, QSqlQuery& query) const;
void executeNonPreperedQuery(const QString &statement, QSqlQuery& query);
signals:
void error();
private:
QSqlDatabase db;

View File

@ -2,12 +2,13 @@
DataManager::DataManager(const bool &dryMode)
{
db = new DatabaseManager("192.168.1.94", "deloitte", "postgres", "34rjkciea12", dryMode);
//db = new DatabaseManager("localhost", "deloitte", "postgres", "34rjkciea12");
db = std::make_shared<DatabaseManager>("192.168.1.94", "deloitte", "postgres", "34rjkciea12", dryMode);
//db = std::make_shared<DatabaseManager>("localhost", "deloitte", "postgres", "34rjkciea12");
Logger::setDBMan(db);
nextLastSync = db->getNow();
lastSync = db->getLastSync();
this->dryMode = dryMode;
connect(db.get(), &DatabaseManager::error, this, &DataManager::error);
}
// load all tokens from colnod to comparing with working set from DB
@ -18,14 +19,14 @@ void DataManager::fillFullTokensColnod(const QString& response)
if (!items.empty())
{
for (QJsonValueRef item : items){
auto token = new Token();
auto token = std::make_shared<Token>();
token->fromJSON(item.toObject());
allTokensFromColnod.insert(token->idToStringWithoutBraces(), token);
}
}
else{
qCritical() << "Colnod is Empty";
auto token = new Token("empty");
auto token = std::make_shared<Token>("empty");
allTokensFromColnod.insert(token->idToStringWithoutBraces(), token);
}
}
@ -39,7 +40,7 @@ void DataManager::fillTokensToUpdateColnod(const QString& response)
{
for (QJsonValueRef item : items)
{
auto token = new Token();
auto token = std::make_shared<Token>();
token->fromJSON(item.toObject());
token->setDeleted(false);
tokensToUpdateFromColnodToDB.insert(token->idToStringWithoutBraces(), token);
@ -49,7 +50,7 @@ void DataManager::fillTokensToUpdateColnod(const QString& response)
else
{
qInfo() << "Colnod: 0 tokens to update";
auto token = new Token("empty");
auto token = std::make_shared<Token>("empty");
tokensToUpdateFromColnodToDB.insert(token->getName(), token);
}
}
@ -63,7 +64,7 @@ void DataManager::fillSubjectsToUpdateColnod(const QString& response)
{
for (QJsonValueRef item : items)
{
auto subject = new Subject();
auto subject = std::make_shared<Subject>();
subject->fromJSON(item.toObject());
subjectsToUpdateFromColnodToDB.insert(subject->idToStringWithoutBraces(), subject);
}
@ -72,7 +73,7 @@ void DataManager::fillSubjectsToUpdateColnod(const QString& response)
else
{
qInfo() << "Colnod:" << "0 subjects to update";
Subject* subject = new Subject("empty");
auto subject = std::make_shared<Subject>("empty");
subjectsToUpdateFromColnodToDB.insert(subject->getName(), subject);
}
}
@ -83,7 +84,7 @@ void DataManager::fillTokensToChangeDB()
QSqlQuery* query = db->getUpdatedTokens();
while (query->next())
{
auto token = new Token;
auto token = std::make_shared<Token>();
token->fromSQLRecord(query);
if (token->getDeleted()){ // sort to delete / to update
tokensFromDBToDeleteFromColnod.append(token->idToStringWithoutBraces());
@ -288,7 +289,7 @@ void DataManager::filterTokensColnod()
auto record = db->getToken(id);
if (!record)
continue;
auto tokenDB = new Token;
auto tokenDB = std::shared_ptr<Token>();
tokenDB->fromSQLRecord(record);
Q_ASSERT(tokenDB != token);
if (*tokenDB > *token)

View File

@ -42,9 +42,9 @@ public:
void emptyDatabase();
QHash<QString, QPointer<Token>> getTokensToUpdateColnod() {return tokensToUpdateFromColnodToDB;}
QHash<QString, std::shared_ptr<Token>> getTokensToUpdateColnod() {return tokensToUpdateFromColnodToDB;}
QList<QString> getTokensToDeleteColnod() {return tokensFromColnodToDeleteFromDB;}
QHash<QString, QPointer<Token>> getTokensToUpdateDB() {return tokensToUpdateFromDBToColnod;}
QHash<QString, std::shared_ptr<Token>> getTokensToUpdateDB() {return tokensToUpdateFromDBToColnod;}
QList<QString> getTokensToDeleteDB() {return tokensFromDBToDeleteFromColnod;}
const quint64 &getLastSync() {return lastSync;}
@ -55,17 +55,20 @@ public slots:
void setLastSync() {db->updateLastSync(nextLastSync);}
void setLastUpdate();
signals:
void error();
private:
DatabaseManager *db = nullptr;
std::shared_ptr<DatabaseManager> db;
quint64 lastSync; // time of last run
quint64 nextLastSync; // time of begin of this run
QHash<QString, QPointer<Subject>> subjectsToUpdateFromColnodToDB;
QHash<QString, QPointer<Token>> tokensToUpdateFromColnodToDB;
QHash<QString, QPointer<Token>> allTokensFromColnod;
QHash<QString, QPointer<Subject>> subjectsDB; // in future
QHash<QString, QPointer<Token>> tokensToUpdateFromDBToColnod;
QHash<QString, std::shared_ptr<Subject>> subjectsToUpdateFromColnodToDB;
QHash<QString, std::shared_ptr<Token>> tokensToUpdateFromColnodToDB;
QHash<QString, std::shared_ptr<Token>> allTokensFromColnod;
QHash<QString, std::shared_ptr<Subject>> subjectsDB; // in future
QHash<QString, std::shared_ptr<Token>> tokensToUpdateFromDBToColnod;
QList<QString> subjectsFromColnodToDeleteFromDB;
QList<QString> tokensFromColnodToDeleteFromDB;

View File

@ -3,6 +3,8 @@
#include <QtCore/QObject>
#include <QtCore/QUuid>
#include <QtCore/QJsonObject>
#include <QDebug>
#include <memory>
class Entity : public QObject {

View File

@ -1,6 +1,6 @@
#include "logger.h"
DatabaseManager *Logger::dbMan = nullptr;
std::shared_ptr<DatabaseManager> Logger::dbMan = nullptr;
Logger *Logger::logger = nullptr;
Logger::Logger()
@ -26,21 +26,24 @@ void Logger::logToDb(const QString &msg)
Logger::dbMan->log(msg);
}
void Logger::setDBMan(DatabaseManager *dbMan)
void Logger::setDBMan(std::shared_ptr<DatabaseManager> dbMan)
{
Logger::dbMan = dbMan;
}
QString Logger::makeTokenMsg(const QString &tokenId, const QString &action, const QString &source)
{
QString msg = QString("Token: %1 of subject: %2 %3. Source: %4").arg(tokenId,dbMan->getSubjectNameByTokenId(tokenId), action, source);
return msg;
return QString("Token: %1 of subject: %2 %3. Source: %4").arg(tokenId,dbMan->getSubjectNameByTokenId(tokenId), action, source);
}
QString Logger::makeSubjectMsg(const QString &subjectId, const QString &action, const QString &source)
{
QString msg = QString("Subject: %1 %2. Source: %3").arg(dbMan->getSubjectNameById(subjectId), action, source);
return msg;
return QString("Subject: %1 %2. Source: %3").arg(dbMan->getSubjectNameById(subjectId), action, source);
}
QString Logger::makeErrorMsg(const QString &source, const QString &errMsg)
{
return QString("Source: %1, Error: %2").arg(source, errMsg);
}

View File

@ -13,16 +13,16 @@ class Logger
Logger();
static DatabaseManager *dbMan;
static std::shared_ptr<DatabaseManager> dbMan;
public:
static Logger *getLogger();
static void log(const QString& msg);
static void logToDb(const QString& msg);
static void setDBMan(DatabaseManager* dbMan);
static void setDBMan(std::shared_ptr<DatabaseManager> dbMan);
static QString makeTokenMsg(const QString& tokenId, const QString& action, const QString& source);
static QString makeSubjectMsg(const QString& subjectId, const QString& action, const QString& source);
static QString makeErrorMsg(const QString& source, const QString& errMsg);
private:

View File

@ -2,16 +2,14 @@
RequestManager::RequestManager()
{
manager = new QNetworkAccessManager();
token = "";
loginStatus = false;
QObject::connect(manager, &QNetworkAccessManager::sslErrors, this, &RequestManager::onSSLError);
manager = std::make_unique<QNetworkAccessManager>();
connect(manager.get(), &QNetworkAccessManager::sslErrors, this, &RequestManager::onSSLError);
}
Response* RequestManager::login()
std::shared_ptr<Response> RequestManager::login()
{
Q_ASSERT(!loginResponse);
loginResponse = new Response;
loginResponse = std::make_shared<Response>();
QNetworkRequest request;
QString hash = encryptedPassword(this->password);
authHeader = getLoginHeader(this->user, hash);
@ -22,25 +20,24 @@ Response* RequestManager::login()
request.setUrl(this->host + "/AaaManager/authSession");
request.setRawHeader("Authorization", authHeader.toLocal8Bit());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=UTF-8");
QJsonDocument jsonDocument;
jsonDocument.setObject(reqBody);
QNetworkReply* reply = manager->post(request, jsonDocument.toJson());
loginResponse->setReply(reply);
QObject::connect(reply, &QNetworkReply::finished, [=]() {
connect(reply, &QNetworkReply::finished, [=]() {
if (reply->error())
{
qDebug() << "Login failed: "<< reply->errorString();
Logger::logToDb(Logger::makeErrorMsg("Request Manager", reply->errorString()));
loginStatus = false;
reply->deleteLater();
emit error();
return;
}
//qDebug() << "Logged in successfully.";
loginStatus = true;
emit successLogin();
reply->deleteLater();
});
connect(this, &RequestManager::successLogin, loginResponse, &Response::ready);
connect(this, &RequestManager::successLogin, loginResponse.get(), &Response::ready);
connect(this, &RequestManager::successLogin, this, &RequestManager::prepareAuthHeader);
return loginResponse;
}
@ -55,12 +52,12 @@ QNetworkReply* RequestManager::postRequest(const QString& endpoint, const QByteA
QObject::connect(reply, &QNetworkReply::finished, [=]() {
if (reply->error())
{
qDebug() << "Authorization failed: " << reply->errorString();
Logger::logToDb(Logger::makeErrorMsg("Request Manager", reply->errorString()));
loginStatus = false;
reply->deleteLater();
emit error();
return;
}
//qDebug() << "Authorized successfully, response ready.";
emit responseReady();
reply->deleteLater();
});
@ -68,7 +65,7 @@ QNetworkReply* RequestManager::postRequest(const QString& endpoint, const QByteA
}
// This will ensure login is called only once
Response* RequestManager::getLoginResponse() {
std::shared_ptr<Response> RequestManager::getLoginResponse() {
if (!loginResponse){
loginResponse = login();
}
@ -79,7 +76,7 @@ Response* RequestManager::postRequestReturnLogic(const QString& endpoint, const
{
auto loginResponse = getLoginResponse();
Q_ASSERT(loginResponse);
auto* response = new Response;
auto response = new Response;
if (!loginStatus){
connect(this, &RequestManager::successLogin, [=](){
@ -121,7 +118,7 @@ QString RequestManager::getLoginHeader(const QString& username, const QString& h
void RequestManager::prepareAuthHeader()
{
jsonResponse = loginResponse->getJson();
token = getFromJson(jsonResponse, "id");
QString token = getFromJson(jsonResponse, "id");
QString authValue = token + ":";
authHeader = "Basic " + authValue.toLocal8Bit().toBase64();
}
@ -146,7 +143,7 @@ QByteArray RequestManager::makeTimestampJson(uint64_t time)
return doc.toJson();
}
QByteArray RequestManager::makeTokensJson(const QHash<QString, QPointer<Token> > &tokens)
QByteArray RequestManager::makeTokensJson(const QHash<QString, std::shared_ptr<Token>> &tokens)
{
QJsonObject items;
QJsonArray jsonTokens;
@ -239,7 +236,7 @@ Response* RequestManager::getAccessGroupMembershipDeleted(uint64_t time)
return postRequestReturnLogic("/AccessManager/getAccessGroupMembershipDeleted", makeTimestampJson(time));
}
Response* RequestManager::setTokens(const QHash<QString, QPointer<Token> > &tokens)
Response* RequestManager::setTokens(const QHash<QString, std::shared_ptr<Token>> &tokens)
{
return postRequestReturnLogic("/TokenManager/setTokens", makeTokensJson(tokens));
}

View File

@ -31,7 +31,12 @@ class RequestManager : public QObject
Q_OBJECT
public:
friend class UnitTest;
friend class ComplexTest;
RequestManager();
// this should be in ColnodAPI class BEGIN
Response* getSubjects();
Response* getTokens();
Response* getTokenSubject();
@ -49,47 +54,47 @@ public:
Response* getAccessGroupMembershipUpdated(uint64_t time);
Response* getAccessGroupMembershipDeleted(uint64_t time);
Response* setTokens(const QHash<QString, QPointer<Token>> &tokens);
Response* setTokens(const QHash<QString, std::shared_ptr<Token>> &tokens);
Response* deleteTokens(const QList<QString> &ids);
Response* login(); //I want it private, but unittest???
const QJsonDocument &getConfig() const {return config;}
const QString &getResponse() const {return jsonResponse;}
// END
private:
// should be public
QNetworkReply* postRequest(const QString& endpoint, const QByteArray& json = QByteArray());
Response* postRequestReturnLogic(const QString& endpoint, const QByteArray& data = QByteArray());
std::shared_ptr<Response> login();
std::shared_ptr<Response> getLoginResponse();
QString getFromJson(const QString& json, const QString &member);
QString encryptedPassword(const QString& password);
QString getLoginHeader(const QString& username, const QString& hash);
// in colnod api as well
QByteArray makeTimestampJson(uint64_t time);
QByteArray makeTokensJson(const QHash<QString, QPointer<Token>> &tokens);
QByteArray makeIdsJson(const QList<QString> &ids);
Response* getLoginResponse();
QByteArray makeTokensJson(const QHash<QString, std::shared_ptr<Token>> &tokens); // maybe better to be in Token class
QByteArray makeIdsJson(const QList<QString> &ids); // Entity class
private slots:
void onSSLError(QNetworkReply *reply, const QList<QSslError> &errors);
//void onReplyFinished(QNetworkReply *reply);
void prepareAuthHeader();
signals:
void successLogin();
void responseReady();
void error();
private:
QNetworkAccessManager* manager = nullptr;
Response* loginResponse = nullptr;
std::unique_ptr<QNetworkAccessManager> manager;
std::shared_ptr<Response> loginResponse;
QJsonDocument config;
QString authHeader;
QString host = "https://192.168.1.3:8443";
const QString host = "https://192.168.1.3:8443";
//QString host = "https://localhost:8080";
QString password = "spaceti1";
QString user = "spaceti";
QString token;
const QString password = "spaceti1";
const QString user = "spaceti";
QString jsonResponse;
bool loginStatus;
bool loginStatus = false;
};

View File

@ -39,6 +39,6 @@ private:
QSet<QString> pinFlags;
//QList<QPointer<Attribute>> atr;
QList<QPair<QString, QString>> atr;
const std::array<QString, 6> attributeTypes = {"Jmeno", "Prijmeni", "ProfilParking", "Spolecnost", "Profil", "spz"};
const QList<QString> attributeTypes = {"Jmeno", "Prijmeni", "ProfilParking", "Spolecnost", "Profil", "spz"};
};

View File

@ -1,13 +1,16 @@
#include "colnodapi.h"
#include "syncmanager.h"
ColnodAPI::ColnodAPI(bool dryMode)
SyncManager::SyncManager(bool dryMode)
{
reqMan = new RequestManager();
dataMan = new DataManager(dryMode);
reqMan = std::make_unique<RequestManager>();
dataMan = std::make_unique<DataManager>(dryMode);
this->dryMode = dryMode;
connect(reqMan.get(), &RequestManager::error, this, &SyncManager::error);
connect(dataMan.get(), &DataManager::error, this, &SyncManager::error);
}
void ColnodAPI::loadDataFromColnod()
void SyncManager::loadDataFromColnod()
{
loadTokensFromColnod();
loadUpdatedDataFromColnod();
@ -15,7 +18,7 @@ void ColnodAPI::loadDataFromColnod()
}
// download all tokens form colnod for comparing with tokens to update from DB
void ColnodAPI::loadTokensFromColnod()
void SyncManager::loadTokensFromColnod()
{
Response* resp = reqMan->getTokens();
connect(resp, &Response::ready, [=](){
@ -26,7 +29,7 @@ void ColnodAPI::loadTokensFromColnod()
}
// fill tokens/subjects to update in data manager
void ColnodAPI::loadUpdatedDataFromColnod()
void SyncManager::loadUpdatedDataFromColnod()
{
uint64_t lastUpdate = dataMan->getLastSync();
Response* resp0 = reqMan->getSubjectsUpdated(lastUpdate);
@ -45,7 +48,7 @@ void ColnodAPI::loadUpdatedDataFromColnod()
}
// fill tokens/subjects to delete in data manager
void ColnodAPI::loadDeletedDataFromColnod()
void SyncManager::loadDeletedDataFromColnod()
{
uint64_t lastUpdate = dataMan->getLastSync();
Response* resp2 = reqMan->getSubjectsDeleted(lastUpdate);
@ -65,12 +68,12 @@ void ColnodAPI::loadDeletedDataFromColnod()
}
// fill structures in data manager (tokens to updata/to delte)
void ColnodAPI::loadDataFromDB()
void SyncManager::loadDataFromDB()
{
dataMan->fillTokensToChangeDB();
}
void ColnodAPI::syncDataFromColnodToDB()
void SyncManager::syncDataFromColnodToDB()
{
syncUpdatedDataFromColnodToDB();
if (dataMan->getLastSync() != 0)
@ -78,21 +81,21 @@ void ColnodAPI::syncDataFromColnodToDB()
}
// push data from colnod to DB
void ColnodAPI::syncUpdatedDataFromColnodToDB()
void SyncManager::syncUpdatedDataFromColnodToDB()
{
dataMan->pushSubjectsToDB();
dataMan->pushTokensToDB();
}
// set deleted tokens from Colnod, delete subject
void ColnodAPI::syncDeletedDataFromColnodToDB()
void SyncManager::syncDeletedDataFromColnodToDB()
{
dataMan->deleteSubjectsFromDB();
dataMan->setDeletedToTokensFromDB();
}
// push changes form DB to Colnod
void ColnodAPI::syncDataFromDBToColnod()
void SyncManager::syncDataFromDBToColnod()
{
if (!dataMan->getTokensToUpdateDB().contains("empty")){
@ -105,9 +108,9 @@ void ColnodAPI::syncDataFromDBToColnod()
}
else
updateFinished = true;
connect(this, &ColnodAPI::dataUpdatedToColnod, dataMan, &DataManager::clear);
connect(this, &ColnodAPI::dataUpdatedToColnod, dataMan, &DataManager::setLastSync);
connect(this, &ColnodAPI::dataUpdatedToColnod, [=](){
connect(this, &SyncManager::dataUpdatedToColnod, dataMan.get(), &DataManager::clear);
connect(this, &SyncManager::dataUpdatedToColnod, dataMan.get(), &DataManager::setLastSync);
connect(this, &SyncManager::dataUpdatedToColnod, [=](){
auto resp = reqMan->getTokensUpdated(dataMan->getCurrentSync());
connect(resp, &Response::ready, [=](){
dataMan->fillTokensToUpdateColnod(resp->getJson());
@ -121,7 +124,7 @@ void ColnodAPI::syncDataFromDBToColnod()
}
// add or update tokens to Colnod
void ColnodAPI::syncUpdatedDataFromDBToColnod()
void SyncManager::syncUpdatedDataFromDBToColnod()
{
auto tokensToUpdate = dataMan->getTokensToUpdateDB();
if (dryMode){
@ -139,7 +142,7 @@ void ColnodAPI::syncUpdatedDataFromDBToColnod()
}
// delete tokens in Colnod
void ColnodAPI::syncDeletedDataFromDBToColnod()
void SyncManager::syncDeletedDataFromDBToColnod()
{
dataMan->filterTokensDB();
auto tokensToDelete = dataMan->getTokensToDeleteDB();
@ -158,20 +161,20 @@ void ColnodAPI::syncDeletedDataFromDBToColnod()
}
// For full sync
void ColnodAPI::prepareDatabase()
void SyncManager::prepareDatabase()
{
dataMan->emptyDatabase();
}
// emit signal when all data is downloaded from Colnod
void ColnodAPI::areChangedDataReady()
void SyncManager::areChangedDataReady()
{
if (dataMan->haveChangedData())
emit dataDownloaded();
}
// emit signal when writing to Colnod is finised
void ColnodAPI::areDataUpdatedToColnod()
void SyncManager::areDataUpdatedToColnod()
{
if (deleteFinished && updateFinished)
{

View File

@ -4,13 +4,13 @@
#include "datamanager.h"
#include "logger.h"
class ColnodAPI : public QObject
class SyncManager : public QObject
{
Q_OBJECT
public:
ColnodAPI(bool dryMode = false);
SyncManager(bool dryMode = false);
void syncDataFromColnodToDB();
void syncDataFromDBToColnod();
@ -25,6 +25,7 @@ signals:
void dataDownloaded();
void dataUpdatedToColnod();
void syncFinished();
void error();
private slots:
@ -46,8 +47,8 @@ private:
void areDataUpdatedToColnod();
private:
RequestManager* reqMan = nullptr;
DataManager* dataMan = nullptr;
std::unique_ptr<RequestManager> reqMan;
std::unique_ptr<DataManager> dataMan;
bool dryMode = false;
bool updateFinished = false;
bool deleteFinished = false;

View File

@ -22,6 +22,10 @@ Token::Token(const QString &name)
this->setName(name);
}
Token::~Token()
{
}
void Token::fromJSON(const QJsonObject &json) {
Entity::fromJSON(json);

View File

@ -14,6 +14,7 @@ public:
Token() = default;
Token(const QString& name, QString tokenData, const QString& decription = "mobile");
Token(const QString& name);
~Token() override;
friend bool operator<(const Token &lToken, const Token &rToken){
return lToken.getLastModified() < rToken.getLastUpdate();

View File

@ -14,7 +14,7 @@ void UnitTest::loginSuccessfully()
spy.wait(timeout);
QCOMPARE(spy.count(), 1);
QString json = testAccess->getResponse();
QString json = testAccess->jsonResponse;
qDebug() << json;
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8());
QVERIFY2(doc.object().value("id").isString(), "No parameter 'id' in response");
@ -211,15 +211,14 @@ void UnitTest::setTokens()
QJsonObject obj = doc.object();
QJsonArray arr = obj["items"].toArray();
qDebug() << arr;
QHash<QString, QPointer<Token>> tokens;
QHash<QString, std::shared_ptr<Token>> tokens;
for (auto object : arr)
{
auto token = new Token;
auto token = std::shared_ptr<Token>();
token->fromJSON(object.toObject());
qDebug() << token;
tokens.insert(token->idToStringWithoutBraces(), token);
}
auto* testAccess = new RequestManager();
auto testAccess = new RequestManager();
QSignalSpy spy(testAccess, SIGNAL(responseReady()));
Response* response = testAccess->setTokens(tokens);
QCOMPARE(spy.count(), 0);

View File

@ -13,7 +13,7 @@ void ComplexTest::initTestCase()
// QTest::qWait(2500);
// Logger *logger = Logger::getLogger();
start = QDateTime::currentMSecsSinceEpoch()-2000;
api = new ColnodAPI();
api = new SyncManager();
qDebug() << start;
}
@ -37,8 +37,8 @@ void ComplexTest::complexTest()
// LOGIN_BEGIN
reqMan = new RequestManager;
QSignalSpy loginSpy(reqMan, &RequestManager::successLogin);
Response* loginResp = reqMan->login();
QSignalSpy loginRespSpy(loginResp, &Response::ready);
auto loginResp = reqMan->login();
QSignalSpy loginRespSpy(loginResp.get(), &Response::ready);
QCOMPARE(loginSpy.count(), 0);
QCOMPARE(loginRespSpy.count(), 0);
loginSpy.wait(timeout);
@ -58,7 +58,7 @@ void ComplexTest::complexTest()
// ADD_TOKENS_CHECK_BEGIN
QHash<QString, QPointer<Token>> tokens;
QHash<QString, std::shared_ptr<Token>> tokens;
auto token = getTestToken();
tokens.insert(token->idToStringWithoutBraces(), token);
Response* setTokensResp = reqMan->setTokens(tokens);
@ -117,14 +117,14 @@ void ComplexTest::fullSync()
{
api->prepareDatabase();
api->loadDataFromColnod();
QSignalSpy spy(api, &ColnodAPI::dataDownloaded);
QSignalSpy spy(api, &SyncManager::dataDownloaded);
spy.wait(timeout);
api->loadDataFromDB();
api->syncDataFromColnodToDB();
api->syncDataFromDBToColnod();
QSignalSpy processSpy(api, &ColnodAPI::dataUpdatedToColnod);
QSignalSpy processSpy(api, &SyncManager::dataUpdatedToColnod);
processSpy.wait(timeout);
QSignalSpy finish(api, &ColnodAPI::syncFinished);
QSignalSpy finish(api, &SyncManager::syncFinished);
finish.wait(timeout);
}
@ -132,14 +132,14 @@ void ComplexTest::syncLastUpdated()
{
Logger::log("ahoj");
api->loadDataFromColnod();
QSignalSpy spy(api, &ColnodAPI::dataDownloaded);
QSignalSpy spy(api, &SyncManager::dataDownloaded);
spy.wait(timeout);
api->loadDataFromDB();
api->syncDataFromColnodToDB();
api->syncDataFromDBToColnod();
QSignalSpy processSpy(api, &ColnodAPI::dataUpdatedToColnod);
QSignalSpy processSpy(api, &SyncManager::dataUpdatedToColnod);
processSpy.wait(timeout);
QSignalSpy finish(api, &ColnodAPI::syncFinished);
QSignalSpy finish(api, &SyncManager::syncFinished);
finish.wait(timeout);
qDebug() << "All right, at least should be.";
}
@ -175,7 +175,7 @@ QJsonDocument ComplexTest::getJsonDoc(const QString &json)
return QJsonDocument::fromJson(json.toUtf8());
}
QPointer<Token> ComplexTest::getTestToken()
std::shared_ptr<Token> ComplexTest::getTestToken()
{
QJsonObject jsonToken;
jsonToken.insert("id", "062c93f6-ba3e-46af-a3a6-7a2988d1f0e9");
@ -191,7 +191,7 @@ QPointer<Token> ComplexTest::getTestToken()
flags.push_back("NoValidity");
jsonToken.insert("flags", flags);
jsonToken.insert("subjectId", "72b37f7e-5761-4e6c-8e87-20c0bed0d904");
QPointer<Token> token = new Token;
auto token = std::shared_ptr<Token>();
token->fromJSON(jsonToken);
return token;
}

View File

@ -5,7 +5,7 @@
#include <QtTest/QtTest>
#include "response.h"
#include "requestmanager.h"
#include "colnodapi.h"
#include "syncmanager.h"
#include "logger.h"
class ComplexTest : public QObject
@ -25,7 +25,7 @@ private:
int getNumOfSubjects();
int getNumOfTokens();
QJsonDocument getJsonDoc(const QString &json);
QPointer<Token> getTestToken();
std::shared_ptr<Token> getTestToken();
// VARIABLES
@ -34,7 +34,7 @@ private:
QString password = "spaceti1";
RequestManager* reqMan = nullptr;
uint64_t start = 0;
ColnodAPI* api = nullptr;
SyncManager* api = nullptr;
static constexpr qint16 timeout = 10000;
};