--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/qlocationutils/tst_qlocationutils.cpp Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,418 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//#include "../../../src/location/qlocationutils_p.h"
+#include "qlocationutils_p.h"
+#include "qgeopositioninfo.h"
+
+#include <QDebug>
+#include <QTest>
+#include <QObject>
+
+#include <math.h>
+
+QTM_USE_NAMESPACE
+Q_DECLARE_METATYPE(QGeoPositionInfo)
+Q_DECLARE_METATYPE(QGeoCoordinate)
+
+
+class tst_QLocationUtils : public QObject
+{
+ Q_OBJECT
+private:
+ QString addChecksumEtc(const QString &sentence)
+ {
+ Q_ASSERT(sentence[0] == '$' && sentence[sentence.length()-1] == '*');
+
+ // XOR byte value of all characters between '$' and '*'
+ int result = 0;
+ for (int i=1; i<sentence.length()-1; i++)
+ result ^= sentence[i].toAscii();
+ QString sum;
+ sum.sprintf("%02x", result);
+ return sentence + sum + "\r\n";
+ }
+
+ double nmeaDegreesToDecimal(double nmeaDegrees)
+ {
+ double deg;
+ double min = 100.0 * modf(nmeaDegrees / 100.0, °);
+ return deg + (min / 60.0);
+ }
+
+private slots:
+
+ void getPosInfoFromNmea()
+ {
+ QFETCH(QString, nmea);
+ QFETCH(QGeoPositionInfo, expectedInfo);
+ QFETCH(bool, expectedHasFix);
+ QFETCH(bool, expectedResult);
+
+ QGeoPositionInfo info;
+ bool hasFix;
+ bool b = QLocationUtils::getPosInfoFromNmea(nmea.toAscii(), nmea.length(), &info, &hasFix);
+ QCOMPARE(b, expectedResult);
+ QCOMPARE(hasFix, expectedHasFix);
+ QCOMPARE(info, expectedInfo);
+ }
+
+ void getPosInfoFromNmea_data()
+ {
+ QTest::addColumn<QString>("nmea");
+ QTest::addColumn<QGeoPositionInfo>("expectedInfo");
+ QTest::addColumn<bool>("expectedHasFix");
+ QTest::addColumn<bool>("expectedResult");
+
+ QTest::newRow("empty") << QString() << QGeoPositionInfo() << false << false;
+
+ // must use exact double values or comparisons fail
+ double lat = nmeaDegreesToDecimal(2734.7964);
+ double lng = nmeaDegreesToDecimal(15306.0124);
+
+ QList<double> dblValues;
+ dblValues << -1.534 << -1.0 << 0.0 << 0.12123 << 3.23 << 123124.11;
+
+ QGeoPositionInfo info;
+
+ // all types
+ QList<QString> types;
+ types << "$GPGGA*" << "$GPGLL*" << "$GPRMC*" << "$GPVTG*" << "$GPZDA*";
+ for (int i=0; i<types.count(); i++) {
+ // the sentence type is valid even if it is empty so the method still returns true
+ QTest::newRow(qPrintable(types[i])) << addChecksumEtc(types[i])
+ << QGeoPositionInfo() << false << true;
+ }
+
+ // bad type
+ QTest::newRow("unknown type") << addChecksumEtc("$GPZZZ*") << QGeoPositionInfo() << false << false;
+
+ // --GGA:
+
+ QTest::newRow("GGA-time") << addChecksumEtc("$GPGGA,060613.626,,,,,,,,,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(6, 6, 13, 626)))
+ << false << true;
+
+ QTest::newRow("GGA-lat/long") << addChecksumEtc("$GPGGA,,2734.7964,S,15306.0124,E,,,,,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime())
+ << false << true;
+
+ QTest::newRow("GGA-lat/long/alt") << addChecksumEtc("$GPGGA,,2734.7964,S,15306.0124,E,,,,26.8,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(-lat, lng, 26.8), QDateTime())
+ << false << true;
+
+ QTest::newRow("GGA alt but no lat/long") << addChecksumEtc("$GPGGA,,,,,,,,,26.8,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ for (int i=-1; i<10; i++) {
+ bool hasFix = i > 0;
+ QTest::newRow("GGA-fix") << addChecksumEtc(QString("$GPGGA,,,,,,%1,,,,,,,,*").arg(i))
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << hasFix << true;
+ }
+
+ QTest::newRow("GGA-all") << addChecksumEtc("$GPGGA,060613.626,2734.7964,S,15306.0124,E,1,03,2.9,-26.8,M,36.8,M,1,0000*")
+ << QGeoPositionInfo(QGeoCoordinate(-lat, lng, -26.8), QDateTime(QDate(), QTime(6,6,13,626)))
+ << true << true;
+
+
+ // --GLL:
+
+ QTest::newRow("GLL-lat/long") << addChecksumEtc("$GPGLL,2734.7964,S,15306.0124,E,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime())
+ << false << true;
+
+ QTest::newRow("GLL-time") << addChecksumEtc("$GPGLL,,,,,060613.626,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(6, 6, 13, 626)))
+ << false << true;
+
+ QTest::newRow("GLL-fix-ok") << addChecksumEtc("$GPGLL,,,,,,A,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << true << true;
+
+ QTest::newRow("GLL-fix-bad") << addChecksumEtc("$GPGLL,,,,,,V,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ QTest::newRow("GLL-all") << addChecksumEtc("$GGGLL,2734.7964,S,15306.0124,E,220125.999,A,,*")
+ << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime(QDate(), QTime(22,1,25,999)))
+ << true << true;
+
+
+ // --RMC:
+
+ QTest::newRow("RMC-time") << addChecksumEtc("$GPRMC,060613.626,,,,,,,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(6, 6, 13, 626)))
+ << false << true;
+
+ QTest::newRow("RMC-fix-ok") << addChecksumEtc("$GPRMC,,A,,,,,,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << true << true;
+
+ QTest::newRow("RMC-fix-bad") << addChecksumEtc("$GPRMC,,V,,,,,,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ QTest::newRow("RMC-lat/long") << addChecksumEtc("$GPRMC,,,2734.7964,S,15306.0124,E,,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime())
+ << false << true;
+
+ for (int i=0; i<dblValues.count(); i++) {
+ info = QGeoPositionInfo();
+ info.setAttribute(QGeoPositionInfo::Direction, dblValues[i]);
+ QTest::newRow(qPrintable(QString("RMC-heading %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPRMC,,,,,,,,%1,,,,*").arg(dblValues[i], 0, 'g', 10))
+ << info << false << true;
+ }
+
+ for (int i=0; i<dblValues.count(); i++) {
+ info = QGeoPositionInfo();
+ info.setAttribute(QGeoPositionInfo::GroundSpeed, dblValues[i] * 1.852 / 3.6);
+ QTest::newRow(qPrintable(QString("RMC-speed %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPRMC,,,,,,,%1,,,,,*").arg(dblValues[i], 0, 'g', 10))
+ << info << false << true;
+ }
+
+ for (int i=0; i<dblValues.count(); i++) {
+ info = QGeoPositionInfo();
+ info.setAttribute(QGeoPositionInfo::MagneticVariation, dblValues[i]);
+ char direction = dblValues[i] > 0 ? 'E' : 'W';
+ QTest::newRow(qPrintable(QString("RMC-magVar %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPRMC,,,,,,,,,,%1,%2,*").arg(qAbs(dblValues[i]), 0, 'g', 10).arg(direction))
+ << info << false << true;
+ }
+
+ QTest::newRow("RMC-date") << addChecksumEtc("$GPRMC,,,,,,,,,010520,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2020,5,1), QTime(), Qt::UTC))
+ << false << true;
+
+ QTest::newRow("RMC-date bad format") << addChecksumEtc("$GPRMC,,,,,,,,,10520,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ info = QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime(QDate(2008,4,3), QTime(22,1,25,999), Qt::UTC));
+ info.setAttribute(QGeoPositionInfo::GroundSpeed, 8.9 * 1.852 / 3.6);
+ info.setAttribute(QGeoPositionInfo::Direction, 47.6);
+ info.setAttribute(QGeoPositionInfo::MagneticVariation, -11.2);
+ QTest::newRow("RMC-all") << addChecksumEtc("$GPRMC,220125.999,A,2734.7964,S,15306.0124,E,8.9,47.6,030408,11.2,W,A*")
+ << info
+ << true << true;
+
+ // -- VTG:
+
+ for (int i=0; i<dblValues.count(); i++) {
+ info = QGeoPositionInfo();
+ info.setAttribute(QGeoPositionInfo::Direction, dblValues[i]);
+ QTest::newRow(qPrintable(QString("VTG-heading %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPVTG,%1,,,,,,,,*").arg(dblValues[i], 0, 'g', 10))
+ << info << false << true;
+ }
+
+ for (int i=0; i<dblValues.count(); i++) {
+ info = QGeoPositionInfo();
+ info.setAttribute(QGeoPositionInfo::GroundSpeed, dblValues[i] / 3.6);
+ QTest::newRow(qPrintable(QString("VTG-speed %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPVTG,,,,,,,%1,,*").arg(dblValues[i], 0, 'g', 10))
+ << info << false << true;
+ }
+
+ info = QGeoPositionInfo();
+ info.setAttribute(QGeoPositionInfo::Direction, 158.7);
+ info.setAttribute(QGeoPositionInfo::GroundSpeed, 61.5 / 3.6);
+ QTest::newRow("VTG-all") << addChecksumEtc("$GPVTG,158.7,T,169.9,M,33.2,N,61.5,K,A*")
+ << info
+ << false << true;
+
+ // ZDA:
+
+ QTest::newRow("ZDA-time") << addChecksumEtc("$GPZDA,152333.4,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(15,23,33, 4), Qt::UTC))
+ << false << true;
+
+ QTest::newRow("ZDA-date day only") << addChecksumEtc("$GPZDA,,1,,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ QTest::newRow("ZDA-date month only") << addChecksumEtc("$GPZDA,,,12,,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ QTest::newRow("ZDA-date bad year only") << addChecksumEtc("$GPZDA,,,,2005,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
+ << false << true;
+
+ QTest::newRow("ZDA-date") << addChecksumEtc("$GPZDA,,1,12,2005,,*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2005,12,1), QTime(), Qt::UTC))
+ << false << true;
+
+ QTest::newRow("ZDA-all") << addChecksumEtc("$GPZDA,052953.05,03,04,2008,00,00*")
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2008, 4, 3), QTime(5, 29, 53, 5), Qt::UTC))
+ << false << true;
+
+ // test if multiple sentences are passed in, only first is parsed
+ QTest::newRow("multiple") << (addChecksumEtc("$GPZDA,052953.05,03,04,2008,00,00*") + addChecksumEtc("$GPVTG,158.7,T,169.9,M,33.2,N,61.5,K,A*"))
+ << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2008, 4, 3), QTime(5, 29, 53, 5), Qt::UTC))
+ << false << true;
+ }
+
+ void hasValidNmeaChecksum() {
+ QFETCH(QString, nmea);
+ QFETCH(bool, expectedResult);
+
+ QCOMPARE(QLocationUtils::hasValidNmeaChecksum(nmea.toAscii().constData(), nmea.length()), expectedResult);
+ }
+
+ void hasValidNmeaChecksum_data()
+ {
+ QTest::addColumn<QString>("nmea");
+ QTest::addColumn<bool>("expectedResult");
+
+ QTest::newRow("empty") << QString() << false;
+
+ QString s = addChecksumEtc("$GPGGA,,,,,,,,,,,,,,*");
+ QString trimmed = s.trimmed();
+ QTest::newRow("ok") << s << true;
+ QTest::newRow("too short") << trimmed.mid(0, trimmed.length()-1) << false;
+ QTest::newRow("no asterisk") << s.replace("*", "") << false; // modifies test data!
+ }
+#ifdef QT_BUILD_INTERNAL
+ void getNmeaTime()
+ {
+ QFETCH(QString, str);
+ QFETCH(QTime, expectedTime);
+ QFETCH(bool, expectedResult);
+
+ QTime time;
+ bool b = QLocationUtils::getNmeaTime(str.toAscii(), &time);
+ QCOMPARE(time, expectedTime);
+ QCOMPARE(b, expectedResult);
+ }
+
+ void getNmeaTime_data()
+ {
+ QTest::addColumn<QString>("str");
+ QTest::addColumn<QTime>("expectedTime");
+ QTest::addColumn<bool>("expectedResult");
+
+ QTest::newRow("empty") << QString() << QTime() << false;
+ QTest::newRow("no numbers") << QString("asdl") << QTime() << false;
+ QTest::newRow("one number short") << QString("11223") << QTime() << false;
+
+ QTest::newRow("112233") << QString("112233") << QTime(11,22,33) << true;
+ QTest::newRow("000000") << QString("000000") << QTime(0,0,0) << true;
+ QTest::newRow("235959") << QString("235959") << QTime(23,59,59) << true;
+ QTest::newRow("235960") << QString("235960") << QTime() << false;
+ QTest::newRow("236059") << QString("236059") << QTime() << false;
+ QTest::newRow("245959") << QString("24959") << QTime() << false;
+
+ QTest::newRow("112233.0") << QString("112233.0") << QTime(11,22,33) << true;
+ QTest::newRow("112233.1") << QString("112233.1") << QTime(11,22,33, 1) << true;
+ QTest::newRow("112233.12") << QString("112233.12") << QTime(11,22,33, 12) << true;
+ QTest::newRow("112233.123") << QString("112233.123") << QTime(11,22,33, 123) << true;
+ QTest::newRow("112233.999") << QString("112233.999") << QTime(11,22,33, 999) << true;
+ QTest::newRow("112233.9990") << QString("112233.9990") << QTime(11,22,33,999) << true;
+ QTest::newRow("112233.9991") << QString("112233.9991") << QTime(11,22,33,999) << true;
+ }
+
+ void getNmeaLatLong()
+ {
+ QFETCH(QString, str);
+ QFETCH(double, expectedLat);
+ QFETCH(double, expectedLng);
+ QFETCH(bool, expectedResult);
+
+ double lat, lng;
+ QList<QByteArray> parts = str.toAscii().split(',');
+ bool b = QLocationUtils::getNmeaLatLong(parts[0], parts[1][0], parts[2], parts[3][0], &lat, &lng);
+ QCOMPARE(b, expectedResult);
+ if (b) {
+ QCOMPARE(lat, expectedLat);
+ QCOMPARE(lng, expectedLng);
+ }
+ }
+
+ void getNmeaLatLong_data()
+ {
+ QTest::addColumn<QString>("str");
+ QTest::addColumn<double>("expectedLat");
+ QTest::addColumn<double>("expectedLng");
+ QTest::addColumn<bool>("expectedResult");
+
+ QTest::newRow("0.0,S,0.0,E") << "0.0,S,0.0,E" << 0.0 << 0.0 << true;
+ QTest::newRow("0.0,S,0.0,E") << "0.0,S,0.0,E" << 0.0 << 0.0 << true;
+ QTest::newRow("0,N,0,W") << "0,N,0,W" << 0.0 << 0.0 << true;
+ QTest::newRow("0,N,0,W") << "0,N,0,W" << 0.0 << 0.0 << true;
+
+ QTest::newRow("bad N/S indicator") << "0.0,Z,0.0,E" << 0.0 << 0.0 << false;
+ QTest::newRow("bad E/W indicator") << "0.0,S,0.0,P" << 0.0 << 0.0 << false;
+
+ QTest::newRow("lat too big") << "9000.0001,N,0.0,E" << 0.0 << 0.0 << false;
+ QTest::newRow("lat almost too big") << "9000.0000,N,0.0,E" << 90.0 << 0.0 << true;
+ QTest::newRow("lat too small") << "9000.0001,S,0.0,E" << 0.0 << 0.0 << false;
+ QTest::newRow("lat almost too small") << "9000.0000,S,0.0,E" << -90.0 << 0.0 << true;
+
+ QTest::newRow("long too big") << "0.0,N,18000.0001,E" << 0.0 << 0.0 << false;
+ QTest::newRow("long almost too big") << "0.0,N,18000.0000,E" << 0.0 << 180.0 << true;
+ QTest::newRow("long too small") << "0.0,N,18000.0001,W" << 0.0 << 0.0 << false;
+ QTest::newRow("long almost too small") << "0.0,N,18000.0000,W" << 0.0 << -180.0 << true;
+
+ double lat = nmeaDegreesToDecimal(2734.7964);
+ double lng = nmeaDegreesToDecimal(15306.0124);
+
+ QTest::newRow("Lat N, Long E")
+ << "2734.7964,N,15306.0124,E"
+ << lat << lng << true;
+
+ QTest::newRow("Lat S, Long E")
+ << "2734.7964,S,15306.0124,E"
+ << -lat << lng << true;
+
+ QTest::newRow("Lat N, Long W")
+ << "2734.7964,N,15306.0124,W"
+ << lat << -lng << true;
+
+ QTest::newRow("Lat S, Long W")
+ << "2734.7964,S,15306.0124,W"
+ << -lat << -lng << true;
+ }
+#endif
+
+};
+
+
+QTEST_MAIN(tst_QLocationUtils)
+#include "tst_qlocationutils.moc"
+