tests/auto/qlocationutils/tst_qlocationutils.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 //#include "../../../src/location/qlocationutils_p.h"
       
    42 #include "qlocationutils_p.h"
       
    43 #include "qgeopositioninfo.h"
       
    44 
       
    45 #include <QDebug>
       
    46 #include <QTest>
       
    47 #include <QObject>
       
    48 
       
    49 #include <math.h>
       
    50 
       
    51 QTM_USE_NAMESPACE
       
    52 Q_DECLARE_METATYPE(QGeoPositionInfo)
       
    53 Q_DECLARE_METATYPE(QGeoCoordinate)
       
    54 
       
    55 
       
    56 class tst_QLocationUtils : public QObject
       
    57 {
       
    58     Q_OBJECT
       
    59 private:
       
    60     QString addChecksumEtc(const QString &sentence)
       
    61     {
       
    62         Q_ASSERT(sentence[0] == '$' && sentence[sentence.length()-1] == '*');
       
    63 
       
    64         // XOR byte value of all characters between '$' and '*'
       
    65         int result = 0;
       
    66         for (int i=1; i<sentence.length()-1; i++)
       
    67             result ^= sentence[i].toAscii();
       
    68         QString sum;
       
    69         sum.sprintf("%02x", result);
       
    70         return sentence + sum + "\r\n";
       
    71     }
       
    72 
       
    73     double nmeaDegreesToDecimal(double nmeaDegrees)
       
    74     {
       
    75         double deg;
       
    76         double min = 100.0 * modf(nmeaDegrees / 100.0, &deg);
       
    77         return deg + (min / 60.0);
       
    78     }
       
    79 
       
    80 private slots:
       
    81 
       
    82     void getPosInfoFromNmea()
       
    83     {
       
    84         QFETCH(QString, nmea);
       
    85         QFETCH(QGeoPositionInfo, expectedInfo);
       
    86         QFETCH(bool, expectedHasFix);
       
    87         QFETCH(bool, expectedResult);
       
    88 
       
    89         QGeoPositionInfo info;
       
    90         bool hasFix;
       
    91         bool b = QLocationUtils::getPosInfoFromNmea(nmea.toAscii(), nmea.length(), &info, &hasFix);
       
    92         QCOMPARE(b, expectedResult);
       
    93         QCOMPARE(hasFix, expectedHasFix);
       
    94         QCOMPARE(info, expectedInfo);
       
    95     }
       
    96 
       
    97     void getPosInfoFromNmea_data()
       
    98     {
       
    99         QTest::addColumn<QString>("nmea");
       
   100         QTest::addColumn<QGeoPositionInfo>("expectedInfo");
       
   101         QTest::addColumn<bool>("expectedHasFix");
       
   102         QTest::addColumn<bool>("expectedResult");
       
   103 
       
   104         QTest::newRow("empty") << QString() << QGeoPositionInfo() << false << false;
       
   105 
       
   106         // must use exact double values or comparisons fail
       
   107         double lat = nmeaDegreesToDecimal(2734.7964); 
       
   108         double lng = nmeaDegreesToDecimal(15306.0124);
       
   109 
       
   110         QList<double> dblValues;
       
   111         dblValues << -1.534 << -1.0 << 0.0 << 0.12123 << 3.23 << 123124.11;
       
   112 
       
   113         QGeoPositionInfo info;
       
   114 
       
   115         // all types
       
   116         QList<QString> types;
       
   117         types << "$GPGGA*" << "$GPGLL*" << "$GPRMC*" << "$GPVTG*" << "$GPZDA*";
       
   118         for (int i=0; i<types.count(); i++) {
       
   119             // the sentence type is valid even if it is empty so the method still returns true
       
   120             QTest::newRow(qPrintable(types[i])) << addChecksumEtc(types[i])
       
   121                     << QGeoPositionInfo() << false << true;
       
   122         }
       
   123 
       
   124         // bad type
       
   125         QTest::newRow("unknown type") << addChecksumEtc("$GPZZZ*") << QGeoPositionInfo() << false << false;
       
   126 
       
   127         // --GGA:
       
   128 
       
   129         QTest::newRow("GGA-time") << addChecksumEtc("$GPGGA,060613.626,,,,,,,,,,,,,*")
       
   130                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(6, 6, 13, 626)))
       
   131                 << false << true;
       
   132 
       
   133         QTest::newRow("GGA-lat/long") << addChecksumEtc("$GPGGA,,2734.7964,S,15306.0124,E,,,,,,,,,*")
       
   134                 << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime())
       
   135                 << false << true;
       
   136 
       
   137         QTest::newRow("GGA-lat/long/alt") << addChecksumEtc("$GPGGA,,2734.7964,S,15306.0124,E,,,,26.8,,,,,*")
       
   138                 << QGeoPositionInfo(QGeoCoordinate(-lat, lng, 26.8), QDateTime())
       
   139                 << false << true;
       
   140     
       
   141         QTest::newRow("GGA alt but no lat/long") << addChecksumEtc("$GPGGA,,,,,,,,,26.8,,,,,*")
       
   142                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   143                 << false << true;
       
   144 
       
   145         for (int i=-1; i<10; i++) {
       
   146             bool hasFix = i > 0;
       
   147             QTest::newRow("GGA-fix") << addChecksumEtc(QString("$GPGGA,,,,,,%1,,,,,,,,*").arg(i))
       
   148                     << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   149                     << hasFix << true;
       
   150         }
       
   151 
       
   152         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*")
       
   153                 << QGeoPositionInfo(QGeoCoordinate(-lat, lng, -26.8), QDateTime(QDate(), QTime(6,6,13,626)))
       
   154                 << true << true;
       
   155 
       
   156 
       
   157         // --GLL:
       
   158 
       
   159         QTest::newRow("GLL-lat/long") << addChecksumEtc("$GPGLL,2734.7964,S,15306.0124,E,,,*")
       
   160                 << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime())
       
   161                 << false << true;
       
   162 
       
   163         QTest::newRow("GLL-time") << addChecksumEtc("$GPGLL,,,,,060613.626,,*")
       
   164                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(6, 6, 13, 626)))
       
   165                 << false << true;
       
   166 
       
   167         QTest::newRow("GLL-fix-ok") << addChecksumEtc("$GPGLL,,,,,,A,*")
       
   168                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   169                 << true << true;
       
   170 
       
   171         QTest::newRow("GLL-fix-bad") << addChecksumEtc("$GPGLL,,,,,,V,*")
       
   172                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   173                 << false << true;
       
   174 
       
   175         QTest::newRow("GLL-all") << addChecksumEtc("$GGGLL,2734.7964,S,15306.0124,E,220125.999,A,,*")
       
   176                 << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime(QDate(), QTime(22,1,25,999)))
       
   177                 << true << true;
       
   178 
       
   179                 
       
   180         // --RMC:
       
   181 
       
   182         QTest::newRow("RMC-time") << addChecksumEtc("$GPRMC,060613.626,,,,,,,,,,,*")
       
   183                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(6, 6, 13, 626)))
       
   184                 << false << true;
       
   185         
       
   186         QTest::newRow("RMC-fix-ok") << addChecksumEtc("$GPRMC,,A,,,,,,,,,,*")
       
   187                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   188                 << true << true;
       
   189 
       
   190         QTest::newRow("RMC-fix-bad") << addChecksumEtc("$GPRMC,,V,,,,,,,,,,*")
       
   191                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   192                 << false << true;
       
   193 
       
   194         QTest::newRow("RMC-lat/long") << addChecksumEtc("$GPRMC,,,2734.7964,S,15306.0124,E,,,,,*")
       
   195                 << QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime())
       
   196                 << false << true;
       
   197 
       
   198         for (int i=0; i<dblValues.count(); i++) {
       
   199             info = QGeoPositionInfo();
       
   200             info.setAttribute(QGeoPositionInfo::Direction, dblValues[i]);
       
   201             QTest::newRow(qPrintable(QString("RMC-heading %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPRMC,,,,,,,,%1,,,,*").arg(dblValues[i], 0, 'g', 10)) 
       
   202                     << info << false << true;
       
   203         }
       
   204 
       
   205         for (int i=0; i<dblValues.count(); i++) {
       
   206             info = QGeoPositionInfo();
       
   207             info.setAttribute(QGeoPositionInfo::GroundSpeed, dblValues[i] * 1.852 / 3.6);
       
   208             QTest::newRow(qPrintable(QString("RMC-speed %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPRMC,,,,,,,%1,,,,,*").arg(dblValues[i], 0, 'g', 10)) 
       
   209                     << info << false << true;
       
   210         }
       
   211 
       
   212         for (int i=0; i<dblValues.count(); i++) {
       
   213             info = QGeoPositionInfo();
       
   214             info.setAttribute(QGeoPositionInfo::MagneticVariation, dblValues[i]);
       
   215             char direction = dblValues[i] > 0 ? 'E' : 'W';
       
   216             QTest::newRow(qPrintable(QString("RMC-magVar %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPRMC,,,,,,,,,,%1,%2,*").arg(qAbs(dblValues[i]), 0, 'g', 10).arg(direction)) 
       
   217                     << info << false << true;
       
   218         }
       
   219 
       
   220         QTest::newRow("RMC-date") << addChecksumEtc("$GPRMC,,,,,,,,,010520,*")
       
   221                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2020,5,1), QTime(), Qt::UTC))
       
   222                 << false << true;
       
   223 
       
   224         QTest::newRow("RMC-date bad format") << addChecksumEtc("$GPRMC,,,,,,,,,10520,,*")
       
   225                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   226                 << false << true;
       
   227 
       
   228         info = QGeoPositionInfo(QGeoCoordinate(-lat, lng), QDateTime(QDate(2008,4,3), QTime(22,1,25,999), Qt::UTC));
       
   229         info.setAttribute(QGeoPositionInfo::GroundSpeed, 8.9 * 1.852 / 3.6);
       
   230         info.setAttribute(QGeoPositionInfo::Direction, 47.6);
       
   231         info.setAttribute(QGeoPositionInfo::MagneticVariation, -11.2);
       
   232         QTest::newRow("RMC-all") << addChecksumEtc("$GPRMC,220125.999,A,2734.7964,S,15306.0124,E,8.9,47.6,030408,11.2,W,A*")
       
   233                 << info
       
   234                 << true << true;
       
   235 
       
   236         // -- VTG:
       
   237 
       
   238         for (int i=0; i<dblValues.count(); i++) {
       
   239             info = QGeoPositionInfo();
       
   240             info.setAttribute(QGeoPositionInfo::Direction, dblValues[i]);
       
   241             QTest::newRow(qPrintable(QString("VTG-heading %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPVTG,%1,,,,,,,,*").arg(dblValues[i], 0, 'g', 10)) 
       
   242                     << info << false << true;
       
   243         }
       
   244 
       
   245         for (int i=0; i<dblValues.count(); i++) {
       
   246             info = QGeoPositionInfo();
       
   247             info.setAttribute(QGeoPositionInfo::GroundSpeed, dblValues[i] / 3.6);
       
   248             QTest::newRow(qPrintable(QString("VTG-speed %1").arg(dblValues[i]))) << addChecksumEtc(QString("$GPVTG,,,,,,,%1,,*").arg(dblValues[i], 0, 'g', 10)) 
       
   249                     << info << false << true;
       
   250         }
       
   251 
       
   252         info = QGeoPositionInfo();
       
   253         info.setAttribute(QGeoPositionInfo::Direction, 158.7);
       
   254         info.setAttribute(QGeoPositionInfo::GroundSpeed, 61.5 / 3.6);
       
   255         QTest::newRow("VTG-all") << addChecksumEtc("$GPVTG,158.7,T,169.9,M,33.2,N,61.5,K,A*")
       
   256                 << info
       
   257                 << false << true;
       
   258 
       
   259         // ZDA:
       
   260 
       
   261         QTest::newRow("ZDA-time") << addChecksumEtc("$GPZDA,152333.4,,,,*")
       
   262                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(), QTime(15,23,33, 4), Qt::UTC))
       
   263                 << false << true;
       
   264 
       
   265         QTest::newRow("ZDA-date day only") << addChecksumEtc("$GPZDA,,1,,,,*")
       
   266                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   267                 << false << true;
       
   268 
       
   269         QTest::newRow("ZDA-date month only") << addChecksumEtc("$GPZDA,,,12,,,*")
       
   270                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   271                 << false << true;
       
   272         
       
   273         QTest::newRow("ZDA-date bad year only") << addChecksumEtc("$GPZDA,,,,2005,,*")
       
   274                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime())
       
   275                 << false << true;
       
   276 
       
   277         QTest::newRow("ZDA-date") << addChecksumEtc("$GPZDA,,1,12,2005,,*")
       
   278                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2005,12,1), QTime(), Qt::UTC))
       
   279                 << false << true;
       
   280 
       
   281         QTest::newRow("ZDA-all") << addChecksumEtc("$GPZDA,052953.05,03,04,2008,00,00*")
       
   282                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2008, 4, 3), QTime(5, 29, 53, 5), Qt::UTC))
       
   283                 << false << true;
       
   284 
       
   285         // test if multiple sentences are passed in, only first is parsed
       
   286         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*"))
       
   287                 << QGeoPositionInfo(QGeoCoordinate(), QDateTime(QDate(2008, 4, 3), QTime(5, 29, 53, 5), Qt::UTC))
       
   288                 << false << true;
       
   289     }
       
   290 
       
   291     void hasValidNmeaChecksum() {
       
   292         QFETCH(QString, nmea);
       
   293         QFETCH(bool, expectedResult);
       
   294 
       
   295         QCOMPARE(QLocationUtils::hasValidNmeaChecksum(nmea.toAscii().constData(), nmea.length()), expectedResult);
       
   296     }
       
   297 
       
   298     void hasValidNmeaChecksum_data()
       
   299     {
       
   300         QTest::addColumn<QString>("nmea");
       
   301         QTest::addColumn<bool>("expectedResult");
       
   302 
       
   303         QTest::newRow("empty") << QString() << false;
       
   304 
       
   305         QString s = addChecksumEtc("$GPGGA,,,,,,,,,,,,,,*");
       
   306         QString trimmed = s.trimmed();
       
   307         QTest::newRow("ok") << s << true;
       
   308         QTest::newRow("too short") << trimmed.mid(0, trimmed.length()-1) << false;
       
   309         QTest::newRow("no asterisk") << s.replace("*", "") << false; // modifies test data!
       
   310     }
       
   311 #ifdef QT_BUILD_INTERNAL
       
   312     void getNmeaTime()
       
   313     {
       
   314         QFETCH(QString, str);
       
   315         QFETCH(QTime, expectedTime);
       
   316         QFETCH(bool, expectedResult);
       
   317 
       
   318         QTime time;
       
   319         bool b = QLocationUtils::getNmeaTime(str.toAscii(), &time);
       
   320         QCOMPARE(time, expectedTime);
       
   321         QCOMPARE(b, expectedResult);
       
   322     }
       
   323 
       
   324     void getNmeaTime_data()
       
   325     {
       
   326         QTest::addColumn<QString>("str");
       
   327         QTest::addColumn<QTime>("expectedTime");
       
   328         QTest::addColumn<bool>("expectedResult");
       
   329         
       
   330         QTest::newRow("empty") << QString() << QTime() << false;
       
   331         QTest::newRow("no numbers") << QString("asdl") << QTime() << false;
       
   332         QTest::newRow("one number short") << QString("11223") << QTime() << false;
       
   333 
       
   334         QTest::newRow("112233") << QString("112233") << QTime(11,22,33) << true;
       
   335         QTest::newRow("000000") << QString("000000") << QTime(0,0,0) << true;
       
   336         QTest::newRow("235959") << QString("235959") << QTime(23,59,59) << true;
       
   337         QTest::newRow("235960") << QString("235960") << QTime() << false;
       
   338         QTest::newRow("236059") << QString("236059") << QTime() << false;
       
   339         QTest::newRow("245959") << QString("24959") << QTime() << false;
       
   340 
       
   341         QTest::newRow("112233.0") << QString("112233.0") << QTime(11,22,33) << true;
       
   342         QTest::newRow("112233.1") << QString("112233.1") << QTime(11,22,33, 1) << true;
       
   343         QTest::newRow("112233.12") << QString("112233.12") << QTime(11,22,33, 12) << true;
       
   344         QTest::newRow("112233.123") << QString("112233.123") << QTime(11,22,33, 123) << true;
       
   345         QTest::newRow("112233.999") << QString("112233.999") << QTime(11,22,33, 999) << true;
       
   346         QTest::newRow("112233.9990") << QString("112233.9990") << QTime(11,22,33,999) << true;
       
   347         QTest::newRow("112233.9991") << QString("112233.9991") << QTime(11,22,33,999) << true;
       
   348     }
       
   349 
       
   350     void getNmeaLatLong()
       
   351     {
       
   352         QFETCH(QString, str);
       
   353         QFETCH(double, expectedLat);
       
   354         QFETCH(double, expectedLng);
       
   355         QFETCH(bool, expectedResult);
       
   356 
       
   357         double lat, lng;
       
   358         QList<QByteArray> parts = str.toAscii().split(',');
       
   359         bool b = QLocationUtils::getNmeaLatLong(parts[0], parts[1][0], parts[2], parts[3][0], &lat, &lng);
       
   360         QCOMPARE(b, expectedResult);
       
   361         if (b) {
       
   362             QCOMPARE(lat, expectedLat);
       
   363             QCOMPARE(lng, expectedLng);
       
   364         }
       
   365     }
       
   366 
       
   367     void getNmeaLatLong_data()
       
   368     {
       
   369         QTest::addColumn<QString>("str");
       
   370         QTest::addColumn<double>("expectedLat");
       
   371         QTest::addColumn<double>("expectedLng");
       
   372         QTest::addColumn<bool>("expectedResult");
       
   373 
       
   374         QTest::newRow("0.0,S,0.0,E") << "0.0,S,0.0,E" << 0.0 << 0.0 << true;
       
   375         QTest::newRow("0.0,S,0.0,E") << "0.0,S,0.0,E" << 0.0 << 0.0 << true;
       
   376         QTest::newRow("0,N,0,W") << "0,N,0,W" << 0.0 << 0.0 << true;
       
   377         QTest::newRow("0,N,0,W") << "0,N,0,W" << 0.0 << 0.0 << true;
       
   378 
       
   379         QTest::newRow("bad N/S indicator") << "0.0,Z,0.0,E" << 0.0 << 0.0 << false;
       
   380         QTest::newRow("bad E/W indicator") << "0.0,S,0.0,P" << 0.0 << 0.0 << false;
       
   381 
       
   382         QTest::newRow("lat too big") << "9000.0001,N,0.0,E" << 0.0 << 0.0 << false; 
       
   383         QTest::newRow("lat almost too big") << "9000.0000,N,0.0,E" << 90.0 << 0.0 << true; 
       
   384         QTest::newRow("lat too small") << "9000.0001,S,0.0,E" << 0.0 << 0.0 << false; 
       
   385         QTest::newRow("lat almost too small") << "9000.0000,S,0.0,E" << -90.0 << 0.0 << true; 
       
   386 
       
   387         QTest::newRow("long too big") << "0.0,N,18000.0001,E" << 0.0 << 0.0 << false; 
       
   388         QTest::newRow("long almost too big") << "0.0,N,18000.0000,E" << 0.0 << 180.0 << true; 
       
   389         QTest::newRow("long too small") << "0.0,N,18000.0001,W" << 0.0 << 0.0 << false; 
       
   390         QTest::newRow("long almost too small") << "0.0,N,18000.0000,W" << 0.0 << -180.0 << true; 
       
   391 
       
   392         double lat = nmeaDegreesToDecimal(2734.7964); 
       
   393         double lng = nmeaDegreesToDecimal(15306.0124);
       
   394 
       
   395         QTest::newRow("Lat N, Long E")
       
   396                 << "2734.7964,N,15306.0124,E" 
       
   397                 << lat << lng << true;
       
   398 
       
   399         QTest::newRow("Lat S, Long E")
       
   400                 << "2734.7964,S,15306.0124,E" 
       
   401                 << -lat << lng << true;
       
   402 
       
   403         QTest::newRow("Lat N, Long W")
       
   404                 << "2734.7964,N,15306.0124,W" 
       
   405                 << lat << -lng << true;
       
   406 
       
   407         QTest::newRow("Lat S, Long W")
       
   408                 << "2734.7964,S,15306.0124,W" 
       
   409                 << -lat << -lng << true;
       
   410     }
       
   411 #endif
       
   412 
       
   413 };
       
   414 
       
   415 
       
   416 QTEST_MAIN(tst_QLocationUtils)
       
   417 #include "tst_qlocationutils.moc"
       
   418