Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include <QMetaType>
++ #include <QSignalSpy>
++ #include <QDebug>
++ #include <QTimer>
++
++ #include <limits.h>
++
++ #include <qnumeric.h>
++ #include <QtPositioning/qgeopositioninfosource.h>
++ #include <QtPositioning/qgeopositioninfo.h>
++
++ #include "testqgeopositioninfosource_p.h"
++ #include "../utils/qlocationtestutils_p.h"
++
++ Q_DECLARE_METATYPE(QGeoPositionInfoSource::PositioningMethod)
++ Q_DECLARE_METATYPE(QGeoPositionInfoSource::PositioningMethods)
++
++ #define MAX_WAITING_TIME 50000
++
++ // Must provide a valid source, unless testing the source
++ // returned by QGeoPositionInfoSource::createDefaultSource() on a system
++ // that has no default source
++ #define CHECK_SOURCE_VALID { \
++ if (!m_source) { \
++ if (m_testingDefaultSource && QGeoPositionInfoSource::createDefaultSource(0) == 0) \
++ QSKIP("No default position source on this system"); \
++ else \
++ QFAIL("createTestSource() must return a valid source!"); \
++ } \
++ }
++
++ class MyPositionSource : public QGeoPositionInfoSource
++ {
++ Q_OBJECT
++ public:
++ MyPositionSource(QObject *parent = 0)
++ : QGeoPositionInfoSource(parent) {
++ }
++
++ QGeoPositionInfo lastKnownPosition(bool /*fromSatellitePositioningMethodsOnly = false*/) const override {
++ return QGeoPositionInfo();
++ }
++
++ void setSupportedPositioningMethods(PositioningMethods methods) {
++ m_methods = methods;
++ }
++
++ virtual PositioningMethods supportedPositioningMethods() const override {
++ return m_methods;
++ }
++ virtual int minimumUpdateInterval() const override {
++ return 0;
++ }
++
++ virtual void startUpdates() override {}
++ virtual void stopUpdates() override {}
++
++ virtual void requestUpdate(int) override {}
++
++ Error error() const override { return QGeoPositionInfoSource::NoError; }
++
++ private:
++ PositioningMethods m_methods;
++ };
++
++ class DefaultSourceTest : public TestQGeoPositionInfoSource
++ {
++ Q_OBJECT
++ protected:
++ QGeoPositionInfoSource *createTestSource() override {
++ return QGeoPositionInfoSource::createSource(QStringLiteral("test.source"), 0);
++ }
++ };
++
++
++ TestQGeoPositionInfoSource::TestQGeoPositionInfoSource(QObject *parent)
++ : QObject(parent)
++ {
++ m_testingDefaultSource = false;
++ #if QT_CONFIG(library)
++ /*
++ * Set custom path since CI doesn't install test plugins
++ */
++ #ifdef Q_OS_WIN
++ QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() +
++ QStringLiteral("/../../../../plugins"));
++ #else
++ QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath()
++ + QStringLiteral("/../../../plugins"));
++ #endif
++ #endif
++ }
++
++ TestQGeoPositionInfoSource *TestQGeoPositionInfoSource::createDefaultSourceTest()
++ {
++ DefaultSourceTest *test = new DefaultSourceTest;
++ test->m_testingDefaultSource = true;
++ return test;
++ }
++
++ void TestQGeoPositionInfoSource::test_slot1()
++ {
++ }
++
++ void TestQGeoPositionInfoSource::test_slot2()
++ {
++ m_testSlot2Called = true;
++ }
++
++ void TestQGeoPositionInfoSource::base_initTestCase()
++ {
++
++ }
++
++ void TestQGeoPositionInfoSource::base_init()
++ {
++ m_source = createTestSource();
++ m_testSlot2Called = false;
++ }
++
++ void TestQGeoPositionInfoSource::base_cleanup()
++ {
++ delete m_source;
++ m_source = 0;
++ }
++
++ void TestQGeoPositionInfoSource::base_cleanupTestCase()
++ {
++ }
++
++ void TestQGeoPositionInfoSource::initTestCase()
++ {
++ base_initTestCase();
++ }
++
++ void TestQGeoPositionInfoSource::init()
++ {
++ base_init();
++ }
++
++ void TestQGeoPositionInfoSource::cleanup()
++ {
++ base_cleanup();
++ }
++
++ void TestQGeoPositionInfoSource::cleanupTestCase()
++ {
++ base_cleanupTestCase();
++ }
++
++ // TC_ID_3_x_1
++ void TestQGeoPositionInfoSource::constructor_withParent()
++ {
++ auto parent = std::make_unique<QObject>();
++ new MyPositionSource(parent.get());
++ }
++
++ // TC_ID_3_x_2
++ void TestQGeoPositionInfoSource::constructor_noParent()
++ {
++ MyPositionSource *obj = new MyPositionSource();
++ delete obj;
++ }
++
++ void TestQGeoPositionInfoSource::updateInterval()
++ {
++ MyPositionSource s;
++ QCOMPARE(s.updateInterval(), 0);
++ }
++
++ void TestQGeoPositionInfoSource::setPreferredPositioningMethods()
++ {
++ QFETCH(QGeoPositionInfoSource::PositioningMethod, supported);
++ QFETCH(QGeoPositionInfoSource::PositioningMethod, preferred);
++ QFETCH(QGeoPositionInfoSource::PositioningMethod, resulting);
++
++ MyPositionSource s;
++ s.setSupportedPositioningMethods(supported);
++ s.setPreferredPositioningMethods(preferred);
++ QCOMPARE(s.preferredPositioningMethods(), resulting);
++ }
++
++ void TestQGeoPositionInfoSource::setPreferredPositioningMethods_data()
++ {
++ QTest::addColumn<QGeoPositionInfoSource::PositioningMethod>("supported");
++ QTest::addColumn<QGeoPositionInfoSource::PositioningMethod>("preferred");
++ QTest::addColumn<QGeoPositionInfoSource::PositioningMethod>("resulting");
++
++ QTest::newRow("Sat supported, Sat preferred")
++ << QGeoPositionInfoSource::SatellitePositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods;
++ QTest::newRow("Sat supported, Non-Sat preferred")
++ << QGeoPositionInfoSource::SatellitePositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods;
++ QTest::newRow("Sat supported, All preferred")
++ << QGeoPositionInfoSource::SatellitePositioningMethods
++ << QGeoPositionInfoSource::AllPositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods;
++
++ QTest::newRow("Non-Sat supported, Sat preferred")
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods;
++ QTest::newRow("Non-Sat supported, Non-Sat preferred")
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods;
++ QTest::newRow("Non-Sat supported, All preferred")
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods
++ << QGeoPositionInfoSource::AllPositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods;
++
++ QTest::newRow("All supported, Sat preferred")
++ << QGeoPositionInfoSource::AllPositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods
++ << QGeoPositionInfoSource::SatellitePositioningMethods;
++ QTest::newRow("All supported, Non-Sat preferred")
++ << QGeoPositionInfoSource::AllPositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods
++ << QGeoPositionInfoSource::NonSatellitePositioningMethods;
++ QTest::newRow("All supported, All preferred")
++ << QGeoPositionInfoSource::AllPositioningMethods
++ << QGeoPositionInfoSource::AllPositioningMethods
++ << QGeoPositionInfoSource::AllPositioningMethods;
++ }
++
++ void TestQGeoPositionInfoSource::preferredPositioningMethods()
++ {
++ MyPositionSource s;
++ QCOMPARE(s.preferredPositioningMethods(), 0);
++ }
++
++ //TC_ID_3_x_1 : Create a position source with the given parent that reads from the system's default
++ // sources of location data
++ void TestQGeoPositionInfoSource::createDefaultSource()
++ {
++ auto parent = std::make_unique<QObject>();
++
++ // source will be deleted when parent goes out of scope
++ QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(parent.get());
++ // now all platforms have the dummy plugin at least
++ QVERIFY(source != nullptr);
++ }
++
++ void TestQGeoPositionInfoSource::setUpdateInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QFETCH(int, interval);
++ QFETCH(int, expectedInterval);
++
++ m_source->setUpdateInterval(interval);
++ QCOMPARE(m_source->updateInterval(), expectedInterval);
++ }
++
++ void TestQGeoPositionInfoSource::setUpdateInterval_data()
++ {
++ QTest::addColumn<int>("interval");
++ QTest::addColumn<int>("expectedInterval");
++ QGeoPositionInfoSource *source = createTestSource();
++ int minUpdateInterval = source ? source->minimumUpdateInterval() : -1;
++ if (source)
++ delete source;
++
++ QTest::newRow("0") << 0 << 0;
++
++ if (minUpdateInterval > -1) {
++ QTest::newRow("INT_MIN") << INT_MIN << minUpdateInterval;
++ QTest::newRow("-1") << -1 << minUpdateInterval;
++ }
++
++ if (minUpdateInterval > 0) {
++ QTest::newRow("more than minInterval") << minUpdateInterval + 1 << minUpdateInterval + 1;
++ QTest::newRow("equal to minInterval") << minUpdateInterval << minUpdateInterval;
++ }
++
++ if (minUpdateInterval > 1) {
++ QTest::newRow("less then minInterval") << minUpdateInterval - 1 << minUpdateInterval;
++ QTest::newRow("in btw zero and minInterval") << 1 << minUpdateInterval;
++ }
++ }
++
++ void TestQGeoPositionInfoSource::lastKnownPosition()
++ {
++ CHECK_SOURCE_VALID;
++ QFETCH(QGeoPositionInfoSource::PositioningMethod, positioningMethod);
++ QFETCH(bool, lastKnownPositionArgument);
++
++ if ((m_source->supportedPositioningMethods() & positioningMethod) == 0)
++ QSKIP("Not a supported positioning method for this position source");
++
++ m_source->setPreferredPositioningMethods(positioningMethod);
++
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->setUpdateInterval(1000);
++ m_source->startUpdates();
++
++ // Use QEventLoop instead of qWait() to ensure we stop as soon as a
++ // position is emitted (otherwise the lastKnownPosition() may have
++ // changed by the time it is checked)
++ QEventLoop loop;
++ QTimer timer;
++ //simulated CI tests will quickly return -> real GPS tests take 2 minutes for satellite systems
++ //use a 5 min timeout
++ timer.setInterval(300000);
++ connect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)),
++ &loop, SLOT(quit()));
++ connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
++ timer.start();
++ loop.exec();
++
++ QVERIFY((spy.size() > 0) && (timeout.size() == 0));
++
++ QList<QVariant> list = spy.takeFirst();
++ QGeoPositionInfo info = list.at(0).value<QGeoPositionInfo>();
++ QGeoPositionInfo lastPositioninfo = m_source->lastKnownPosition(lastKnownPositionArgument);
++
++ // lastPositioninfo is only gauranteed to be valid in all cases when only using satelite
++ // positioning methods or when lastKnownPositionArgument is false
++ if (!lastKnownPositionArgument ||
++ positioningMethod == QGeoPositionInfoSource::SatellitePositioningMethods) {
++ QVERIFY(lastPositioninfo.isValid());
++ }
++
++ if (lastPositioninfo.isValid()) {
++ QCOMPARE(info.coordinate(), lastPositioninfo.coordinate());
++ // On some CI machines the above evenloop code is not sufficient as positionUpdated
++ // still fires causing last know position and last update to be out of sync.
++ // To accommodate we check that the time stamps are no more than 1s apart
++ // ideally they should be the same
++ // doesn't work: QCOMPARE(info.timestamp(), lastPositioninfo.timestamp());
++ const qint64 diff = qAbs(info.timestamp().msecsTo(lastPositioninfo.timestamp()));
++ QCOMPARE(diff < 1000, true);
++
++ QCOMPARE(info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy),
++ lastPositioninfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy));
++
++ if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) {
++ bool isNaN1 = qIsNaN(info.attribute(QGeoPositionInfo::HorizontalAccuracy));
++ bool isNaN2 = qIsNaN(lastPositioninfo.attribute(QGeoPositionInfo::HorizontalAccuracy));
++ QCOMPARE(isNaN1, isNaN2);
++ if (!isNaN1) {
++ QCOMPARE(info.attribute(QGeoPositionInfo::HorizontalAccuracy),
++ lastPositioninfo.attribute(QGeoPositionInfo::HorizontalAccuracy));
++ }
++ }
++
++ QCOMPARE(info.hasAttribute(QGeoPositionInfo::VerticalAccuracy),
++ lastPositioninfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy));
++
++ if (info.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) {
++ bool isNaN1 = qIsNaN(info.attribute(QGeoPositionInfo::VerticalAccuracy));
++ bool isNaN2 = qIsNaN(lastPositioninfo.attribute(QGeoPositionInfo::VerticalAccuracy));
++ QCOMPARE(isNaN1, isNaN2);
++ if (!isNaN1) {
++ QCOMPARE(info.attribute(QGeoPositionInfo::VerticalAccuracy),
++ lastPositioninfo.attribute(QGeoPositionInfo::VerticalAccuracy));
++ }
++ }
++ }
++
++ m_source->stopUpdates();
++ }
++
++ void TestQGeoPositionInfoSource::lastKnownPosition_data()
++ {
++ QTest::addColumn<QGeoPositionInfoSource::PositioningMethod>("positioningMethod");
++ QTest::addColumn<bool>("lastKnownPositionArgument");
++
++ // no good way to determine on MeeGo what are supported. If we ask for all or non-satellites, we
++ // typically get geoclue-example provider, which is not suitable for this test.
++ QTest::newRow("all - false") << QGeoPositionInfoSource::AllPositioningMethods << false;
++ QTest::newRow("all - true") << QGeoPositionInfoSource::AllPositioningMethods << true;
++ QTest::newRow("satellite - false") << QGeoPositionInfoSource::SatellitePositioningMethods << false;
++ QTest::newRow("satellite - true") << QGeoPositionInfoSource::SatellitePositioningMethods << true;
++ }
++
++ void TestQGeoPositionInfoSource::minimumUpdateInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QVERIFY(m_source->minimumUpdateInterval() > 0);
++ }
++
++ //TC_ID_3_x_1
++ void TestQGeoPositionInfoSource::startUpdates_testIntervals()
++ {
++ CHECK_SOURCE_VALID;
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->setUpdateInterval(1000);
++ const int interval = 15000;
++
++ m_source->startUpdates();
++
++ QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 1, interval);
++ for (int i = 0; i < 6; i++) {
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() == 1) && (timeout.size() == 0), interval);
++ spy.clear();
++ }
++
++ m_source->stopUpdates();
++ }
++
++
++ void TestQGeoPositionInfoSource::startUpdates_testIntervalChangesWhileRunning()
++ {
++ // There are two ways of dealing with an interval change, and we have left it system dependent.
++ // The interval can be changed will running or after the next update.
++ // WinCE uses the first method, S60 uses the second method.
++
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->setUpdateInterval(0);
++ m_source->startUpdates();
++ m_source->setUpdateInterval(0);
++
++ QTRY_VERIFY_WITH_TIMEOUT(spy.size() > 0, 3000);
++ QCOMPARE(timeout.size(), 0);
++ spy.clear();
++
++ m_source->setUpdateInterval(1000);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() == 2) && (timeout.size() == 0), 15000);
++ spy.clear();
++
++ m_source->setUpdateInterval(2000);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() == 2) && (timeout.size() == 0), 30000);
++ spy.clear();
++
++ m_source->setUpdateInterval(1000);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() == 2) && (timeout.size() == 0), 15000);
++ spy.clear();
++
++ m_source->setUpdateInterval(1000);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() == 2) && (timeout.size() == 0), 15000);
++ spy.clear();
++
++ m_source->setUpdateInterval(0);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() > 0) && (timeout.size() == 0), 7000);
++ spy.clear();
++
++ m_source->setUpdateInterval(0);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() > 0) && (timeout.size() == 0), 7000);
++ spy.clear();
++
++ m_source->stopUpdates();
++ }
++
++ //TC_ID_3_x_2
++ void TestQGeoPositionInfoSource::startUpdates_testDefaultInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->startUpdates();
++ for (int i = 0; i < 3; i++) {
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() > 0) && (timeout.size() == 0), 7000);
++ spy.clear();
++ }
++ m_source->stopUpdates();
++ }
++
++ //TC_ID_3_x_3
++ void TestQGeoPositionInfoSource::startUpdates_testZeroInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->setUpdateInterval(0);
++ m_source->startUpdates();
++ for (int i = 0; i < 3; i++) {
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() > 0) && (timeout.size() == 0), 7000);
++ spy.clear();
++ }
++ m_source->stopUpdates();
++ }
++
++ void TestQGeoPositionInfoSource::startUpdates_moreThanOnce()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->setUpdateInterval(0);
++ m_source->startUpdates();
++
++ m_source->startUpdates(); // check there is no crash
++
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() > 0) && (timeout.size() == 0), 7000);
++
++ m_source->startUpdates(); // check there is no crash
++
++ m_source->stopUpdates();
++ }
++
++ //TC_ID_3_x_1
++ void TestQGeoPositionInfoSource::stopUpdates()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spy(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy timeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->setUpdateInterval(1000);
++ m_source->startUpdates();
++ for (int i = 0; i < 2; i++) {
++ QTRY_VERIFY_WITH_TIMEOUT((spy.size() > 0) && (timeout.size() == 0), 9500);
++ spy.clear();
++ }
++ m_source->stopUpdates();
++ QTest::qWait(2000);
++ QCOMPARE(spy.size(), 0);
++ spy.clear();
++
++ m_source->setUpdateInterval(0);
++ m_source->startUpdates();
++ m_source->stopUpdates();
++ QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 0, 9500);
++ }
++
++ //TC_ID_3_x_2
++ void TestQGeoPositionInfoSource::stopUpdates_withoutStart()
++ {
++ CHECK_SOURCE_VALID;
++ m_source->stopUpdates(); // check there is no crash
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdate()
++ {
++ CHECK_SOURCE_VALID;
++ QFETCH(int, timeout);
++ QSignalSpy spy(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->requestUpdate(timeout);
++ QTRY_COMPARE(spy.size(), 1);
++ const QList<QVariant> arguments = spy.takeFirst();
++ const auto error = arguments.at(0).value<QGeoPositionInfoSource::Error>();
++ QCOMPARE(error, QGeoPositionInfoSource::UpdateTimeoutError);
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdate_data()
++ {
++ QTest::addColumn<int>("timeout");
++ QTest::newRow("less than zero") << -1; //TC_ID_3_x_7
++ }
++
++ // TC_ID_3_x_1 : Create position source and call requestUpdate with valid timeout value
++ void TestQGeoPositionInfoSource::requestUpdate_validTimeout()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ // currently all the sources have a minimumUpdateInterval <= 1000
++ m_source->requestUpdate(1500);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdate_defaultTimeout()
++ {
++ CHECK_SOURCE_VALID;
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ m_source->requestUpdate(0);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ }
++
++ // TC_ID_3_x_2 : Create position source and call requestUpdate with a timeout less than
++ // minimumupdateInterval
++ void TestQGeoPositionInfoSource::requestUpdate_timeoutLessThanMinimumInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++ m_source->requestUpdate(1);
++
++ QTRY_COMPARE_WITH_TIMEOUT(spyTimeout.size(), 1, 1000);
++ const QList<QVariant> arguments = spyTimeout.takeFirst();
++ const auto error = arguments.at(0).value<QGeoPositionInfoSource::Error>();
++ QCOMPARE(error, QGeoPositionInfoSource::UpdateTimeoutError);
++ }
++
++ // TC_ID_3_x_3 : Call requestUpdate() with same value repeatedly
++ void TestQGeoPositionInfoSource::requestUpdate_repeatedCalls()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ // currently all the sources have a minimumUpdateInterval <= 1000
++ m_source->requestUpdate(1500);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ spyUpdate.clear();
++ m_source->requestUpdate(1500);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdate_overlappingCalls()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ // currently all the sources have a minimumUpdateInterval <= 1000
++ m_source->requestUpdate(1500);
++ m_source->requestUpdate(1500);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ }
++
++ //TC_ID_3_x_4
++ void TestQGeoPositionInfoSource::requestUpdateAfterStartUpdates_ZeroInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ m_source->setUpdateInterval(0);
++ m_source->startUpdates();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ spyUpdate.clear();
++
++ m_source->requestUpdate(1500);
++ QTest::qWait(7000);
++
++ QVERIFY((spyUpdate.size() > 0) && (spyTimeout.size() == 0));
++ spyUpdate.clear();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), MAX_WAITING_TIME);
++
++ m_source->stopUpdates();
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdateAfterStartUpdates_SmallInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ m_source->setUpdateInterval(2000);
++ m_source->startUpdates();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() == 1) && (spyTimeout.size() == 0), 20000);
++ spyUpdate.clear();
++
++ m_source->requestUpdate(1500);
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() == 1) && (spyTimeout.size() == 0), 7000);
++ spyUpdate.clear();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() == 1) && (spyTimeout.size() == 0), 20000);
++
++ m_source->stopUpdates();
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdateBeforeStartUpdates_ZeroInterval()
++ {
++ CHECK_SOURCE_VALID;
++
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ m_source->requestUpdate(1500);
++
++ m_source->setUpdateInterval(0);
++ m_source->startUpdates();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() >= 2) && (spyTimeout.size() == 0), 14000);
++ spyUpdate.clear();
++
++ QTest::qWait(1500);
++
++ QCOMPARE(spyTimeout.size(), 0);
++
++ m_source->stopUpdates();
++ }
++
++ void TestQGeoPositionInfoSource::requestUpdateBeforeStartUpdates_SmallInterval()
++ {
++ CHECK_SOURCE_VALID;
++ QSignalSpy spyUpdate(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)));
++ QSignalSpy spyTimeout(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)));
++
++ m_source->requestUpdate(1500);
++
++ m_source->setUpdateInterval(3000);
++ m_source->startUpdates();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 7000);
++ spyUpdate.clear();
++
++ QTRY_VERIFY_WITH_TIMEOUT((spyUpdate.size() > 0) && (spyTimeout.size() == 0), 20000);
++
++ m_source->stopUpdates();
++ }
++
++ void TestQGeoPositionInfoSource::removeSlotForRequestTimeout()
++ {
++ CHECK_SOURCE_VALID;
++
++ bool i = connect(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)),
++ this, SLOT(test_slot1()));
++ QVERIFY(i == true);
++ i = connect(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)),
++ this, SLOT(test_slot2()));
++ QVERIFY(i == true);
++ i = disconnect(m_source, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)),
++ this, SLOT(test_slot1()));
++ QVERIFY(i == true);
++
++ m_source->requestUpdate(-1);
++ QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 1000);
++ }
++
++ void TestQGeoPositionInfoSource::removeSlotForPositionUpdated()
++ {
++ CHECK_SOURCE_VALID;
++
++ bool i = connect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(test_slot1()));
++ QVERIFY(i == true);
++ i = connect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(test_slot2()));
++ QVERIFY(i == true);
++ i = disconnect(m_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(test_slot1()));
++ QVERIFY(i == true);
++
++ m_source->requestUpdate(1500);
++
++ QTRY_VERIFY_WITH_TIMEOUT((m_testSlot2Called == true), 7000);
++ }
++
++ void TestQGeoPositionInfoSource::updateIntervalBinding()
++ {
++ auto parent = std::make_unique<QObject>();
++ // source will be deleted when parent goes out of scope
++ QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(parent.get());
++ QVERIFY(source != nullptr);
++
++ QTestPrivate::testReadWritePropertyBasics<QGeoPositionInfoSource, int>(
++ *source, 1000, 2000, "updateInterval",
++ []() {
++ return std::unique_ptr<QGeoPositionInfoSource>(
++ QGeoPositionInfoSource::createDefaultSource(nullptr));
++ });
++ }
++
++ void TestQGeoPositionInfoSource::preferredMethodsBinding()
++ {
++ auto parent = std::make_unique<QObject>();
++ // source will be deleted when parent goes out of scope
++ QGeoPositionInfoSource *source =
++ QGeoPositionInfoSource::createSource("test.source", parent.get());
++ QVERIFY(source != nullptr);
++
++ QTestPrivate::testReadWritePropertyBasics<QGeoPositionInfoSource,
++ QGeoPositionInfoSource::PositioningMethods>(
++ *source, QGeoPositionInfoSource::SatellitePositioningMethods,
++ QGeoPositionInfoSource::AllPositioningMethods, "preferredPositioningMethods",
++ []() {
++ return std::unique_ptr<QGeoPositionInfoSource>(
++ QGeoPositionInfoSource::createSource("test.source", nullptr));
++ });
++ }
++
++ #include "testqgeopositioninfosource.moc"