refs #369, unit test for interpolator

This commit is contained in:
Klaus Basan
2015-02-24 01:58:00 +01:00
parent 420a47e90c
commit bd58475436
9 changed files with 250 additions and 73 deletions

View File

@@ -1,20 +1,24 @@
/* Copyright (C) 2014
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "testblackcoremain.h" #include "testblackcoremain.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
using namespace BlackCoreTest; using namespace BlackCoreTest;
/*! //! Starter for test cases
* Starter for test cases
* \brief main
* \param argc
* \param argv
* \return
*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
CBlackCoreTestMain::unitMain(argc, argv); CBlackCoreTestMain::unitMain(argc, argv);
Q_UNUSED(a);
// bye // bye
return 0; return 0;

View File

@@ -1,7 +1,11 @@
/* Copyright (C) 2013 VATSIM Community / contributors /* Copyright (C) 2014
* This Source Code Form is subject to the terms of the Mozilla Public * swift project Community / Contributors
* License, v. 2.0. If a copy of the MPL was not distributed with this *
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "testblackcoremain.h" #include "testblackcoremain.h"
#include "testinterpolator.h" #include "testinterpolator.h"
@@ -10,20 +14,20 @@
namespace BlackCoreTest namespace BlackCoreTest
{ {
/* /*
* Starting main, equivalent to QTEST_APPLESS_MAIN for multiple test classes. * Starting main, equivalent to QTEST_APPLESS_MAIN for multiple test classes.
*/ */
int CBlackCoreTestMain::unitMain(int argc, char *argv[]) int CBlackCoreTestMain::unitMain(int argc, char *argv[])
{
int status = 0;
{ {
CTestInterpolator interpolatorTests; int status = 0;
status |= QTest::qExec(&interpolatorTests, argc, argv); {
CTestInterpolator interpolatorTests;
status |= QTest::qExec(&interpolatorTests, argc, argv);
}
{
// CTestNetwork networkTests;
// status |= QTest::qExec(&networkTests, argc, argv);
}
return status;
} }
{
CTestNetwork networkTests;
status |= QTest::qExec(&networkTests, argc, argv);
}
return status;
}
} // namespace } // namespace

View File

