1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
4 //
5 
6 
7 #include "GeoDataTreeModel.h"
8 #include "GeoDataAccuracy.h"
9 #include "PositionProviderPlugin.h"
10 #include "PositionTracking.h"
11 #include "TestUtils.h"
12 
13 #include <QSignalSpy>
14 
15 class FakeProvider : public Marble::PositionProviderPlugin
16 {
17 public:
FakeProvider()18     FakeProvider() :
19         m_status( Marble::PositionProviderStatusUnavailable ),
20         m_position(),
21         m_accuracy(),
22         m_speed( 0.0 ),
23         m_direction( 0.0 ),
24         m_timestamp()
25     {}
26 
name() const27     QString name() const override           { return "fake plugin"; }
guiString() const28     QString guiString() const override      { return "fake"; }
nameId() const29     QString nameId() const override         { return "fakeplugin"; }
version() const30     QString version() const override        { return "1.0"; }
description() const31     QString description() const override    { return "plugin for testing"; }
icon() const32     QIcon icon() const override             { return QIcon(); }
copyrightYears() const33     QString copyrightYears() const override { return "2012"; }
pluginAuthors() const34     QVector<Marble::PluginAuthor> pluginAuthors() const override { return QVector<Marble::PluginAuthor>(); }
initialize()35     void initialize() override {}
isInitialized() const36     bool isInitialized() const override     { return true; }
37 
status() const38     Marble::PositionProviderStatus status() const override { return m_status; }
position() const39     Marble::GeoDataCoordinates position() const override { return m_position; }
accuracy() const40     Marble::GeoDataAccuracy accuracy() const override { return m_accuracy; }
speed() const41     qreal speed() const override { return m_speed; }
direction() const42     qreal direction() const override { return m_direction; }
timestamp() const43     QDateTime timestamp() const override { return m_timestamp; }
44 
newInstance() const45     Marble::PositionProviderPlugin *newInstance() const override { return nullptr; }
46 
47     void setStatus( Marble::PositionProviderStatus status );
48     void setPosition( const Marble::GeoDataCoordinates &position,
49                       const Marble::GeoDataAccuracy &accuracy,
50                       qreal speed,
51                       qreal direction,
52                       const QDateTime &timestamp );
53 
54 private:
55     Marble::PositionProviderStatus m_status;
56     Marble::GeoDataCoordinates m_position;
57     Marble::GeoDataAccuracy m_accuracy;
58     qreal m_speed;
59     qreal m_direction;
60     QDateTime m_timestamp;
61 };
62 
setStatus(Marble::PositionProviderStatus status)63 void FakeProvider::setStatus( Marble::PositionProviderStatus status )
64 {
65     const Marble::PositionProviderStatus oldStatus = m_status;
66 
67     m_status = status;
68 
69     if ( oldStatus != m_status ) {
70         emit statusChanged( m_status );
71     }
72 }
73 
setPosition(const Marble::GeoDataCoordinates & position,const Marble::GeoDataAccuracy & accuracy,qreal speed,qreal direction,const QDateTime & timestamp)74 void FakeProvider::setPosition( const Marble::GeoDataCoordinates &position,
75                                 const Marble::GeoDataAccuracy &accuracy,
76                                 qreal speed,
77                                 qreal direction,
78                                 const QDateTime &timestamp )
79 {
80     m_position = position;
81     m_accuracy = accuracy;
82     m_speed = speed;
83     m_direction = direction;
84     m_timestamp = timestamp;
85 
86     emit positionChanged( m_position, m_accuracy );
87 }
88 
89 namespace Marble
90 {
91 
92 class PositionTrackingTest : public QObject
93 {
94     Q_OBJECT
95 
96  public:
97     PositionTrackingTest();
98 
99  private Q_SLOTS:
100     void construct();
101 
102     void statusChanged_data();
103     void statusChanged();
104 
105     void setPositionProviderPlugin();
106 
107     void clearTrack();
108 };
109 
PositionTrackingTest()110 PositionTrackingTest::PositionTrackingTest()
111 {
112     qRegisterMetaType<GeoDataCoordinates>( "GeoDataCoordinates" );
113     qRegisterMetaType<PositionProviderStatus>( "PositionProviderStatus" );
114 }
115 
construct()116 void PositionTrackingTest::construct()
117 {
118     GeoDataTreeModel treeModel;
119     const PositionTracking tracking( &treeModel );
120 
121     QCOMPARE( const_cast<PositionTracking &>( tracking ).positionProviderPlugin(), static_cast<PositionProviderPlugin *>( nullptr ) );
122     QCOMPARE( tracking.speed(), qreal( 0 ) );
123     QCOMPARE( tracking.direction(), qreal( 0 ) );
124     QCOMPARE( tracking.timestamp(), QDateTime() );
125     QCOMPARE( tracking.accuracy(), GeoDataAccuracy() );
126     QCOMPARE( tracking.trackVisible(), true );
127     QCOMPARE( tracking.currentLocation(), GeoDataCoordinates() );
128     QCOMPARE( tracking.status(), PositionProviderStatusUnavailable );
129     QCOMPARE( tracking.isTrackEmpty(), true );
130 
131     QCOMPARE( treeModel.rowCount(), 1 );
132     const QModelIndex indexPositionTracking = treeModel.index( 0, 0 );
133     QCOMPARE( treeModel.data( indexPositionTracking, Qt::DisplayRole ).toString(), QString( "Position Tracking" ) );
134     QCOMPARE( treeModel.rowCount( indexPositionTracking ), 2 );
135     const QModelIndex indexCurrentPosition = treeModel.index( 0, 0, indexPositionTracking );
136     QCOMPARE( treeModel.data( indexCurrentPosition, Qt::DisplayRole ).toString(), QString( "Current Position" ) );
137     const QModelIndex indexCurrentTrack = treeModel.index( 1, 0, indexPositionTracking );
138     QCOMPARE( treeModel.data( indexCurrentTrack, Qt::DisplayRole ).toString(), QString( "Current Track" ) );
139 }
140 
statusChanged_data()141 void PositionTrackingTest::statusChanged_data()
142 {
143     QTest::addColumn<PositionProviderStatus>( "finalStatus" );
144 
145     addRow() << PositionProviderStatusError;
146     addRow() << PositionProviderStatusUnavailable;
147     addRow() << PositionProviderStatusAcquiring;
148     addRow() << PositionProviderStatusAvailable;
149 }
150 
statusChanged()151 void PositionTrackingTest::statusChanged()
152 {
153     QFETCH( PositionProviderStatus, finalStatus );
154     const int expectedStatusChangedCount = ( finalStatus == PositionProviderStatusUnavailable ) ? 0 : 1;
155 
156     GeoDataTreeModel treeModel;
157     PositionTracking tracking( &treeModel );
158 
159     QSignalSpy statusChangedSpy( &tracking, SIGNAL(statusChanged(PositionProviderStatus)) );
160 
161     FakeProvider provider;
162     provider.setStatus( finalStatus );
163 
164     tracking.setPositionProviderPlugin( &provider );
165 
166     QCOMPARE( tracking.status(), finalStatus );
167     QCOMPARE( statusChangedSpy.count(), expectedStatusChangedCount );
168 }
169 
setPositionProviderPlugin()170 void PositionTrackingTest::setPositionProviderPlugin()
171 {
172     const GeoDataCoordinates coordinates( 1.2, 0.9 );
173     const GeoDataAccuracy accuracy( GeoDataAccuracy::Detailed, 10.0, 22.0 );
174     const qreal speed = 32.8;
175     const qreal direction = 49.7;
176     const QDateTime timestamp( QDate( 1, 3, 1994 ) );
177 
178     GeoDataTreeModel treeModel;
179     PositionTracking tracking( &treeModel );
180 
181     QSignalSpy gpsLocationSpy( &tracking, SIGNAL(gpsLocation(GeoDataCoordinates,qreal)) );
182 
183     QPointer<FakeProvider> provider( new FakeProvider );
184     provider->setStatus( PositionProviderStatusAvailable );
185     provider->setPosition( coordinates, accuracy, speed, direction, timestamp );
186 
187     tracking.setPositionProviderPlugin( provider );
188 
189     QCOMPARE( tracking.currentLocation(), coordinates );
190     QCOMPARE( tracking.accuracy(), accuracy );
191     QCOMPARE( tracking.speed(), speed );
192     QCOMPARE( tracking.direction(), direction );
193     QCOMPARE( tracking.timestamp(), timestamp );
194     QCOMPARE( gpsLocationSpy.count(), 1 );
195 
196     tracking.setPositionProviderPlugin( nullptr );
197 
198     QVERIFY( provider.isNull() );
199 }
200 
clearTrack()201 void PositionTrackingTest::clearTrack()
202 {
203     const GeoDataCoordinates position( 2.1, 0.8 );
204     const GeoDataAccuracy accuracy( GeoDataAccuracy::Detailed, 10.0, 22.0 );
205     const qreal speed = 32.8;
206     const qreal direction = 49.7;
207     const QDateTime timestamp( QDate( 1, 3, 1994 ) );
208 
209     GeoDataTreeModel treeModel;
210     PositionTracking tracking( &treeModel );
211 
212     FakeProvider provider;
213     tracking.setPositionProviderPlugin( &provider );
214 
215     tracking.clearTrack();
216 
217     QVERIFY( tracking.isTrackEmpty() );
218 
219     provider.setStatus( PositionProviderStatusAvailable );
220 
221     provider.setPosition( position, accuracy, speed, direction, timestamp );
222 
223     QVERIFY( !tracking.isTrackEmpty() );
224 
225     tracking.clearTrack();
226 
227     QVERIFY( tracking.isTrackEmpty() );
228 }
229 
230 }
231 
232 QTEST_MAIN( Marble::PositionTrackingTest )
233 
234 #include "PositionTrackingTest.moc"
235