diff --git a/src/blackmisc/dbusutils.cpp b/src/blackmisc/dbusutils.cpp index c369af754..7d3c1beaf 100644 --- a/src/blackmisc/dbusutils.cpp +++ b/src/blackmisc/dbusutils.cpp @@ -75,6 +75,7 @@ namespace BlackMisc const CAirportIcaoCode airportIcao; const CLivery livery; const CAirport airport; + const CAircraftSituation situation; const CSimulatedAircraft aircraft; const CSimulatedAircraftList aircraftList; const CVariant var; @@ -89,6 +90,8 @@ namespace BlackMisc out << "CAirportIcaoCode" << " size: " << s.size() << " sig: " << s << endl; s = CDBusUtils::dBusSignature(livery); out << "CLivery" << " size: " << s.size() << " sig: " << s << endl; + s = CDBusUtils::dBusSignature(situation); + out << "CAircraftSituation" << " size: " << s.size() << " sig: " << s << endl; s = CDBusUtils::dBusSignature(country); out << "CCountry" << " size: " << s.size() << " sig: " << s << endl; s = CDBusUtils::dBusSignature(airport); diff --git a/src/blackmisc/dbusutils.h b/src/blackmisc/dbusutils.h index 6fb3509fc..548649818 100644 --- a/src/blackmisc/dbusutils.h +++ b/src/blackmisc/dbusutils.h @@ -34,6 +34,13 @@ namespace BlackMisc return arg.currentSignature(); } + //! Signature size for BlackMisc::CValueObject + template + static int dBusSignatureSize(const ValueObj &obj) + { + return dBusSignature(obj).size(); + } + //! Type as string static QString dbusTypeAsString(QDBusArgument::ElementType type); diff --git a/tests/blackcore/testblackcoremain.h b/tests/blackcore/testblackcoremain.h index e5e39e2e3..7659be8f1 100644 --- a/tests/blackcore/testblackcoremain.h +++ b/tests/blackcore/testblackcoremain.h @@ -30,7 +30,7 @@ namespace BlackCoreTest //! Unit tests static int unitMain(int argc, char *argv[]); }; -} +} // ns //! \endcond diff --git a/tests/blackcore/testcontext.cpp b/tests/blackcore/testcontext.cpp index 1e90a2028..4a88280d4 100644 --- a/tests/blackcore/testcontext.cpp +++ b/tests/blackcore/testcontext.cpp @@ -16,8 +16,13 @@ #include "testcontext.h" #include "blackcore/context/contextallproxies.h" +#include "blackmisc/simulation/simulatedaircraftlist.h" +#include "blackmisc/dbusutils.h" #include +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Simulation; using namespace BlackCore::Context; namespace BlackCoreTest @@ -37,6 +42,27 @@ namespace BlackCoreTest CContextOwnAircraftProxy::unitTestRelaySignals(); CContextSimulatorProxy::unitTestRelaySignals(); } -} + + void CTestContext::dBusSignatures() + { + const CAircraftModel model; + const CAircraftSituation situation; + const CSimulatedAircraft aircraft; + const CSimulatedAircraftList aircraftList; + + constexpr int MaxSize = 210; + int s = CDBusUtils::dBusSignatureSize(model); + QVERIFY2(s < MaxSize, "CAircraftModel"); + + s = CDBusUtils::dBusSignatureSize(situation); + QVERIFY2(s < MaxSize, "CAircraftSituation"); + + s = CDBusUtils::dBusSignatureSize(aircraft); + QVERIFY2(s < MaxSize, "CSimulatedAircraft"); + + s = CDBusUtils::dBusSignatureSize(aircraftList); + QVERIFY2(s < MaxSize, "CSimulatedAircraftList"); + } +} // ns //! \endcond diff --git a/tests/blackcore/testcontext.h b/tests/blackcore/testcontext.h index f46762e9c..411106b2f 100644 --- a/tests/blackcore/testcontext.h +++ b/tests/blackcore/testcontext.h @@ -34,6 +34,9 @@ namespace BlackCoreTest private slots: //! Init tests for context void contextInitTest(); + + //! Test the DBus signatures + void dBusSignatures(); }; } //namespace diff --git a/tests/blackmisc/testaircraftsituation.cpp b/tests/blackmisc/testaircraftsituation.cpp new file mode 100644 index 000000000..9ecad17fb --- /dev/null +++ b/tests/blackmisc/testaircraftsituation.cpp @@ -0,0 +1,179 @@ +/* Copyright (C) 2018 + * 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. + */ + +//! \cond PRIVATE_TESTS + +/*! + * \file + * \ingroup testblackmisc + */ + +#include "testaircraftsituation.h" +#include "blackmisc/aviation/aircraftsituationchange.h" +#include "blackmisc/math/mathutils.h" +#include "blackcore/vatsim/networkvatlib.h" + +#include +#include + +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Math; +using namespace BlackCore::Vatsim; + +namespace BlackMiscTest +{ + CTestAircraftSituation::CTestAircraftSituation(QObject *parent): QObject(parent) + { + // void + } + + void CTestAircraftSituation::allGndFlagsAndTakeOff() const + { + CAircraftSituationList situations = testSituations(); + situations.setOnGround(CAircraftSituation::OnGround); + const CAircraftSituationChange change(situations); + QVERIFY2(change.isConstOnGround(), "Expect const on ground"); + QVERIFY(!change.isConstNotOnGround()); + QVERIFY(!change.isJustTakingOff()); + QVERIFY(!change.isJustTouchingDown()); + QVERIFY(change.wasConstOnGround()); + QVERIFY(!change.wasConstNotOnGround()); + QVERIFY(situations.isSortedAdjustedLatestFirstWithoutNullPositions()); + + CAircraftSituation f = situations.front(); + f.setOnGround(false); + situations.pop_front(); + situations.push_front(f); + const CAircraftSituationChange change2(situations); + QVERIFY2(change2.isJustTakingOff(), "Expect just take off"); + QVERIFY(!change2.isJustTouchingDown()); + QVERIFY(change.wasConstOnGround()); + QVERIFY(!change.wasConstNotOnGround()); + } + + void CTestAircraftSituation::allNotGndFlagsAndTouchdown() const + { + CAircraftSituationList situations = testSetDescendingAltitudes(testSituations()); + situations.setOnGround(CAircraftSituation::NotOnGround); + const CAircraftSituationChange change(situations); + QVERIFY2(change.isConstNotOnGround(), "Expect const not on ground"); + QVERIFY(!change.isConstOnGround()); + QVERIFY(!change.isJustTakingOff()); + QVERIFY(!change.isJustTouchingDown()); + QVERIFY(!change.wasConstOnGround()); + QVERIFY(change.wasConstNotOnGround()); + QVERIFY(situations.isSortedAdjustedLatestFirstWithoutNullPositions()); + + CAircraftSituation f = situations.front(); + f.setOnGround(true); + situations.pop_front(); + situations.push_front(f); + const CAircraftSituationChange change2(situations); + QVERIFY2(change2.isJustTouchingDown(), "Expect just touchdown"); + QVERIFY(!change2.isJustTakingOff()); + QVERIFY(!change.wasConstOnGround()); + QVERIFY(change.wasConstNotOnGround()); + } + + void CTestAircraftSituation::ascending() + { + const CAircraftSituationList situations = testSituations(); + QVERIFY2(situations.isConstAscending(), "Expect ascending"); + } + + void CTestAircraftSituation::descending() + { + const CAircraftSituationList situations = testSetDescendingAltitudes(testSituations()); + QVERIFY2(situations.isConstDescending(), "Expect descending"); + } + + void CTestAircraftSituation::rotateUp() + { + CAircraftSituationList situations = testSetRotateUpPitch(testSituations()); + const CAircraftSituationChange change(situations); + QVERIFY2(!change.isRotatingUp(), "Do not expect rotate up"); + + CAircraftSituation f = situations.front(); + situations.pop_front(); + f.setPitch(CAngle(7.3, CAngleUnit::deg())); + situations.push_front(f); + + const CAircraftSituationChange change2(situations); + QVERIFY2(change2.isRotatingUp(), "Expect rotate up"); + } + + void CTestAircraftSituation::sortOrder() const + { + CAircraftSituationList situations = testSituations(); + QVERIFY2(situations.isSortedAdjustedLatestFirstWithoutNullPositions(), "Expect latest first"); + QVERIFY(!situations.isSortedLatestLast()); + + situations.reverse(); + QVERIFY2(situations.isSortedAdjustedLatestLast(), "Expect latest first"); + QVERIFY(!situations.isSortedAdjustedLatestFirst()); + } + + CAircraftSituationList CTestAircraftSituation::testSituations() + { + // "Kugaaruk Airport","Pelly Bay","Canada","YBB","CYBB",68.534401,-89.808098,56,-7,"A","America/Edmonton","airport","OurAirports" + // "Baie Comeau Airport","Baie Comeau","Canada","YBC","CYBC",49.13249969482422,-68.20439910888672,71,-5,"A","America/Toronto","airport","OurAirports" + // "CFB Bagotville","Bagotville","Canada","YBG","CYBG",48.33060073852539,-70.99639892578125,522,-5,"A","America/Toronto","airport","OurAirports" + + CAircraftSituationList situations; + qint64 ts = QDateTime::currentSecsSinceEpoch(); + qint64 os = CFsdSetup::c_positionTimeOffsetMsec; + CAltitude alt(10000, CAltitude::MeanSeaLevel, CLengthUnit::m()); + static const CCoordinateGeodetic dummyPos(48.33060073852539, -70.99639892578125, 522); + + for (int i = 0; i < 10; i++) + { + CAircraftSituation s(dummyPos); + const qint64 cTs = ts - i * os; + s.setMSecsSinceEpoch(cTs); + s.setTimeOffsetMs(os); + CAltitude altitude(alt); + altitude.addValueSameUnit(-100 * i); // 10000, 9900, 9800 .... (newer->older) + s.setAltitude(altitude); + situations.push_back(s); + } + return situations; + } + + CAircraftSituationList CTestAircraftSituation::testSetDescendingAltitudes(const CAircraftSituationList &situations) + { + CAircraftSituationList newSituations; + CAltitude alt(0, CAltitude::MeanSeaLevel, CLengthUnit::m()); + + for (const CAircraftSituation &situation : situations) + { + CAircraftSituation s(situation); + s.setAltitude(alt); + newSituations.push_back(s); + alt.addValueSameUnit(100); // 0, 100, 200 ... (newer->older) + } + return newSituations; + } + + CAircraftSituationList CTestAircraftSituation::testSetRotateUpPitch(const CAircraftSituationList &situations) + { + CAircraftSituationList newSituations; + for (const CAircraftSituation &situation : situations) + { + CAircraftSituation s(situation); + const double pitch = CMathUtils::randomDouble(1.5); + s.setPitch(CAngle(pitch, CAngleUnit::deg())); + newSituations.push_back(s); + } + return newSituations; + } +} // namespace + +//! \endcond diff --git a/tests/blackmisc/testaircraftsituation.h b/tests/blackmisc/testaircraftsituation.h new file mode 100644 index 000000000..f07aed191 --- /dev/null +++ b/tests/blackmisc/testaircraftsituation.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2018 + * 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. + */ + +#ifndef BLACKMISCTEST_TESTAIRCRAFTSITUATION_H +#define BLACKMISCTEST_TESTAIRCRAFTSITUATION_H + +//! \cond PRIVATE_TESTS + +/*! + * \file + * \ingroup testblackmisc + */ + +#include "blackmisc/aviation/aircraftsituationlist.h" +#include + +namespace BlackMiscTest +{ + /*! + * CAircraftSituation and CAircraftSituationChange tests + */ + class CTestAircraftSituation : public QObject + { + Q_OBJECT + + public: + //! Standard test case constructor + explicit CTestAircraftSituation(QObject *parent = nullptr); + + private slots: + //! All GND flags + void allGndFlagsAndTakeOff() const; + + //! All not GND flags + void allNotGndFlagsAndTouchdown() const; + + //! Ascending aircraft + void ascending(); + + //! Descending aircraft + void descending(); + + //! Rotating up aircraft + void rotateUp(); + + //! Test sort order + void sortOrder() const; + + private: + //! Test situations (ascending) + static BlackMisc::Aviation::CAircraftSituationList testSituations(); + + //! Set descending altitudes + static BlackMisc::Aviation::CAircraftSituationList testSetDescendingAltitudes(const BlackMisc::Aviation::CAircraftSituationList &situations); + + //! Set descending altitudes + static BlackMisc::Aviation::CAircraftSituationList testSetRotateUpPitch(const BlackMisc::Aviation::CAircraftSituationList &situations); + }; +} // namespace + +//! \endcond + +#endif // guard diff --git a/tests/blackmisc/testaviation.cpp b/tests/blackmisc/testaviation.cpp index f798b603a..34a0ded04 100644 --- a/tests/blackmisc/testaviation.cpp +++ b/tests/blackmisc/testaviation.cpp @@ -201,6 +201,25 @@ namespace BlackMiscTest QCOMPARE(qRound(altitude2.value(CLengthUnit::m())), 510); } + void CTestAviation::testGuessing() + { + const CAircraftIcaoCode icao172("C172", "L1P"); + const CAircraftIcaoCode icaoB737("B737", "L2J"); + const CAircraftIcaoCode icaoB747("B747", "L4J"); + + CSpeed s172, sB737, sB747; s172 = sB737 = sB747 = CSpeed::null(); + CLength cg172, cgB737, cgB747; cg172 = cgB737 = cgB747 = CLength::null(); + icao172.guessModelParameters(cg172, s172); + icaoB737.guessModelParameters(cgB737, sB737); + icaoB747.guessModelParameters(cgB747, sB747); + + QVERIFY(cg172 < cgB737); + QVERIFY(cgB737 < cgB747); + + QVERIFY(s172 < sB747); + QVERIFY(sB737 < sB747); + } + } // namespace //! \endcond diff --git a/tests/blackmisc/testaviation.h b/tests/blackmisc/testaviation.h index 2e9351517..a425e0cc8 100644 --- a/tests/blackmisc/testaviation.h +++ b/tests/blackmisc/testaviation.h @@ -50,6 +50,9 @@ namespace BlackMiscTest //! CAltitude tests void altitude(); + + //! Test some of the guessing functions + void testGuessing(); }; } // namespace diff --git a/tests/blackmisc/testblackmiscmain.cpp b/tests/blackmisc/testblackmiscmain.cpp index 2a9ebbdb1..1fae88029 100644 --- a/tests/blackmisc/testblackmiscmain.cpp +++ b/tests/blackmisc/testblackmiscmain.cpp @@ -14,6 +14,7 @@ #include "testaviation.h" #include "testcompress.h" #include "testblackmiscmain.h" +#include "testaircraftsituation.h" #include "testcontainers.h" #include "testdbus.h" #include "testflightplan.h" @@ -69,6 +70,10 @@ namespace BlackMiscTest CTestAircraftParts apTests; status |= test.exec(&apTests, "blackmisc_aircraftParts"); } + { + CTestAircraftSituation sitTests; + status |= test.exec(&sitTests, "blackmisc_aircraftSituation"); + } { CTestGeo geoTests; status |= test.exec(&geoTests, "blackmisc_geo"); diff --git a/tests/blackmisc/testcontainers.cpp b/tests/blackmisc/testcontainers.cpp index d0f1b2f08..4f67bb719 100644 --- a/tests/blackmisc/testcontainers.cpp +++ b/tests/blackmisc/testcontainers.cpp @@ -43,9 +43,16 @@ using namespace BlackMisc; using namespace BlackMisc::Aviation; +using namespace BlackMisc::Geo; +using namespace BlackMisc::PhysicalQuantities; namespace BlackMiscTest { + void CTestContainers::initTestCase() + { + BlackMisc::registerMetadata(); + } + void CTestContainers::collectionBasics() { CCollection c1; @@ -132,7 +139,6 @@ namespace BlackMiscTest void CTestContainers::findTests() { - BlackMisc::registerMetadata(); CCallsignSet callsigns; CSequence found = callsigns.findBy(&CCallsign::asString, "Foo"); QVERIFY2(found.isEmpty(), "Empty found"); @@ -227,7 +233,7 @@ namespace BlackMiscTest { CAircraftSituationList situations; const qint64 ts = QDateTime::currentMSecsSinceEpoch(); - const int no = 10; + int no = 10; for (int i = 0; i < no; ++i) { CAircraftSituation s; @@ -266,20 +272,46 @@ namespace BlackMiscTest QVERIFY2(situations.front().getMSecsSinceEpoch() == cTs, "Wrong front element"); } } + + situations.sortLatestFirst(); + QVERIFY2(situations.isSortedLatestFirst(), "Espect sorted latest first"); + no = situations.size(); + for (int i = 0; i < no; ++i) + { + const CAircraftSituation current = situations[i]; + const qint64 cTs = current.getMSecsSinceEpoch(); + const CAircraftSituation expectedBefore = situations.findObjectBeforeOrDefault(cTs); + const CAircraftSituation expectedAfter = situations.findObjectAfterOrDefault(cTs); + const qint64 beforeTs = expectedBefore.getMSecsSinceEpoch(); + const qint64 afterTs = expectedAfter.getMSecsSinceEpoch(); + + if (i > 0) + { + const qint64 t1 = situations[i - 1].getMSecsSinceEpoch(); + QVERIFY2(t1 == afterTs, "Wrong expected after"); + } + if (i < (no - 1)) + { + const qint64 t1 = situations[i + 1].getMSecsSinceEpoch(); + QVERIFY2(t1 == beforeTs, "Wrong expected before"); + } + } } void CTestContainers::offsetTimestampList() { qsrand(QDateTime::currentDateTime().toTime_t()); CAircraftSituationList situations; + static const CCoordinateGeodetic geoPos = CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", { 1487, CLengthUnit::ft() }); qint64 ts = 1000000; - const int no = 10; + int no = 10; const int max = 6; int dt = 0; for (int i = 0; i < no; ++i) { CAircraftSituation s; + s.setPosition(geoPos); s.setMSecsSinceEpoch(ts); s.setCallsign("CS" + QString::number(i)); @@ -300,10 +332,32 @@ namespace BlackMiscTest situations.push_frontKeepLatestFirstAdjustOffset(s, max); QVERIFY2(situations.size() <= max, "Wrong size"); - QVERIFY2(situations.isSortedAdjustedLatestFirst(), "Wrong sort order"); + QVERIFY2(situations.isSortedAdjustedLatestFirstWithoutNullPositions(), "Wrong sort order"); QVERIFY2(!situations.hasInvalidTimestamps(), "Missing timestamps"); QVERIFY2(!situations.containsZeroOrNegativeOffsetTime(), "Missing offset time"); } + + no = situations.size(); + for (int i = 0; i < no; ++i) + { + const CAircraftSituation current = situations[i]; + const qint64 cTs = current.getAdjustedMSecsSinceEpoch(); + const CAircraftSituation expectedBefore = situations.findObjectBeforeAdjustedOrDefault(cTs); + const CAircraftSituation expectedAfter = situations.findObjectAfterAdjustedOrDefault(cTs); + const qint64 beforeTs = expectedBefore.getAdjustedMSecsSinceEpoch(); + const qint64 afterTs = expectedAfter.getAdjustedMSecsSinceEpoch(); + + if (i > 0) + { + const qint64 t1 = situations[i - 1].getAdjustedMSecsSinceEpoch(); + QVERIFY2(t1 == afterTs, "Wrong expected after"); + } + if (i < (no - 1)) + { + const qint64 t1 = situations[i + 1].getAdjustedMSecsSinceEpoch(); + QVERIFY2(t1 == beforeTs, "Wrong expected before"); + } + } } } //namespace diff --git a/tests/blackmisc/testcontainers.h b/tests/blackmisc/testcontainers.h index d55a82123..87efe63c6 100644 --- a/tests/blackmisc/testcontainers.h +++ b/tests/blackmisc/testcontainers.h @@ -28,6 +28,8 @@ namespace BlackMiscTest explicit CTestContainers(QObject *parent = nullptr) : QObject(parent) {} private slots: + void initTestCase(); + void collectionBasics(); void sequenceBasics(); void joinAndSplit();