@@ -1,24 +1,121 @@
/* Copyright (C) 2013 VATSIM Community / contributors /* Copyright (C) 2014
* This Source Code Form is subject to the terms of the Mozilla Public * swift project Community / Contributors
* License, v. 2.0. If a copy of the MPL was not distributed with this *
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "testinterpolator.h" #include "testinterpolator.h"
#include "blackcore/interpolator_linear.h" #include "blackcore/interpolator_linear.h"
#include "blackmisc/simulation/simdirectaccessremoteaircraftdummy.h"
#include <QScopedPointer>
using namespace BlackCore; using namespace BlackCore;
using namespace BlackMisc::Aviation; using namespace BlackMisc::Aviation;
using namespace BlackMisc::Geo;
using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Simulation;
namespace BlackCoreTest namespace BlackCoreTest
{ {
/* void CTestInterpolator::linearInterpolator()
* Interpolator tests
*/
void CTestInterpolator::interpolatorBasics()
{ {
//! \todo what would we test here? QScopedPointer<CRemoteAircraftProviderDummy> provider(new CRemoteAircraftProviderDummy());
CInterpolatorLinear interpolator(provider.data());
const CCallsign cs("SWIFT");
const qint64 ts = QDateTime::currentMSecsSinceEpoch();
const qint64 deltaT = 5000; // ms
for (int i = 0; i < IInterpolator::MaxSituationsPerCallsign; i++)
{
CAltitude a(i, CAltitude::MeanSeaLevel, CLengthUnit::m());
CLatitude lat(i, CAngleUnit::deg());
CLongitude lng(180.0 + i, CAngleUnit::deg());
CLength height(0, CLengthUnit::m());
CHeading heading(i * 10, CHeading::True, CAngleUnit::deg());
CAngle bank(i, CAngleUnit::deg());
CAngle pitch(i, CAngleUnit::deg());
CSpeed gs(i * 10, CSpeedUnit::km_h());
CCoordinateGeodetic c(lat, lng, height);
CAircraftSituation s(c, a, heading, pitch, bank, gs);
s.setMSecsSinceEpoch(ts - deltaT * i); // values in past
s.setCallsign(cs);
// check height above ground
CLength hag = (a - height);
QVERIFY2(s.getHeightAboveGround() == hag, "Wrong elevation");
provider->insertNewSituation(s);
}
// make sure signals are processed
QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
// check if all situations have been received
QVERIFY2(interpolator.getSituationsForCallsign(cs).size() == IInterpolator::MaxSituationsPerCallsign, "Missing situations");
// interpolation
bool ok = false;
double latOld = 360.0;
double lngOld = 360.0;
for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250)
{
// This will use range
// from: ts - 2* deltaT - IInterpolator::TimeOffsetMs
// to: ts - IInterpolator::TimeOffsetMs
CAircraftSituation currentSituation(interpolator.getCurrentInterpolatedSituation
(interpolator.getSituationsByCallsign(), cs, currentTime, &ok)
);
QVERIFY2(ok, "OK was false");
double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5);
QVERIFY2(latDeg < latOld && lngDeg < lngOld, "Values shall decrease");
latOld = latDeg;
lngOld = lngDeg;
}
QTime timer;
timer.start();
int interpolationNo = 0;
qint64 startTimeMsSinceEpoch = ts - 2 * deltaT;
for (int callsigns = 0; callsigns < 20; callsigns++)
{
for (qint64 currentTime = startTimeMsSinceEpoch; currentTime < ts; currentTime += 250)
{
// This will use range
// from: ts - 2* deltaT - IInterpolator::TimeOffsetMs
// to: ts - IInterpolator::TimeOffsetMs
CAircraftSituation currentSituation(interpolator.getCurrentInterpolatedSituation
(interpolator.getSituationsByCallsign(), cs, currentTime, &ok)
);
QVERIFY2(ok, "OK was false");
QVERIFY2(currentSituation.getCallsign() == cs, "Wrong callsign");
double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5);
Q_UNUSED(latDeg);
Q_UNUSED(lngDeg);
interpolationNo++;
}
}
int timeMs = timer.elapsed();
QVERIFY2(timeMs < interpolationNo, "Interpolation > 1ms");
interpolator.syncRequestSituationsCalculationsForAllCallsigns(1, startTimeMsSinceEpoch);
CAircraftSituationList interpolationsSync(interpolator.getRequest(1));
QVERIFY(interpolationsSync.size() == 1);
QVERIFY(interpolationsSync.containsCallsign(cs));
interpolator.asyncRequestSituationsCalculationsForAllCallsigns(2, startTimeMsSinceEpoch);
QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
CAircraftSituationList interpolationsAsync(interpolator.getRequest(1));
QVERIFY(interpolationsAsync.size() == 1);
QVERIFY(interpolationsAsync.containsCallsign(cs));
QVERIFY2(interpolationsAsync.front() == interpolationsSync.front(), "Calculated values should be equal");
} }
} // namespace } // namespace

View File

@@ -1,7 +1,13 @@
/* Copyright (C) 2013 VATSIM Community / contributors /* Copyright (C) 2014
* This Source Code Form is subject to the terms of the Mozilla Public * swift project Community / Contributors
* License, v. 2.0. If a copy of the MPL was not distributed with this *
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORETEST_TESTAVIATIONBASE_H #ifndef BLACKCORETEST_TESTAVIATIONBASE_H
#define BLACKCORETEST_TESTAVIATIONBASE_H #define BLACKCORETEST_TESTAVIATIONBASE_H
@@ -11,27 +17,19 @@
namespace BlackCoreTest namespace BlackCoreTest
{ {
/*! //! Interpolator classes basic tests
* \brief Interpolator classes basic tests class CTestInterpolator : public QObject
*/ {
class CTestInterpolator : public QObject Q_OBJECT
{
Q_OBJECT
public: public:
/*! //! Standard test case constructor
* \brief Standard test case constructor explicit CTestInterpolator(QObject *parent = nullptr) : QObject(parent) {}
* \param parent
*/
explicit CTestInterpolator(QObject *parent = 0) : QObject(parent) {}
private slots: private slots:
//! Basic unit tests for interpolator
/*! void linearInterpolator();
* \brief Basic unit tests for interpolator };
*/
void interpolatorBasics();
};
} // namespace } // namespace

