From 7cd6a4db67cccad64e6e0965654b30353ab35d3b Mon Sep 17 00:00:00 2001 From: Lincoln Ramsay Date: Tue, 23 Aug 2011 11:24:22 +1000 Subject: Add a unit test for QtmSensors. As parts of the QtSensors unit test are re-used, they must be updated to include the correct headers. Change-Id: I189eb74fe312f74cfbe9e1fb605ac047bc9bdfbb Reviewed-on: http://codereview.qt.nokia.com/3349 Reviewed-by: Qt Sanity Bot Reviewed-by: Zsolt Simon --- tests/auto/qtmsensor/tst_qtmsensor.cpp | 766 +++++++++++++++++++++++++++++++++ 1 file changed, 766 insertions(+) create mode 100644 tests/auto/qtmsensor/tst_qtmsensor.cpp (limited to 'tests/auto/qtmsensor/tst_qtmsensor.cpp') diff --git a/tests/auto/qtmsensor/tst_qtmsensor.cpp b/tests/auto/qtmsensor/tst_qtmsensor.cpp new file mode 100644 index 00000000..40f90670 --- /dev/null +++ b/tests/auto/qtmsensor/tst_qtmsensor.cpp @@ -0,0 +1,766 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtSensors module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/sensors + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_sensor_qtm.h" +#include "test_backends_qtm.h" +#include + +static char const * const testsensorimpl_id("test sensor impl"); + +Q_SENSORS_EXPORT void sensors_unit_test_hook(int); + +QTM_BEGIN_NAMESPACE +QTM_SENSORS_EXPORT void qtm_sensors_unit_test_hook(int); +QTM_END_NAMESPACE + +QTM_USE_NAMESPACE + +bool operator==(const qoutputrange &orl1, const qoutputrange &orl2) +{ + return (orl1.minimum == orl2.minimum && + orl1.maximum == orl2.maximum && + orl1.accuracy == orl2.accuracy); +} + +namespace QTest { + template<> char *toString(const qoutputrangelist &orl) + { + QStringList list; + foreach (const qoutputrange &item, orl) { + list << QString("%1-%2%3%4").arg(item.minimum).arg(item.maximum).arg(QString::fromWCharArray(L"\u00B1")).arg(item.accuracy); + } + QString ret = QString("qoutputrangelist: (%1)").arg(list.join("), (")); + return qstrdup(ret.toLatin1().data()); + } + template<> char *toString(const QList &data) + { + QStringList list; + foreach (const QByteArray &str, data) { + list << QString::fromLatin1(str); + } + QString ret = QString("QList: (%1)").arg(list.join("), (")); + return qstrdup(ret.toLatin1().data()); + } +} + + +class MyFilter : public TestSensorFilter { bool filter(TestSensorReading *) { return false; } }; + +class ModFilter : public TestSensorFilter +{ + bool filter(TestSensorReading *reading) + { + reading->setTest(3); + return true; + } +}; + +/* + Unit test for QtmSensor class. +*/ +class tst_QtmSensor : public QObject +{ + Q_OBJECT + +public: + tst_QtmSensor() + { + sensors_unit_test_hook(0); // change some flags the library uses + qtm_sensors_unit_test_hook(0); // change some flags the library uses + } + +private slots: + void initTestCase() + { + QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors")); + settings.clear(); + } + + void cleanupTestCase() + { + QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors")); + settings.clear(); + +#ifdef WAIT_AT_END + QFile _stdin; + _stdin.open(1, QIODevice::ReadOnly); + _stdin.readLine(); +#endif + } + + // This test MUST be first + void testRecursiveLoadPlugins() + { + TestSensor sensor; + + // This confirms that legacy static plugins can still be registered + //QTest::ignoreMessage(QtWarningMsg, "Loaded the LegacySensorPlugin "); + + // The logic for the test is in test_sensorplugin.cpp (which warns and aborts if the test fails) + (void)QSensor::sensorTypes(); + + // Checking that the availableSensorsChanged() signal was not emitted too many times while loading plugins. + QCOMPARE(sensor.sensorsChangedEmitted, 1); + } + + void testTypeRegistered() + { + QList expected; + expected << TestSensor::type; + QList actual = QSensor::sensorTypes(); + qSort(actual); // The actual list is not in a defined order + QCOMPARE(actual, expected); + } + + void testSensorRegistered() + { + QList expected; + expected << "test sensor 2" << "test sensor 3" << testsensorimpl_id; + QList actual = QSensor::sensorsForType(TestSensor::type); + qSort(actual); // The actual list is not in a defined order + QCOMPARE(actual, expected); + } + + void testSensorDefault() + { + QByteArray expected = testsensorimpl_id; + QByteArray actual = QSensor::defaultSensorForType(TestSensor::type); + QCOMPARE(actual, expected); + } + + void testBadDefaultFromConfig() + { + QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors")); + settings.setValue(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(TestSensor::type)), QByteArray("bogus id")); + settings.sync(); + + QByteArray expected = testsensorimpl_id; + QByteArray actual = QSensor::defaultSensorForType(TestSensor::type); + QCOMPARE(actual, expected); + } + + void testGoodDefaultFromConfig() + { + QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors")); + settings.setValue(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(TestSensor::type)), QByteArray(testsensorimpl_id)); + settings.sync(); + + QByteArray expected = testsensorimpl_id; + QByteArray actual = QSensor::defaultSensorForType(TestSensor::type); + QCOMPARE(actual, expected); + + settings.clear(); + } + + void testNoSensorsForType() + { + QList expected; + QList actual = QSensor::sensorsForType("bogus type"); + QCOMPARE(actual, expected); + } + + void testNoDefaultForType() + { + QByteArray expected; + QByteArray actual = QSensor::defaultSensorForType("bogus type"); + QCOMPARE(actual, expected); + } + + void testCreation() + { + TestSensor sensor; + sensor.connectToBackend(); + QByteArray expected = testsensorimpl_id; + QByteArray actual = sensor.identifier(); + QCOMPARE(actual, expected); + } + + void testSetIdentifierFail() + { + TestSensor sensor; + sensor.setIdentifier(testsensorimpl_id); + sensor.connectToBackend(); + QVERIFY(sensor.isConnectedToBackend()); + QByteArray expected = testsensorimpl_id; + QByteArray actual = sensor.identifier(); + QCOMPARE(actual, expected); + + QTest::ignoreMessage(QtWarningMsg, "ERROR: Cannot call QSensor::setIdentifier while connected to a backend! "); + sensor.setIdentifier("dummy.accelerometer"); + expected = testsensorimpl_id; + actual = sensor.identifier(); + QCOMPARE(actual, expected); + } + + void testBadDefaultCreation() + { + QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors")); + settings.setValue(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(TestSensor::type)), QByteArray("test sensor 2")); + settings.sync(); + + TestSensor sensor; + QTest::ignoreMessage(QtWarningMsg, "Can't create backend \"test sensor 2\" "); + sensor.connectToBackend(); + QByteArray expected = testsensorimpl_id; + QByteArray actual = sensor.identifier(); + QCOMPARE(actual, expected); + + settings.clear(); + } + + void testBadCreation() + { + QSensor sensor("bogus type"); + sensor.connectToBackend(); + QByteArray expected; // should be null + QByteArray actual = sensor.identifier(); + QCOMPARE(actual, expected); + } + + void testTimestamp() + { + TestSensor sensor; + sensor.connectToBackend(); + QVERIFY(sensor.reading() != 0); + qtimestamp timestamp = sensor.reading()->timestamp(); + QVERIFY(timestamp == qtimestamp()); + sensor.setProperty("doThis", "setOne"); + sensor.start(); + timestamp = sensor.reading()->timestamp(); + QVERIFY(timestamp == 1); + } + + void testStart() + { + TestSensor sensor; + sensor.start(); + QVERIFY(sensor.isActive()); + sensor.start(); + QVERIFY(sensor.isActive()); + } + + void testBadStart() + { + QSensor sensor("bogus type"); + sensor.start(); + QVERIFY(!sensor.isActive()); + } + + void testStop() + { + TestSensor sensor; + sensor.stop(); + QVERIFY(!sensor.isActive()); + sensor.start(); + QVERIFY(sensor.isActive()); + sensor.stop(); + QVERIFY(!sensor.isActive()); + } + + void testMetaData() + { + TestSensor sensor; + + { + bool actual = sensor.isConnectedToBackend(); + bool expected = false; + QCOMPARE(actual, expected); + } + + sensor.connectToBackend(); + + { + bool actual = sensor.isConnectedToBackend(); + bool expected = true; + QCOMPARE(actual, expected); + } + + { + QString actual = sensor.description(); + QString expected = "sensor description"; + QCOMPARE(actual, expected); + } + + { + qoutputrangelist actual = sensor.outputRanges(); + qoutputrangelist expected; + qoutputrange r; r.minimum = 0; r.maximum = 1; r.accuracy = 0.5; + expected << r; + r.minimum = 0; r.maximum = 2; r.accuracy = 1; + expected << r; + QCOMPARE(actual, expected); + } + + { + int actual = sensor.outputRange(); + int expected = -1; + QCOMPARE(actual, expected); + + sensor.setOutputRange(0); + + actual = sensor.outputRange(); + expected = 0; + QCOMPARE(actual, expected); + } + + { + qrangelist actual = sensor.availableDataRates(); + qrangelist expected = qrangelist() << qrange(100,100); + QCOMPARE(actual, expected); + } + + { + TestSensor sensor; + sensor.setProperty("doThis", "rates"); + sensor.connectToBackend(); + qrangelist actual = sensor.availableDataRates(); + qrangelist expected = qrangelist() << qrange(100,100); + QCOMPARE(actual, expected); + } + + { + TestSensor sensor; + sensor.setProperty("doThis", "rates(0)"); + QTest::ignoreMessage(QtWarningMsg, "ERROR: Cannot call QSensorBackend::setDataRates with 0 "); + sensor.connectToBackend(); + } + + { + TestSensor sensor; + sensor.setProperty("doThis", "rates(nodef)"); + QTest::ignoreMessage(QtWarningMsg, "ERROR: Cannot call QSensorBackend::setDataRates with an invalid sensor "); + sensor.connectToBackend(); + } + + { + int actual = sensor.dataRate(); + int expected = 0; + QCOMPARE(actual, expected); + + sensor.setDataRate(100); + + actual = sensor.dataRate(); + expected = 100; + QCOMPARE(actual, expected); + } + + // Test the generic accessor functions + TestSensorReading *reading = sensor.reading(); + QCOMPARE(reading->valueCount(), 1); + reading->setTest(1); + QCOMPARE(reading->test(), reading->value(0).toInt()); + } + + void testFilter() + { + TestSensor sensor; + sensor.connectToBackend(); + + QList actual = sensor.filters(); + QList expected = QList(); + QCOMPARE(actual, expected); + + QTest::ignoreMessage(QtWarningMsg, "addFilter: passed a null filter! "); + sensor.addFilter(0); + + QTest::ignoreMessage(QtWarningMsg, "removeFilter: passed a null filter! "); + sensor.removeFilter(0); + + MyFilter *filter = new MyFilter; + sensor.addFilter(filter); + + actual = sensor.filters(); + expected = QList() << filter; + QCOMPARE(actual, expected); + + MyFilter *filter2 = new MyFilter; + sensor.addFilter(filter2); + + actual = sensor.filters(); + expected = QList() << filter << filter2; + QCOMPARE(actual, expected); + + delete filter2; + + actual = sensor.filters(); + expected = QList() << filter; + QCOMPARE(actual, expected); + + sensor.removeFilter(filter); + + actual = sensor.filters(); + expected = QList(); + QCOMPARE(actual, expected); + + delete filter; + } + + void testFilter2() + { + TestSensor sensor; + sensor.setProperty("doThis", "setOne"); + TestSensorFilter *filter1 = new ModFilter; + TestSensorFilter *filter2 = new MyFilter; + sensor.addFilter(filter1); + sensor.start(); + QCOMPARE(sensor.reading()->test(), 3); + sensor.stop(); + sensor.reading()->setTest(1); + sensor.addFilter(filter2); + sensor.start(); + QCOMPARE(sensor.reading()->test(), 1); + sensor.stop(); + delete filter1; + delete filter2; + } + + void testFilter3() + { + TestSensor sensor; + sensor.setProperty("doThis", "setOne"); + QSignalSpy spy(&sensor, SIGNAL(readingChanged())); + sensor.start(); + QCOMPARE(spy.count(), 1); // reading changes + sensor.stop(); + + TestSensorFilter *filter2 = new MyFilter; + sensor.addFilter(filter2); + sensor.start(); + QCOMPARE(spy.count(), 1); // filter suppresses reading so it does not change + sensor.stop(); + delete filter2; + + TestSensorFilter *filter1 = new ModFilter; + sensor.addFilter(filter1); + sensor.start(); + QCOMPARE(spy.count(), 2); // filter does not suppress reading + sensor.stop(); + delete filter1; + } + + void testStart2() + { + TestSensor sensor; + sensor.connectToBackend(); + + sensor.setProperty("doThis", "stop"); + sensor.start(); + QVERIFY(!sensor.isActive()); + sensor.stop(); + + sensor.setProperty("doThis", "error"); + sensor.start(); + QVERIFY(sensor.error() == 1); + // Yes, this is non-intuitive but the sensor + // decides if an error is fatal or not. + // In this case our test sensor is reporting a + // non-fatal error so the sensor will start. + QVERIFY(sensor.isActive()); + sensor.stop(); + + sensor.setProperty("doThis", "setOne"); + sensor.start(); + QCOMPARE(sensor.reading()->timestamp(), qtimestamp(1)); + QCOMPARE(sensor.reading()->test(), 1); + sensor.stop(); + + sensor.setProperty("doThis", "setTwo"); + sensor.start(); + QCOMPARE(sensor.reading()->timestamp(), qtimestamp(2)); + QCOMPARE(sensor.reading()->test(), 2); + sensor.stop(); + } + + void testSetBadDataRate() + { + TestSensor sensor; + sensor.connectToBackend(); + + QTest::ignoreMessage(QtWarningMsg, "setDataRate: 1 is not supported by the sensor. "); + sensor.setDataRate(1); + QCOMPARE(sensor.dataRate(), 0); + + QTest::ignoreMessage(QtWarningMsg, "setDataRate: 1000 is not supported by the sensor. "); + sensor.setDataRate(1000); + QCOMPARE(sensor.dataRate(), 0); + } + + void testSetBadDataRateWhenNotConnected() + { + TestSensor sensor; + sensor.setDataRate(0); + QCOMPARE(sensor.dataRate(), 0); + sensor.setDataRate(300); + QCOMPARE(sensor.dataRate(), 300); + sensor.setDataRate(350); + QTest::ignoreMessage(QtWarningMsg, "setDataRate: 350 is not supported by the sensor. "); + sensor.connectToBackend(); + QCOMPARE(sensor.dataRate(), 0); + } + + void testSetBadOutputRange() + { + TestSensor sensor; + sensor.connectToBackend(); + + sensor.setOutputRange(-1); + QCOMPARE(sensor.outputRange(), -1); + QTest::ignoreMessage(QtWarningMsg, "setOutputRange: 300 is not supported by the sensor. "); + sensor.setOutputRange(300); + QCOMPARE(sensor.outputRange(), -1); + } + + void testSetBadOutputRangeWhenNotConnected() + { + TestSensor sensor; + sensor.setOutputRange(300); + QCOMPARE(sensor.outputRange(), 300); + sensor.setOutputRange(350); + QTest::ignoreMessage(QtWarningMsg, "setOutputRange: 350 is not supported by the sensor. "); + sensor.connectToBackend(); + QCOMPARE(sensor.outputRange(), -1); + QTest::ignoreMessage(QtWarningMsg, "setOutputRange: -2 is not supported by the sensor. "); + sensor.setOutputRange(-2); + QCOMPARE(sensor.outputRange(), -1); + } + + void testEnumHandling() + { + { + QAmbientLightReading reading; + for (int i = 0; i <= 6; i++) { + QAmbientLightReading::LightLevel setting = static_cast(i); + QAmbientLightReading::LightLevel expected = setting; + if (i == 6) + expected = QAmbientLightReading::Undefined; + reading.setLightLevel(setting); + QCOMPARE(reading.lightLevel(), expected); + } + } + + { + QOrientationReading reading; + for (int i = 0; i <= 7; i++) { + QOrientationReading::Orientation setting = static_cast(i); + QOrientationReading::Orientation expected = setting; + if (i == 7) + expected = QOrientationReading::Undefined; + reading.setOrientation(setting); + QCOMPARE(reading.orientation(), expected); + } + } + + { + QTapReading reading; + reading.setTapDirection(QTapReading::Undefined); + QCOMPARE(reading.tapDirection(), QTapReading::Undefined); + reading.setTapDirection(QTapReading::X_Pos); + QCOMPARE(reading.tapDirection(), QTapReading::X_Pos); + reading.setTapDirection(QTapReading::X_Neg); + QCOMPARE(reading.tapDirection(), QTapReading::X_Neg); + reading.setTapDirection(QTapReading::Y_Pos); + QCOMPARE(reading.tapDirection(), QTapReading::Y_Pos); + reading.setTapDirection(QTapReading::Y_Neg); + QCOMPARE(reading.tapDirection(), QTapReading::Y_Neg); + reading.setTapDirection(QTapReading::Z_Pos); + QCOMPARE(reading.tapDirection(), QTapReading::Z_Pos); + reading.setTapDirection(QTapReading::Z_Neg); + QCOMPARE(reading.tapDirection(), QTapReading::Z_Neg); + // Directions can be ORed together + reading.setTapDirection(QTapReading::X_Both); + QCOMPARE(reading.tapDirection(), QTapReading::X_Both); + reading.setTapDirection(QTapReading::Y_Both); + QCOMPARE(reading.tapDirection(), QTapReading::Y_Both); + reading.setTapDirection(QTapReading::Z_Both); + QCOMPARE(reading.tapDirection(), QTapReading::Z_Both); + // You can't set just the Axis + reading.setTapDirection(QTapReading::X); + QCOMPARE(reading.tapDirection(), QTapReading::Undefined); + reading.setTapDirection(QTapReading::Y); + QCOMPARE(reading.tapDirection(), QTapReading::Undefined); + reading.setTapDirection(QTapReading::Z); + QCOMPARE(reading.tapDirection(), QTapReading::Undefined); + reading.setTapDirection(static_cast(0x1000)); + QCOMPARE(reading.tapDirection(), QTapReading::Undefined); + } + } + + void testSetActive() + { + TestSensor sensor; + sensor.setActive(true); + // doesn't start till the event loop is hit + QVERIFY(!sensor.isActive()); + // hit the event loop + QTest::qWait(0); + QVERIFY(sensor.isActive()); + sensor.setActive(true); + QVERIFY(sensor.isActive()); + // it does stop immediately + sensor.setActive(false); + QVERIFY(!sensor.isActive()); + } + + void testIsRegistered() + { + bool expected; + bool actual; + + expected = true; + actual = QSensorManager::isBackendRegistered(TestSensor::type, testsensorimpl_id); + QCOMPARE(expected, actual); + + expected = false; + actual = QSensorManager::isBackendRegistered(TestSensor::type, "random"); + QCOMPARE(expected, actual); + + expected = false; + actual = QSensorManager::isBackendRegistered("random", "random"); + QCOMPARE(expected, actual); + } + + void testAllTheInterfaces() + { + register_test_backends(); + + TEST_SENSORINTERFACE(QAccelerometer, QAccelerometerReading, { + QCOMPARE(reading->x(), 1.0); + QCOMPARE(reading->y(), 1.0); + QCOMPARE(reading->z(), 1.0); + }) + + TEST_SENSORINTERFACE(QAmbientLightSensor, QAmbientLightReading, { + QCOMPARE(reading->lightLevel(), QAmbientLightReading::Twilight); + }) + + TEST_SENSORINTERFACE(QCompass, QCompassReading, { + QCOMPARE(reading->azimuth(), 1.0); + QCOMPARE(reading->calibrationLevel(), 1.0); + }) + + TEST_SENSORINTERFACE(QGyroscope, QGyroscopeReading, { + QCOMPARE(reading->x(), 1.0); + QCOMPARE(reading->y(), 1.0); + QCOMPARE(reading->z(), 1.0); + }) + + TEST_SENSORINTERFACE(QLightSensor, QLightReading, { + QCOMPARE(reading->lux(), 1.0); + }) + + TEST_SENSORINTERFACE(QMagnetometer, QMagnetometerReading, { + QCOMPARE(reading->x(), 1.0); + QCOMPARE(reading->y(), 1.0); + QCOMPARE(reading->z(), 1.0); + QCOMPARE(reading->calibrationLevel(), 1.0); + }) + + TEST_SENSORINTERFACE(QOrientationSensor, QOrientationReading, { + QCOMPARE(reading->orientation(), QOrientationReading::LeftUp); + }) + + TEST_SENSORINTERFACE(QProximitySensor, QProximityReading, { + QCOMPARE(reading->close(), true); + }) + + TEST_SENSORINTERFACE(QRotationSensor, QRotationReading, { + QCOMPARE(reading->x(), 1.0); + QCOMPARE(reading->y(), 1.0); + QCOMPARE(reading->z(), 1.0); + }) + + TEST_SENSORINTERFACE(QTapSensor, QTapReading, { + QCOMPARE(reading->tapDirection(), QTapReading::Z_Both); + QCOMPARE(reading->isDoubleTap(), true); + }) + + unregister_test_backends(); + } + + void testBusyChanged() + { + // Start an exclusive sensor + TestSensor sensor1; + sensor1.setProperty("exclusive", true); + sensor1.start(); + QVERIFY(sensor1.isActive()); + + // Try to start another one, sensor reports busy + TestSensor sensor2; + sensor2.setProperty("exclusive", true); + sensor2.start(); + QVERIFY(sensor2.isBusy()); + QVERIFY(!sensor2.isActive()); + + // Stopping the first instance causes the busyChanged signal to be emitted from the second instance + QSignalSpy spy(&sensor2, SIGNAL(busyChanged())); + sensor1.stop(); + QCOMPARE(spy.count(), 1); + + // Now we can start the second instance + sensor2.start(); + QVERIFY(sensor2.isActive()); + } +}; + +QTEST_MAIN(tst_QtmSensor) + +#include "tst_qtmsensor.moc" -- cgit v1.2.3