mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-09 05:28:09 +08:00
refs #605, fixed unit test itself
* threaded reader were normal members causing a crash when those were moved in their own thread * we need own event processing for unit test * Network request needs to be generated in main thread * don`t shutdown readers on QCoreApplication::aboutToQuit, let CApplication handle it * use CApplication in unit test (as in real world) Unrelated: * access global setup via application
This commit is contained in:
committed by
Mathew Sutcliffe
parent
12957f8ec0
commit
f124412896
@@ -18,6 +18,7 @@
|
||||
#include "blackmisc/project.h"
|
||||
#include "blackmisc/dbusserver.h"
|
||||
#include "blackmisc/registermetadata.h"
|
||||
#include "blackmisc/threadutils.h"
|
||||
#include "blackmisc/network/networkutils.h"
|
||||
#include "blackmisc/simulation/aircraftmodellist.h"
|
||||
#include "blackmisc/verify.h"
|
||||
@@ -32,6 +33,7 @@ using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::Simulation;
|
||||
using namespace BlackMisc::Weather;
|
||||
using namespace BlackCore;
|
||||
using namespace BlackCore::Data;
|
||||
|
||||
BlackCore::CApplication *sApp = nullptr; // set by constructor
|
||||
|
||||
@@ -96,6 +98,13 @@ namespace BlackCore
|
||||
return QCoreApplication::instance()->applicationName() + " " + CProject::version();
|
||||
}
|
||||
|
||||
Data::CGlobalSetup CApplication::getGlobalSetup() const
|
||||
{
|
||||
const CSetupReader *r = this->m_setupReader.data();
|
||||
if (!r) { return CGlobalSetup(); }
|
||||
return r->getSetup();
|
||||
}
|
||||
|
||||
bool CApplication::start(bool waitForStart)
|
||||
{
|
||||
if (!this->m_parsed)
|
||||
@@ -130,7 +139,9 @@ namespace BlackCore
|
||||
const QTime dieTime = QTime::currentTime().addMSecs(5000);
|
||||
while (QTime::currentTime() < dieTime && !this->m_started && !this->m_startUpCompleted)
|
||||
{
|
||||
// Alternative: use QEventLoop, which seemed to make the scenario here more complex
|
||||
QCoreApplication::instance()->processEvents(QEventLoop::AllEvents, 250);
|
||||
QThread::msleep(250); // avoid CPU loop overload by "infinite loop"
|
||||
}
|
||||
if (!this->m_startUpCompleted)
|
||||
{
|
||||
@@ -170,46 +181,75 @@ namespace BlackCore
|
||||
return this->m_webDataServices.data();
|
||||
}
|
||||
|
||||
QNetworkReply *CApplication::getFromNetwork(const CUrl &url, const BlackMisc::CSlot<void (QNetworkReply *)> &callback)
|
||||
bool CApplication::isApplicationThread() const
|
||||
{
|
||||
return CThreadUtils::isCurrentThreadApplicationThread();
|
||||
}
|
||||
|
||||
QNetworkReply *CApplication::getFromNetwork(const CUrl &url, const CSlot<void(QNetworkReply *)> &callback)
|
||||
{
|
||||
if (this->m_shutdown) { return nullptr; }
|
||||
return getFromNetwork(url.toNetworkRequest(), callback);
|
||||
}
|
||||
|
||||
QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, const BlackMisc::CSlot<void(QNetworkReply *)> &callback)
|
||||
QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, const CSlot<void(QNetworkReply *)> &callback)
|
||||
{
|
||||
if (this->m_shutdown) { return nullptr; }
|
||||
QNetworkRequest r(request);
|
||||
CNetworkUtils::ignoreSslVerification(r);
|
||||
QWriteLocker locker(&m_accessManagerLock);
|
||||
Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread");
|
||||
if (QThread::currentThread() != this->m_accessManager.thread())
|
||||
{
|
||||
QTimer::singleShot(0, this, [this, request, callback]() { this->getFromNetwork(request, callback); });
|
||||
return nullptr; // not yet started
|
||||
}
|
||||
|
||||
Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch");
|
||||
QNetworkRequest r(request); // no QObject
|
||||
CNetworkUtils::ignoreSslVerification(r);
|
||||
QNetworkReply *reply = this->m_accessManager.get(r);
|
||||
if (callback)
|
||||
{
|
||||
connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); });
|
||||
connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }, Qt::QueuedConnection);
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, const QByteArray &data, const BlackMisc::CSlot<void (QNetworkReply *)> &callback)
|
||||
QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, const QByteArray &data, const CSlot<void(QNetworkReply *)> &callback)
|
||||
{
|
||||
if (this->m_shutdown) { return nullptr; }
|
||||
QWriteLocker locker(&m_accessManagerLock);
|
||||
Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread");
|
||||
if (QThread::currentThread() != this->m_accessManager.thread())
|
||||
{
|
||||
QTimer::singleShot(0, this, [this, request, data, callback]() { this->postToNetwork(request, data, callback); });
|
||||
return nullptr; // not yet started
|
||||
}
|
||||
|
||||
Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch");
|
||||
QNetworkRequest r(request);
|
||||
CNetworkUtils::ignoreSslVerification(r);
|
||||
QWriteLocker locker(&m_accessManagerLock);
|
||||
QNetworkReply *reply = this->m_accessManager.post(r, data);
|
||||
if (callback)
|
||||
{
|
||||
connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); });
|
||||
connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }, Qt::QueuedConnection);
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart, const BlackMisc::CSlot<void (QNetworkReply *)> &callback)
|
||||
QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart, const CSlot<void(QNetworkReply *)> &callback)
|
||||
{
|
||||
if (this->m_shutdown) { return nullptr; }
|
||||
QWriteLocker locker(&m_accessManagerLock);
|
||||
Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread");
|
||||
if (QThread::currentThread() != this->m_accessManager.thread())
|
||||
{
|
||||
QTimer::singleShot(0, this, [this, request, multiPart, callback]() { this->postToNetwork(request, multiPart, callback); });
|
||||
return nullptr; // not yet started
|
||||
}
|
||||
|
||||
Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch");
|
||||
QNetworkRequest r(request);
|
||||
CNetworkUtils::ignoreSslVerification(r);
|
||||
QWriteLocker locker(&m_accessManagerLock);
|
||||
QNetworkReply *reply = this->m_accessManager.post(r, multiPart);
|
||||
if (callback)
|
||||
{
|
||||
@@ -244,6 +284,16 @@ namespace BlackCore
|
||||
return QCoreApplication::arguments();
|
||||
}
|
||||
|
||||
void CApplication::processEventsFor(int milliseconds)
|
||||
{
|
||||
const QTime end = QTime::currentTime().addMSecs(milliseconds);
|
||||
while (QTime::currentTime() <= end)
|
||||
{
|
||||
QCoreApplication::processEvents();
|
||||
QThread::msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
bool CApplication::useContexts(const CCoreFacadeConfig &coreConfig)
|
||||
{
|
||||
Q_ASSERT_X(this->m_parsed, Q_FUNC_INFO, "Call this after parsing");
|
||||
@@ -380,6 +430,7 @@ namespace BlackCore
|
||||
this->m_started = this->asyncWebAndContextStart();
|
||||
}
|
||||
this->m_startUpCompleted = true;
|
||||
emit this->startUpCompleted(this->m_started);
|
||||
}
|
||||
|
||||
bool CApplication::asyncWebAndContextStart()
|
||||
|
||||
@@ -71,31 +71,9 @@ namespace BlackCore
|
||||
//! Application name and version
|
||||
QString getApplicationNameAndVersion() const;
|
||||
|
||||
//! Start services, if not yet parsed call CApplication::parse
|
||||
virtual bool start(bool waitForStart = true);
|
||||
|
||||
//! Wait for stert by calling the event loop and waiting until everything is ready
|
||||
bool waitForStart();
|
||||
|
||||
//! Request to get network reply
|
||||
//! Global setup
|
||||
//! \threadsafe
|
||||
QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
//! Request to get network reply
|
||||
//! \threadsafe
|
||||
QNetworkReply *getFromNetwork(const QNetworkRequest &request,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
//! Post to network
|
||||
//! \threadsafe
|
||||
QNetworkReply *postToNetwork(const QNetworkRequest &request, const QByteArray &data,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
//! Post to network
|
||||
//! \threadsafe
|
||||
QNetworkReply *postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
BlackCore::Data::CGlobalSetup getGlobalSetup() const;
|
||||
|
||||
//! Delete all cookies from cookier manager
|
||||
void deleteAllCookies();
|
||||
@@ -112,6 +90,9 @@ namespace BlackCore
|
||||
//! Get the web data services
|
||||
CWebDataServices *getWebDataServices() const;
|
||||
|
||||
//! Currently running in application thread?
|
||||
bool isApplicationThread() const;
|
||||
|
||||
//! Run event loop
|
||||
static int exec();
|
||||
|
||||
@@ -121,6 +102,9 @@ namespace BlackCore
|
||||
//! Similar to QCoreApplication::arguments
|
||||
static QStringList arguments();
|
||||
|
||||
//! Process all events for some time
|
||||
static void processEventsFor(int milliseconds);
|
||||
|
||||
// ----------------------- parsing ----------------------------------------
|
||||
|
||||
//! \name parsing of command line options
|
||||
@@ -197,10 +181,39 @@ namespace BlackCore
|
||||
//! Graceful shutdown
|
||||
virtual void gracefulShutdown();
|
||||
|
||||
//! Start services, if not yet parsed call CApplication::parse
|
||||
virtual bool start(bool waitForStart = true);
|
||||
|
||||
//! Wait for stert by calling the event loop and waiting until everything is ready
|
||||
bool waitForStart();
|
||||
|
||||
//! Request to get network reply
|
||||
//! \threadsafe
|
||||
QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
//! Request to get network reply
|
||||
//! \threadsafe
|
||||
QNetworkReply *getFromNetwork(const QNetworkRequest &request,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
//! Post to network
|
||||
//! \threadsafe
|
||||
QNetworkReply *postToNetwork(const QNetworkRequest &request, const QByteArray &data,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
//! Post to network
|
||||
//! \threadsafe
|
||||
QNetworkReply *postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart,
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
signals:
|
||||
//! Setup syncronized
|
||||
void setupSyncronized();
|
||||
|
||||
//! Startup has been completed
|
||||
void startUpCompleted(bool success);
|
||||
|
||||
//! Facade started
|
||||
void coreFacadeStarted();
|
||||
|
||||
@@ -212,9 +225,6 @@ namespace BlackCore
|
||||
void ps_setupSyncronized(bool success);
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
CApplication(const QString &applicationName, QCoreApplication *app);
|
||||
|
||||
//! Display help message
|
||||
virtual void cmdLineHelpMessage();
|
||||
|
||||
|
||||
@@ -66,17 +66,9 @@ namespace BlackCore
|
||||
|
||||
QString query = params.toString();
|
||||
const QNetworkRequest request(CNetworkUtils::getNetworkRequest(url, CNetworkUtils::PostUrlEncoded));
|
||||
QNetworkReply *r = sApp->postToNetwork(request, query.toUtf8(), { this, &CDatabaseAuthenticationService::ps_parseServerResponse});
|
||||
if (!r)
|
||||
{
|
||||
QString rm("Cannot send request to authentication server %1");
|
||||
msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, rm.arg(url.toQString())));
|
||||
}
|
||||
else
|
||||
{
|
||||
QString rm("Sent request to authentication server %1");
|
||||
msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityInfo, rm.arg(url.toQString())));
|
||||
}
|
||||
sApp->postToNetwork(request, query.toUtf8(), { this, &CDatabaseAuthenticationService::ps_parseServerResponse});
|
||||
QString rm("Sent request to authentication server %1");
|
||||
msgs.push_back(CStatusMessage(cats, CStatusMessage::SeverityInfo, rm.arg(url.toQString())));
|
||||
return msgs;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user