View File

@@ -22,7 +22,7 @@ void BlackCoreTest::CTestNetwork::networkTest(BlackCore::INetwork *net)
EXPECT_UNIT(e) EXPECT_UNIT(e)
.send(&INetwork::presetServer, CServer("", "", "vatsim-germany.org", 6809, CUser("1234567", "", "", "123456"))) .send(&INetwork::presetServer, CServer("", "", "vatsim-germany.org", 6809, CUser("1234567", "", "", "123456")))
.send(&INetwork::presetCallsign, "BLACK") .send(&INetwork::presetCallsign, "SWIFT")
.send(&INetwork::presetIcaoCodes, CAircraftIcao("C172", "P1L", "YYY", "YYY", "white")) .send(&INetwork::presetIcaoCodes, CAircraftIcao("C172", "P1L", "YYY", "YYY", "white"))
.send(&INetwork::initiateConnection) .send(&INetwork::initiateConnection)
.expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus, INetwork::ConnectionStatus newStatus) .expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus, INetwork::ConnectionStatus newStatus)

View File

@@ -100,8 +100,8 @@ namespace BlackMiscTest
void CTestAviation::callsignWithContainers() void CTestAviation::callsignWithContainers()
{ {
CCallsign cs1("EDDm_twr"); CCallsign cs1("EDDm_twr");
CCallsign cs2("EDDmtwr"); CCallsign cs2("eddm_TWR");
CCallsign cs3("EDDmapp", "München Radar"); CCallsign cs3("EDDm_app", "München Radar");
QVERIFY2(cs1 == cs2, "Callsigns shall be equal"); QVERIFY2(cs1 == cs2, "Callsigns shall be equal");
QVERIFY2(cs1 != cs3, "Callsigns shall not be equal"); QVERIFY2(cs1 != cs3, "Callsigns shall not be equal");
@@ -164,7 +164,7 @@ namespace BlackMiscTest
QVERIFY2(icao1 == icao2, "ICAOs shall be equal"); QVERIFY2(icao1 == icao2, "ICAOs shall be equal");
CCallsign call1("EDDS_N_APP"); CCallsign call1("EDDS_N_APP");
CCallsign call2("eddsnapp"); CCallsign call2("edds_n_app");
QVERIFY2(call1 == call2, "Callsigns shall be equal"); QVERIFY2(call1 == call2, "Callsigns shall be equal");
CAtcStation atc1(c1, user1, f1, situation1.getPosition(), CLength(), false, QDateTime(), QDateTime(), CInformationMessage(CInformationMessage::ATIS, "foo")); CAtcStation atc1(c1, user1, f1, situation1.getPosition(), CLength(), false, QDateTime(), QDateTime(), CInformationMessage(CInformationMessage::ATIS, "foo"));

View File

@@ -15,6 +15,7 @@
#include "blackmisc/collection.h" #include "blackmisc/collection.h"
#include "blackmisc/sequence.h" #include "blackmisc/sequence.h"
#include "blackmisc/avcallsignlist.h" #include "blackmisc/avcallsignlist.h"
#include "blackmisc/avaircraftsituationlist.h"
#include "blackmisc/dictionary.h" #include "blackmisc/dictionary.h"
#include <QList> #include <QList>
#include <QVector> #include <QVector>
@@ -128,7 +129,7 @@ namespace BlackMiscTest
QVERIFY2(found.isEmpty(), "Empty found"); QVERIFY2(found.isEmpty(), "Empty found");
callsigns.push_back(CCallsign("EDDM_TWR")); callsigns.push_back(CCallsign("EDDM_TWR"));
callsigns.push_back(CCallsign("KLAX_TWR")); callsigns.push_back(CCallsign("KLAX_TWR"));
found = callsigns.findBy(&CCallsign::asString, "KLAXTWR"); found = callsigns.findBy(&CCallsign::asString, "KLAX_TWR");
QVERIFY2(found.size() == 1, "found"); QVERIFY2(found.size() == 1, "found");
} }
@@ -213,4 +214,70 @@ namespace BlackMiscTest
QVERIFY2(d1 == d4, "JSON serialization/deserialization failed"); QVERIFY2(d1 == d4, "JSON serialization/deserialization failed");
} }
} //namespace BlackMiscTest void CTestContainers::timestampList()
{
CAircraftSituationList situations;
const qint64 ts = QDateTime::currentMSecsSinceEpoch();
const int no = 10;
for (int i = 0; i < no; ++i)
{
CAircraftSituation s;
s.setCallsign("CS" + QString::number(i));
s.setMSecsSinceEpoch(ts - 10 * i);
situations.push_back(s);
}
// test sorting
situations.sortOldestFirst();
qint64 ms = situations.front().getMSecsSinceEpoch();
QVERIFY2(ms == ts - 10 * (no - 1), "Oldest value not first");
situations.sortLatestFirst();
ms = situations.front().getMSecsSinceEpoch();
QVERIFY2(ms == ts, "Latest value not first");
// split in half
situations.sortOldestFirst(); // check that we really get latest first
QList<CAircraftSituationList> split = situations.splitByTime(ts - ((no / 2) * 10) + 1);
CAircraftSituationList before = split[0];
CAircraftSituationList after = split[1];
int beforeSize = before.size();
int afterSize = after.size();
QVERIFY(beforeSize == no / 2);
QVERIFY(afterSize == no / 2);
// check sort order, latest should
for (int i = 0; i < no; ++i)
{
CAircraftSituation s = (i < no / 2) ? before[i] : after[i - no / 2];
ms = s.getMSecsSinceEpoch();
QVERIFY2(ms == ts - 10 * i, "time does not match");
}
// test shifting
situations.clear();
const int maxElements = 8;
QVERIFY(situations.isEmpty());
for (int i = 0; i < no; ++i)
{
qint64 cTs = ts - 10 * i;
CAircraftSituation s;
s.setCallsign("CS" + QString::number(i));
s.setMSecsSinceEpoch(cTs);
situations.insertTimestampObject(s, maxElements);
if (i > maxElements - 1)
{
QVERIFY2(situations.size() == maxElements, "Situations must only contain max.elements");
}
else
{
QVERIFY2(situations.size() == i + 1, "Element size does not match");
QVERIFY2(situations.front().getMSecsSinceEpoch() == cTs, "Wrong front element");
}
}
}
} //namespace

