Commit 5fde6e71 authored by Don Gagne's avatar Don Gagne

Better/More survey related unit testing

parent b3fe4b6b
......@@ -400,6 +400,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/MissionManagerTest.h \
src/MissionManager/MissionSettingsTest.h \
src/MissionManager/PlanMasterControllerTest.h \
src/MissionManager/QGCMapPolygonTest.h \
src/MissionManager/SectionTest.h \
src/MissionManager/SimpleMissionItemTest.h \
src/MissionManager/SpeedSectionTest.h \
......@@ -434,6 +435,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/MissionManagerTest.cc \
src/MissionManager/MissionSettingsTest.cc \
src/MissionManager/PlanMasterControllerTest.cc \
src/MissionManager/QGCMapPolygonTest.cc \
src/MissionManager/SectionTest.cc \
src/MissionManager/SimpleMissionItemTest.cc \
src/MissionManager/SpeedSectionTest.cc \
......
......@@ -72,6 +72,9 @@ void QGCMapPolygon::setDirty(bool dirty)
{
if (_dirty != dirty) {
_dirty = dirty;
if (!dirty) {
_polygonModel.setDirty(false);
}
emit dirtyChanged(dirty);
}
}
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "QGCMapPolygonTest.h"
#include "QGCApplication.h"
#include "QGCQGeoCoordinate.h"
QGCMapPolygonTest::QGCMapPolygonTest(void)
{
_polyPoints << QGeoCoordinate(47.635638361473475, -122.09269407980834 ) <<
QGeoCoordinate(47.635638361473475, -122.08545246602667) <<
QGeoCoordinate(47.63057923872075, -122.08545246602667) <<
QGeoCoordinate(47.63057923872075, -122.09269407980834);
}
void QGCMapPolygonTest::init(void)
{
UnitTest::init();
_rgPolygonSignals[polygonCountChangedIndex] = SIGNAL(countChanged(int));
_rgPolygonSignals[pathChangedIndex] = SIGNAL(pathChanged());
_rgPolygonSignals[polygonDirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
_rgPolygonSignals[clearedIndex] = SIGNAL(cleared());
_rgPolygonSignals[centerChangedIndex] = SIGNAL(centerChanged(QGeoCoordinate));
_rgModelSignals[modelCountChangedIndex] = SIGNAL(countChanged(int));
_rgModelSignals[modelDirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
_mapPolygon = new QGCMapPolygon(this, this);
_pathModel = _mapPolygon->qmlPathModel();
QVERIFY(_pathModel);
_multiSpyPolygon = new MultiSignalSpy();
QCOMPARE(_multiSpyPolygon->init(_mapPolygon, _rgPolygonSignals, _cPolygonSignals), true);
_multiSpyModel = new MultiSignalSpy();
QCOMPARE(_multiSpyModel->init(_pathModel, _rgModelSignals, _cModelSignals), true);
}
void QGCMapPolygonTest::cleanup(void)
{
delete _mapPolygon;
delete _multiSpyPolygon;
delete _multiSpyModel;
}
void QGCMapPolygonTest::_testDirty(void)
{
// Check basic dirty bit set/get
QVERIFY(!_mapPolygon->dirty());
QVERIFY(!_pathModel->dirty());
_mapPolygon->setDirty(false);
QVERIFY(!_mapPolygon->dirty());
QVERIFY(!_pathModel->dirty());
QVERIFY(_multiSpyPolygon->checkNoSignals());
QVERIFY(_multiSpyModel->checkNoSignals());
_mapPolygon->setDirty(true);
QVERIFY(_mapPolygon->dirty());
QVERIFY(!_pathModel->dirty());
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(polygonDirtyChangedMask));
QVERIFY(_multiSpyPolygon->pullBoolFromSignalIndex(polygonDirtyChangedIndex));
QVERIFY(_multiSpyModel->checkNoSignals());
_multiSpyPolygon->clearAllSignals();
_mapPolygon->setDirty(false);
QVERIFY(!_mapPolygon->dirty());
QVERIFY(!_pathModel->dirty());
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(polygonDirtyChangedMask));
QVERIFY(!_multiSpyPolygon->pullBoolFromSignalIndex(polygonDirtyChangedIndex));
QVERIFY(_multiSpyModel->checkNoSignals());
_multiSpyPolygon->clearAllSignals();
_pathModel->setDirty(true);
QVERIFY(_pathModel->dirty());
QVERIFY(_mapPolygon->dirty());
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(polygonDirtyChangedMask));
QVERIFY(_multiSpyPolygon->pullBoolFromSignalIndex(polygonDirtyChangedIndex));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask));
QVERIFY(_multiSpyModel->pullBoolFromSignalIndex(modelDirtyChangedIndex));
_multiSpyPolygon->clearAllSignals();
_multiSpyModel->clearAllSignals();
_mapPolygon->setDirty(false);
QVERIFY(!_mapPolygon->dirty());
QVERIFY(!_pathModel->dirty());
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(polygonDirtyChangedMask));
QVERIFY(!_multiSpyPolygon->pullBoolFromSignalIndex(polygonDirtyChangedIndex));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask));
QVERIFY(!_multiSpyModel->pullBoolFromSignalIndex(modelDirtyChangedIndex));
_multiSpyPolygon->clearAllSignals();
_multiSpyModel->clearAllSignals();
}
void QGCMapPolygonTest::_testVertexManipulation(void)
{
#if 0
Q_INVOKABLE void clear(void);
Q_INVOKABLE void appendVertex(const QGeoCoordinate& coordinate);
Q_INVOKABLE void removeVertex(int vertexIndex);
/// Adjust the value for the specified coordinate
/// @param vertexIndex Polygon point index to modify (0-based)
/// @param coordinate New coordinate for point
Q_INVOKABLE void adjustVertex(int vertexIndex, const QGeoCoordinate coordinate);
/// Splits the segment comprised of vertextIndex -> vertexIndex + 1
Q_INVOKABLE void splitPolygonSegment(int vertexIndex);
#endif
// Vertex addition testing
for (int i=0; i<_polyPoints.count(); i++) {
QCOMPARE(_mapPolygon->count(), i);
_mapPolygon->appendVertex(_polyPoints[i]);
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask | modelCountChangedMask));
QCOMPARE(_multiSpyPolygon->pullIntFromSignalIndex(polygonCountChangedIndex), i+1);
QCOMPARE(_multiSpyModel->pullIntFromSignalIndex(modelCountChangedIndex), i+1);
QVERIFY(_mapPolygon->dirty());
QVERIFY(_pathModel->dirty());
QCOMPARE(_mapPolygon->count(), i+1);
QVariantList polyList = _mapPolygon->path();
QCOMPARE(polyList.count(), i+1);
QCOMPARE(polyList[i].value<QGeoCoordinate>(), _polyPoints[i]);
QCOMPARE(_pathModel->count(), i+1);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(i)->coordinate(), _polyPoints[i]);
_mapPolygon->setDirty(false);
_multiSpyPolygon->clearAllSignals();
_multiSpyModel->clearAllSignals();
}
// Vertex adjustment testing
QGCQGeoCoordinate* geoCoord = _pathModel->value<QGCQGeoCoordinate*>(1);
QSignalSpy coordSpy(geoCoord, SIGNAL(coordinateChanged(QGeoCoordinate)));
QSignalSpy coordDirtySpy(geoCoord, SIGNAL(dirtyChanged(bool)));
QGeoCoordinate adjustCoord(_polyPoints[1].latitude() + 1, _polyPoints[1].longitude() + 1);
_mapPolygon->adjustVertex(1, adjustCoord);
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(pathChangedMask | polygonDirtyChangedMask | centerChangedMask));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask));
QCOMPARE(coordSpy.count(), 1);
QCOMPARE(coordDirtySpy.count(), 1);
QCOMPARE(geoCoord->coordinate(), adjustCoord);
QVariantList polyList = _mapPolygon->path();
QCOMPARE(polyList[0].value<QGeoCoordinate>(), _polyPoints[0]);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(0)->coordinate(), _polyPoints[0]);
QCOMPARE(polyList[2].value<QGeoCoordinate>(), _polyPoints[2]);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(2)->coordinate(), _polyPoints[2]);
QCOMPARE(polyList[3].value<QGeoCoordinate>(), _polyPoints[3]);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(3)->coordinate(), _polyPoints[3]);
_mapPolygon->setDirty(false);
_multiSpyPolygon->clearAllSignals();
_multiSpyModel->clearAllSignals();
// Vertex removal testing
_mapPolygon->removeVertex(1);
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask | modelCountChangedMask));
QCOMPARE(_mapPolygon->count(), 3);
polyList = _mapPolygon->path();
QCOMPARE(polyList.count(), 3);
QCOMPARE(_pathModel->count(), 3);
QCOMPARE(polyList[0].value<QGeoCoordinate>(), _polyPoints[0]);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(0)->coordinate(), _polyPoints[0]);
QCOMPARE(polyList[1].value<QGeoCoordinate>(), _polyPoints[2]);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(1)->coordinate(), _polyPoints[2]);
QCOMPARE(polyList[2].value<QGeoCoordinate>(), _polyPoints[3]);
QCOMPARE(_pathModel->value<QGCQGeoCoordinate*>(2)->coordinate(), _polyPoints[3]);
// Clear testing
_mapPolygon->clear();
QVERIFY(_multiSpyPolygon->checkOnlySignalsByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask | clearedMask));
QVERIFY(_multiSpyModel->checkOnlySignalsByMask(modelDirtyChangedMask | modelCountChangedMask));
QVERIFY(_mapPolygon->dirty());
QVERIFY(_pathModel->dirty());
QCOMPARE(_mapPolygon->count(), 0);
polyList = _mapPolygon->path();
QCOMPARE(polyList.count(), 0);
QCOMPARE(_pathModel->count(), 0);
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "UnitTest.h"
#include "MultiSignalSpy.h"
#include "QGCMapPolygon.h"
#include "QmlObjectListModel.h"
/// Unit test for SurveyMissionItem
class QGCMapPolygonTest : public UnitTest
{
Q_OBJECT
public:
QGCMapPolygonTest(void);
protected:
void init(void) final;
void cleanup(void) final;
private slots:
void _testDirty(void);
void _testVertexManipulation(void);
private:
enum {
polygonCountChangedIndex = 0,
pathChangedIndex,
polygonDirtyChangedIndex,
clearedIndex,
centerChangedIndex,
maxPolygonSignalIndex
};
enum {
polygonCountChangedMask = 1 << polygonCountChangedIndex,
pathChangedMask = 1 << pathChangedIndex,
polygonDirtyChangedMask = 1 << polygonDirtyChangedIndex,
clearedMask = 1 << clearedIndex,
centerChangedMask = 1 << centerChangedIndex,
};
static const size_t _cPolygonSignals = maxPolygonSignalIndex;
const char* _rgPolygonSignals[_cPolygonSignals];
void countChanged(int count);
void dirtyChanged(bool dirtyChanged);
enum {
modelCountChangedIndex = 0,
modelDirtyChangedIndex,
maxModelSignalIndex
};
enum {
modelCountChangedMask = 1 << modelCountChangedIndex,
modelDirtyChangedMask = 1 << modelDirtyChangedIndex,
};
static const size_t _cModelSignals = maxModelSignalIndex;
const char* _rgModelSignals[_cModelSignals];
MultiSignalSpy* _multiSpyPolygon;
MultiSignalSpy* _multiSpyModel;
QGCMapPolygon* _mapPolygon;
QmlObjectListModel* _pathModel;
QList<QGeoCoordinate> _polyPoints;
};
......@@ -92,7 +92,7 @@ void SurveyMissionItemTest::_testDirty(void)
// These facts should not change dirty bit
rgFacts << _surveyItem->groundResolution() << _surveyItem->frontalOverlap() << _surveyItem->sideOverlap() << _surveyItem->cameraSensorWidth() << _surveyItem->cameraSensorHeight() <<
_surveyItem->cameraResolutionWidth() << _surveyItem->cameraResolutionHeight() << _surveyItem->cameraFocalLength() << _surveyItem->cameraOrientationLandscape() <<
_surveyItem->fixedValueIsAltitude() << _surveyItem->camera() << _surveyItem->manualGrid();
_surveyItem->fixedValueIsAltitude() << _surveyItem->camera() << _surveyItem->manualGrid();
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
QVERIFY(!_surveyItem->dirty());
......@@ -143,106 +143,9 @@ void SurveyMissionItemTest::_testCameraValueChanged(void)
rgFacts.clear();
}
#if 0
void SurveyMissionItemTest::_testAddPolygonCoordinate(void)
{
QCOMPARE(_mapPolygon->count(), 0);
// First call to addPolygonCoordinate should trigger:
// polygonPathChanged
// dirtyChanged
_mapPolygon->appendVertex(_polyPoints[0]);
QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | dirtyChangedMask));
// Validate object data
QVariantList polyList = _mapPolygon->path();
QCOMPARE(polyList.count(), 1);
QCOMPARE(polyList[0].value<QGeoCoordinate>(), _polyPoints[0]);
// Reset
_surveyItem->setDirty(false);
_multiSpy->clearAllSignals();
// Second call to addPolygonCoordinate should only trigger:
// polygonPathChanged
// dirtyChanged
_mapPolygon->appendVertex(_polyPoints[1]);
QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | dirtyChangedMask));
polyList = _mapPolygon->path();
QCOMPARE(polyList.count(), 2);
for (int i=0; i<polyList.count(); i++) {
QCOMPARE(polyList[i].value<QGeoCoordinate>(), _polyPoints[i]);
}
_surveyItem->setDirty(false);
_multiSpy->clearAllSignals();
// Third call to addPolygonCoordinate should trigger:
// polygonPathChanged
// dirtyChanged
// Grid is generated for the first time on closing of polygon which triggers:
// coordinateChanged - grid generates new entry coordinate
// exitCoordinateChanged - grid generates new exit coordinate
// specifiesCoordinateChanged - once grid entry/exit shows up specifiesCoordinate gets set to true
// Grid generation triggers the following signals
// lastSequenceNumberChanged - number of internal mission items changes
// gridPointsChanged - grid points show up for the first time
_mapPolygon->appendVertex(_polyPoints[2]);
QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | lastSequenceNumberChangedMask | gridPointsChangedMask | coordinateChangedMask |
exitCoordinateChangedMask | specifiesCoordinateChangedMask | dirtyChangedMask));
int seqNum = _multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex);
QVERIFY(seqNum > 0);
polyList = _mapPolygon->path();
QCOMPARE(polyList.count(), 3);
for (int i=0; i<polyList.count(); i++) {
QCOMPARE(polyList[i].value<QGeoCoordinate>(), _polyPoints[i]);
}
// Test that number of waypoints is doubled when using turnaround waypoints
_surveyItem->setTurnaroundDist(60.0);
QVariantList gridPoints = _surveyItem->gridPoints();
_surveyItem->setTurnaroundDist(0.0);
QVariantList gridPointsNoT = _surveyItem->gridPoints();
QCOMPARE(gridPoints.count(), 2 * gridPointsNoT.count());
}
void SurveyMissionItemTest::_testClearPolygon(void)
{
for (int i=0; i<3; i++) {
_mapPolygon->appendVertex(_polyPoints[i]);
}
_surveyItem->setDirty(false);
_multiSpy->clearAllSignals();
// Call to clearPolygon should trigger:
// polygonPathChangedMask
// dirtyChanged
// lastSequenceNumberChangedMask
// gridPointsChangedMask
// dirtyChangedMask
// specifiesCoordinateChangedMask
_mapPolygon->clear();
QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | lastSequenceNumberChangedMask | gridPointsChangedMask | dirtyChangedMask |
specifiesCoordinateChangedMask));
QVERIFY(!_multiSpy->pullBoolFromSignalIndex(specifiesCoordinateChangedIndex));
QCOMPARE(_multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex), 0);
QCOMPARE(_mapPolygon->path().count(), 0);
QCOMPARE(_surveyItem->gridPoints().count(), 0);
_surveyItem->setDirty(false);
_multiSpy->clearAllSignals();
}
void SurveyMissionItemTest::_testCameraTrigger(void)
{
#if 0
QCOMPARE(_surveyItem->property("cameraTrigger").toBool(), true);
// Set up a grid
......@@ -273,5 +176,5 @@ void SurveyMissionItemTest::_testCameraTrigger(void)
_surveyItem->setProperty("cameraTrigger", true);
QVERIFY(_multiSpy->checkOnlySignalByMask(lastSequenceNumberChangedMask | dirtyChangedMask | cameraTriggerChangedMask));
QCOMPARE(_multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex), lastSeq);
}
#endif
}
......@@ -33,11 +33,7 @@ protected:
private slots:
void _testDirty(void);
void _testCameraValueChanged(void);
#if 0
void _testAddPolygonCoordinate(void);
void _testClearPolygon(void);
void _testCameraTrigger(void);
#endif
private:
enum {
......
......@@ -12,8 +12,9 @@
#include <QQmlEngine>
QGCQGeoCoordinate::QGCQGeoCoordinate(const QGeoCoordinate& coord, QObject* parent)
: QObject(parent)
, _coordinate(coord)
: QObject (parent)
, _coordinate (coord)
, _dirty (false)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
......@@ -23,5 +24,14 @@ void QGCQGeoCoordinate::setCoordinate(const QGeoCoordinate& coordinate)
if (_coordinate != coordinate) {
_coordinate = coordinate;
emit coordinateChanged(coordinate);
setDirty(true);
}
}
void QGCQGeoCoordinate::setDirty(bool dirty)
{
if (_dirty != dirty) {
_dirty = dirty;
emit dirtyChanged(dirty);
}
}
......@@ -20,14 +20,19 @@ class QGCQGeoCoordinate : public QObject
public:
QGCQGeoCoordinate(const QGeoCoordinate& coord, QObject* parent = NULL);
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
QGeoCoordinate coordinate(void) const { return _coordinate; }
void setCoordinate(const QGeoCoordinate& coordinate);
QGeoCoordinate coordinate (void) const { return _coordinate; }
void setCoordinate (const QGeoCoordinate& coordinate);
bool dirty (void) const { return _dirty; }
void setDirty (bool dirty);
signals:
void coordinateChanged(QGeoCoordinate coordinate);
void coordinateChanged (QGeoCoordinate coordinate);
void dirtyChanged (bool dirty);
private:
QGeoCoordinate _coordinate;
QGeoCoordinate _coordinate;
bool _dirty;
};
......@@ -196,18 +196,18 @@ int QmlObjectListModel::count(void) const
void QmlObjectListModel::setDirty(bool dirty)
{
_dirty = dirty;
if (!dirty) {
// Need to clear dirty from all children
foreach(QObject* object, _objectList) {
if (object->property("dirty").isValid()) {
object->setProperty("dirty", false);
if (_dirty != dirty) {
_dirty = dirty;
if (!dirty) {
// Need to clear dirty from all children
foreach(QObject* object, _objectList) {
if (object->property("dirty").isValid()) {
object->setProperty("dirty", false);
}
}
}
emit dirtyChanged(_dirty);
}
emit dirtyChanged(_dirty);
}
void QmlObjectListModel::_childDirtyChanged(bool dirty)
......
......@@ -37,6 +37,7 @@
#include "SpeedSectionTest.h"
#include "PlanMasterControllerTest.h"
#include "MissionSettingsTest.h"
#include "QGCMapPolygonTest.h"
UT_REGISTER_TEST(FactSystemTestGeneric)
UT_REGISTER_TEST(FactSystemTestPX4)
......@@ -60,6 +61,7 @@ UT_REGISTER_TEST(CameraSectionTest)
UT_REGISTER_TEST(SpeedSectionTest)
UT_REGISTER_TEST(PlanMasterControllerTest)
UT_REGISTER_TEST(MissionSettingsTest)
UT_REGISTER_TEST(QGCMapPolygonTest)
// List of unit test which are currently disabled.
// If disabling a new test, include reason in comment.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment