1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 //TESTED_COMPONENT=src/location
30 
31 #include <QtPositioning/qgeopositioninfo.h>
32 
33 #include <QMetaType>
34 #include <QObject>
35 #include <QDebug>
36 #include <QTest>
37 #include <QtCore/QtNumeric>
38 
39 #include <float.h>
40 
41 QT_USE_NAMESPACE
42 
43 Q_DECLARE_METATYPE(QGeoPositionInfo::Attribute)
44 
45 QByteArray tst_qgeopositioninfo_debug;
46 
tst_qgeopositioninfo_messageHandler(QtMsgType type,const QMessageLogContext &,const QString & msg)47 void tst_qgeopositioninfo_messageHandler(QtMsgType type, const QMessageLogContext&, const QString &msg)
48 {
49     switch (type) {
50         case QtDebugMsg :
51             tst_qgeopositioninfo_debug = msg.toLocal8Bit();
52             break;
53         default:
54             break;
55     }
56 }
57 
tst_qgeopositioninfo_qrealTestValues()58 QList<qreal> tst_qgeopositioninfo_qrealTestValues()
59 {
60     QList<qreal> values;
61 
62     if (qreal(DBL_MIN) == DBL_MIN)
63         values << DBL_MIN;
64 
65     values << FLT_MIN;
66     values << -1.0 << 0.0 << 1.0;
67     values << FLT_MAX;
68 
69     if (qreal(DBL_MAX) == DBL_MAX)
70         values << DBL_MAX;
71 
72     return values;
73 }
74 
tst_qgeopositioninfo_getAttributes()75 QList<QGeoPositionInfo::Attribute> tst_qgeopositioninfo_getAttributes()
76 {
77     QList<QGeoPositionInfo::Attribute> attributes;
78     attributes << QGeoPositionInfo::Direction
79             << QGeoPositionInfo::GroundSpeed
80             << QGeoPositionInfo::VerticalSpeed
81             << QGeoPositionInfo::MagneticVariation
82             << QGeoPositionInfo::HorizontalAccuracy
83             << QGeoPositionInfo::VerticalAccuracy;
84     return attributes;
85 }
86 
87 
88 class tst_QGeoPositionInfo : public QObject
89 {
90     Q_OBJECT
91 
92 private:
infoWithAttribute(QGeoPositionInfo::Attribute attribute,qreal value)93     QGeoPositionInfo infoWithAttribute(QGeoPositionInfo::Attribute attribute, qreal value)
94     {
95         QGeoPositionInfo info;
96         info.setAttribute(attribute, value);
97         return info;
98     }
99 
addTestData_info()100     void addTestData_info()
101     {
102         QTest::addColumn<QGeoPositionInfo>("info");
103 
104         QTest::newRow("invalid") << QGeoPositionInfo();
105 
106         QTest::newRow("coord") << QGeoPositionInfo(QGeoCoordinate(-27.3422,150.2342), QDateTime());
107         QTest::newRow("datetime") << QGeoPositionInfo(QGeoCoordinate(), QDateTime::currentDateTime());
108 
109         QList<QGeoPositionInfo::Attribute> attributes = tst_qgeopositioninfo_getAttributes();
110         QList<qreal> values = tst_qgeopositioninfo_qrealTestValues();
111         for (int i=0; i<attributes.count(); i++) {
112             for (int j=0; j<values.count(); j++) {
113                 QTest::newRow(qPrintable(QString("Attribute %1 = %2").arg(attributes[i]).arg(values[j])))
114                         << infoWithAttribute(attributes[i], values[j]);
115             }
116         }
117     }
118 
119 private slots:
constructor()120     void constructor()
121     {
122         QGeoPositionInfo info;
123         QVERIFY(!info.isValid());
124         QVERIFY(!info.coordinate().isValid());
125         QVERIFY(info.timestamp().isNull());
126     }
127 
constructor_coord_dateTime()128     void constructor_coord_dateTime()
129     {
130         QFETCH(QGeoCoordinate, coord);
131         QFETCH(QDateTime, dateTime);
132         QFETCH(bool, valid);
133 
134         QGeoPositionInfo info(coord, dateTime);
135         QCOMPARE(info.coordinate(), coord);
136         QCOMPARE(info.timestamp(), dateTime);
137         QCOMPARE(info.isValid(), valid);
138     }
139 
constructor_coord_dateTime_data()140     void constructor_coord_dateTime_data()
141     {
142         QTest::addColumn<QGeoCoordinate>("coord");
143         QTest::addColumn<QDateTime>("dateTime");
144         QTest::addColumn<bool>("valid");
145 
146         QTest::newRow("both null") << QGeoCoordinate() << QDateTime() << false;
147         QTest::newRow("both valid") << QGeoCoordinate(1,1) << QDateTime::currentDateTime() << true;
148         QTest::newRow("valid coord") << QGeoCoordinate(1,1) << QDateTime() << false;
149         QTest::newRow("valid datetime") << QGeoCoordinate() << QDateTime::currentDateTime() << false;
150         QTest::newRow("valid time but not date == invalid")
151                 << QGeoCoordinate() << QDateTime(QDate(), QTime::currentTime()) << false;
152         QTest::newRow("valid date but not time == valid due to QDateTime constructor")
153                 << QGeoCoordinate() << QDateTime(QDate::currentDate(), QTime()) << false;
154     }
155 
constructor_copy()156     void constructor_copy()
157     {
158         QFETCH(QGeoPositionInfo, info);
159 
160         QCOMPARE(QGeoPositionInfo(info), info);
161     }
162 
constructor_copy_data()163     void constructor_copy_data()
164     {
165         addTestData_info();
166     }
167 
operator_assign()168     void operator_assign()
169     {
170         QFETCH(QGeoPositionInfo, info);
171 
172         QGeoPositionInfo info2 = info;
173         QCOMPARE(info2, info);
174     }
175 
operator_assign_data()176     void operator_assign_data()
177     {
178         addTestData_info();
179     }
180 
operator_equals()181     void operator_equals()
182     {
183         QFETCH(QGeoPositionInfo, info);
184 
185         QVERIFY(info == info);
186         if (info.isValid())
187             QCOMPARE(info == QGeoPositionInfo(), false);
188     }
189 
operator_equals_data()190     void operator_equals_data()
191     {
192         addTestData_info();
193     }
194 
operator_notEquals()195     void operator_notEquals()
196     {
197         QFETCH(QGeoPositionInfo, info);
198 
199         QCOMPARE(info != info, false);
200         if (info.isValid())
201             QCOMPARE(info != QGeoPositionInfo(), true);
202     }
203 
operator_notEquals_data()204     void operator_notEquals_data()
205     {
206         addTestData_info();
207     }
208 
setDateTime()209     void setDateTime()
210     {
211         QFETCH(QDateTime, dateTime);
212 
213         QGeoPositionInfo info;
214         info.setTimestamp(dateTime);
215         QCOMPARE(info.timestamp(), dateTime);
216     }
217 
setDateTime_data()218     void setDateTime_data()
219     {
220         QTest::addColumn<QDateTime>("dateTime");
221         QTest::newRow("invalid") << QDateTime();
222         QTest::newRow("now") << QDateTime::currentDateTime();
223     }
224 
dateTime()225     void dateTime()
226     {
227         QGeoPositionInfo info;
228         QVERIFY(info.timestamp().isNull());
229     }
230 
setCoordinate()231     void setCoordinate()
232     {
233 
234         QFETCH(QGeoCoordinate, coord);
235 
236         QGeoPositionInfo info;
237         info.setCoordinate(coord);
238         QCOMPARE(info.coordinate(), coord);
239     }
240 
setCoordinate_data()241     void setCoordinate_data()
242     {
243         QTest::addColumn<QGeoCoordinate>("coord");
244 
245         QTest::newRow("invalid") << QGeoCoordinate();
246         QTest::newRow("valid") << QGeoCoordinate(30,30);
247     }
248 
attribute()249     void attribute()
250     {
251         QFETCH(QGeoPositionInfo::Attribute, attribute);
252         QFETCH(qreal, value);
253 
254         QGeoPositionInfo info;
255         QVERIFY(qIsNaN(info.attribute(attribute)));
256 
257         info.setAttribute(attribute, value);
258         QCOMPARE(info.attribute(attribute), value);
259 
260         info.removeAttribute(attribute);
261         QVERIFY(qIsNaN(info.attribute(attribute)));
262     }
263 
attribute_data()264     void attribute_data()
265     {
266         QTest::addColumn<QGeoPositionInfo::Attribute>("attribute");
267         QTest::addColumn<qreal>("value");
268 
269         QList<QGeoPositionInfo::Attribute> attributes = tst_qgeopositioninfo_getAttributes();
270         QList<qreal> values = tst_qgeopositioninfo_qrealTestValues();
271         for (int i=0; i<attributes.count(); i++) {
272             for (int j=0; j<values.count(); j++) {
273                 QTest::newRow(qPrintable(QString("Attribute %1 = %2").arg(attributes[i]).arg(values[j])))
274                         << attributes[i] << values[j];
275             }
276         }
277     }
278 
hasAttribute()279     void hasAttribute()
280     {
281         QFETCH(QGeoPositionInfo::Attribute, attribute);
282         QFETCH(qreal, value);
283 
284         QGeoPositionInfo info;
285         QVERIFY(!info.hasAttribute(attribute));
286 
287         info.setAttribute(attribute, value);
288         QVERIFY(info.hasAttribute(attribute));
289 
290         info.removeAttribute(attribute);
291         QVERIFY(!info.hasAttribute(attribute));
292     }
293 
hasAttribute_data()294     void hasAttribute_data()
295     {
296         attribute_data();
297     }
298 
removeAttribute()299     void removeAttribute()
300     {
301         QFETCH(QGeoPositionInfo::Attribute, attribute);
302         QFETCH(qreal, value);
303 
304         QGeoPositionInfo info;
305         QVERIFY(!info.hasAttribute(attribute));
306 
307         info.setAttribute(attribute, value);
308         QVERIFY(info.hasAttribute(attribute));
309 
310         info.removeAttribute(attribute);
311         QVERIFY(!info.hasAttribute(attribute));
312 
313         info.setAttribute(attribute, value);
314         QVERIFY(info.hasAttribute(attribute));
315     }
316 
removeAttribute_data()317     void removeAttribute_data()
318     {
319         attribute_data();
320     }
321 
datastream()322     void datastream()
323     {
324         QFETCH(QGeoPositionInfo, info);
325 
326         QByteArray ba;
327         QDataStream out(&ba, QIODevice::WriteOnly);
328         out << info;
329 
330         QDataStream in(&ba, QIODevice::ReadOnly);
331         QGeoPositionInfo inInfo;
332         in >> inInfo;
333         QCOMPARE(inInfo, info);
334     }
335 
datastream_data()336     void datastream_data()
337     {
338         addTestData_info();
339     }
340 
debug()341     void debug()
342     {
343         QFETCH(QGeoPositionInfo, info);
344         QFETCH(int, nextValue);
345         QFETCH(QByteArray, debugStringEnd);
346 
347         qInstallMessageHandler(tst_qgeopositioninfo_messageHandler);
348         qDebug() << info << nextValue;
349         qInstallMessageHandler(0);
350 
351         // use endsWith() so we don't depend on QDateTime's debug() implementation
352         QVERIFY2(tst_qgeopositioninfo_debug.endsWith(debugStringEnd),
353                  qPrintable(QString::fromLatin1("'%1' does not end with '%2'").
354                             arg(QLatin1String(tst_qgeopositioninfo_debug),
355                                 QLatin1String(debugStringEnd))));
356     }
357 
debug_data()358     void debug_data()
359     {
360         QTest::addColumn<QGeoPositionInfo>("info");
361         QTest::addColumn<int>("nextValue");
362         QTest::addColumn<QByteArray>("debugStringEnd");
363 
364         QTest::newRow("no values") << QGeoPositionInfo() << 40
365                 << QString("QGeoCoordinate(?, ?)) 40").toLatin1();
366 
367         QGeoCoordinate coord(1, 1);
368         QTest::newRow("coord, time") << QGeoPositionInfo(coord, QDateTime::currentDateTime())
369                 << 40 << QByteArray("QGeoCoordinate(1, 1)) 40");
370 
371         QGeoPositionInfo info;
372         info.setAttribute(QGeoPositionInfo::Direction, 1.1);
373         info.setAttribute(QGeoPositionInfo::GroundSpeed, 2.1);
374         info.setAttribute(QGeoPositionInfo::VerticalSpeed, 3.1);
375         info.setAttribute(QGeoPositionInfo::MagneticVariation, 4.1);
376         info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, 5.1);
377         info.setAttribute(QGeoPositionInfo::VerticalAccuracy, 6.1);
378         QTest::newRow("all attributes") << info << 40
379                 << QByteArray("QGeoCoordinate(?, ?), Direction=1.1, GroundSpeed=2.1, VerticalSpeed=3.1, MagneticVariation=4.1, HorizontalAccuracy=5.1, VerticalAccuracy=6.1) 40");
380     }
381 };
382 
383 
384 QTEST_APPLESS_MAIN(tst_QGeoPositionInfo)
385 #include "tst_qgeopositioninfo.moc"
386