View File

@@ -1,9 +1,13 @@
/* Copyright (C) 2013 VATSIM Community / contributors /* Copyright (C) 2014
* This Source Code Form is subject to the terms of the Mozilla Public * swift project community / contributors
* License, v. 2.0. If a copy of the MPL was not distributed with this *
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
/*! \file */ //! \file
#ifndef BLACKMISCTEST_TESTCONTAINERS_H #ifndef BLACKMISCTEST_TESTCONTAINERS_H
#define BLACKMISCTEST_TESTCONTAINERS_H #define BLACKMISCTEST_TESTCONTAINERS_H
@@ -13,12 +17,14 @@
namespace BlackMiscTest namespace BlackMiscTest
{ {
//! Testing containers
class CTestContainers : public QObject class CTestContainers : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CTestContainers(QObject *parent = 0) : QObject(parent) {} //! Constructor
explicit CTestContainers(QObject *parent = nullptr) : QObject(parent) {}
private slots: private slots:
void collectionBasics(); void collectionBasics();
@@ -26,8 +32,9 @@ namespace BlackMiscTest
void joinAndSplit(); void joinAndSplit();
void findTests(); void findTests();
void dictionaryBasics(); void dictionaryBasics();
void timestampList();
}; };
} //namespace BlackMiscTest } // namespace
#endif // guard #endif // guard

View File

@@ -90,9 +90,9 @@ namespace BlackMiscTest
CPropertyIndexVariantMap vm; CPropertyIndexVariantMap vm;
CPropertyIndexVariantMap vmCopy(vmWildcard); CPropertyIndexVariantMap vmCopy(vmWildcard);
// remark: Shortcoming here, as the callsign will automatically set for user in station // Remark: Shortcoming here, as the callsign will be automatically set for user in station
// I have to set this as well, otherwise, not match. // I have to set this as well, otherwise, no match.
vm.addValue(CAtcStation::IndexController, CUser("123456", "Joe Doe", CCallsign("EDDMTWR"))); vm.addValue(CAtcStation::IndexController, CUser("123456", "Joe Doe", CCallsign("EDDM_TWR")));
// compare // compare