split tests into different files
This commit is contained in:
parent
7c4354a6e1
commit
ca8717d2a0
@ -105,6 +105,14 @@ DeviceManager::DeviceManager(QObject *parent) :
|
||||
QMetaObject::invokeMethod(this, "loaded", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager()
|
||||
{
|
||||
qDebug() << "Shutting down DeviceManager";
|
||||
foreach (DevicePlugin *plugin, m_devicePlugins) {
|
||||
delete plugin;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Returns all the \l{DevicePlugin}{DevicePlugins} loaded in the system. */
|
||||
QList<DevicePlugin *> DeviceManager::plugins() const
|
||||
{
|
||||
|
||||
@ -69,6 +69,7 @@ public:
|
||||
};
|
||||
|
||||
explicit DeviceManager(QObject *parent = 0);
|
||||
~DeviceManager();
|
||||
|
||||
QList<DevicePlugin*> plugins() const;
|
||||
DevicePlugin* plugin(const PluginId &id) const;
|
||||
|
||||
@ -37,6 +37,12 @@ ActionTypeId mockAction2Id = ActionTypeId("defd3ed6-1a0d-400b-8879-a0202cf39935"
|
||||
|
||||
DevicePluginMock::DevicePluginMock()
|
||||
{
|
||||
qDebug() << "Mock device plugin created";
|
||||
}
|
||||
|
||||
DevicePluginMock::~DevicePluginMock()
|
||||
{
|
||||
qDebug() << "shutting down Mock device plugin";
|
||||
}
|
||||
|
||||
QList<Vendor> DevicePluginMock::supportedVendors() const
|
||||
|
||||
@ -34,6 +34,7 @@ class DevicePluginMock : public DevicePlugin
|
||||
|
||||
public:
|
||||
explicit DevicePluginMock();
|
||||
~DevicePluginMock();
|
||||
|
||||
QList<Vendor> supportedVendors() const override;
|
||||
QList<DeviceClass> supportedDevices() const override;
|
||||
|
||||
@ -47,6 +47,11 @@ GuhCore *GuhCore::instance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
GuhCore::~GuhCore()
|
||||
{
|
||||
qDebug() << "Shutting down. Bye.";
|
||||
}
|
||||
|
||||
void GuhCore::destroy()
|
||||
{
|
||||
delete s_instance;
|
||||
|
||||
@ -34,6 +34,7 @@ class GuhCore : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
static GuhCore* instance();
|
||||
~GuhCore();
|
||||
|
||||
// Used for testing
|
||||
void destroy();
|
||||
|
||||
@ -7,14 +7,28 @@ DEFINES += TESTING_ENABLED
|
||||
DEFINES += TESTS_SOURCE_DIR=\\\"$$top_srcdir/tests/auto/\\\"
|
||||
|
||||
INCLUDEPATH += $$top_srcdir/server/ $$top_srcdir/server/jsonrpc $$top_srcdir/libguh $$top_srcdir/tests/auto/
|
||||
LIBS += -L$$top_builddir/libguh/ -lguh
|
||||
LIBS += -L$$top_builddir/libguh/ -lguh -L$$top_builddir/plugins/deviceplugins/mock/ -lguh_devicepluginmock
|
||||
QMAKE_LFLAGS += -Wl,--rpath=$$top_builddir/libguh
|
||||
|
||||
include($$top_srcdir/server/server.pri)
|
||||
|
||||
SOURCES += testjsonrpc.cpp \
|
||||
mocktcpserver.cpp
|
||||
testcases="TestJSONRPC TestVersioning TestDevices"
|
||||
|
||||
HEADERS += mocktcpserver.h
|
||||
SOURCES += guhtestbase.cpp \
|
||||
mocktcpserver.cpp \
|
||||
testjsonrpc.cpp \
|
||||
testversioning.cpp \
|
||||
testdevices.cpp
|
||||
|
||||
LIBS += -L$$top_builddir/plugins/deviceplugins/mock/ -lguh_devicepluginmock
|
||||
HEADERS += mocktcpserver.h \
|
||||
guhtestbase.h \
|
||||
testdefines.h \
|
||||
testversioning.h \
|
||||
testjsonrpc.h \
|
||||
testdevices.h
|
||||
|
||||
message("testcases: $${testcases}")
|
||||
#DEFINES += TESTCASES=\\\"$${testcases}\\\"
|
||||
#DEFINES += TESTCASES=\\\"TestJSONRPC\\\"
|
||||
|
||||
system(./generatedefines.sh $${testcases})
|
||||
|
||||
19
tests/auto/generatedefines.sh
Executable file
19
tests/auto/generatedefines.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo generating defines... $@
|
||||
echo \#include \<QMetaType\> > testdefines.h
|
||||
for i in $@; do
|
||||
echo \#include \"${i,,}.h\" >> testdefines.h
|
||||
done
|
||||
|
||||
echo >> testdefines.h
|
||||
|
||||
echo \#define REGISTER_METATYPES \\ >> testdefines.h
|
||||
|
||||
for i in $@; do
|
||||
echo qRegisterMetaType\<$i\>\(\"$i\"\)\; \\ >> testdefines.h
|
||||
done
|
||||
|
||||
echo >> testdefines.h
|
||||
|
||||
echo \#define TESTCASES \"$@\" >> testdefines.h
|
||||
121
tests/auto/guhtestbase.cpp
Normal file
121
tests/auto/guhtestbase.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "guhtestbase.h"
|
||||
#include "mocktcpserver.h"
|
||||
#include "guhcore.h"
|
||||
#include "devicemanager.h"
|
||||
|
||||
#include <QVariantMap>
|
||||
#include <QJsonDocument>
|
||||
#include <QSignalSpy>
|
||||
#include <QSettings>
|
||||
#include <QtTest>
|
||||
#include <QMetaType>
|
||||
#include "testdefines.h"
|
||||
|
||||
Q_IMPORT_PLUGIN(DevicePluginMock)
|
||||
|
||||
GuhTestBase::GuhTestBase(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_commandId(0)
|
||||
{
|
||||
m_mockDevice1Port = 1337;
|
||||
m_mockDevice2Port = 7331;
|
||||
QCoreApplication::instance()->setOrganizationName("guh-test");
|
||||
|
||||
}
|
||||
|
||||
void GuhTestBase::initTestCase()
|
||||
{
|
||||
|
||||
// If testcase asserts cleanup won't do. Lets clear any previous test run settings leftovers
|
||||
QSettings settings;
|
||||
settings.clear();
|
||||
|
||||
GuhCore::instance();
|
||||
|
||||
// Wait for the DeviceManager to signal that it has loaded plugins and everything
|
||||
QSignalSpy spy(GuhCore::instance()->deviceManager(), SIGNAL(loaded()));
|
||||
QVERIFY(spy.isValid());
|
||||
QVERIFY(spy.wait());
|
||||
|
||||
m_mockTcpServer = MockTcpServer::servers().first();
|
||||
m_clientId = QUuid::createUuid();
|
||||
|
||||
// Lets add one instance of the mockdevice
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", "{753f0d32-0468-4d08-82ed-1964aab03298}");
|
||||
QVariantMap deviceParams;
|
||||
deviceParams.insert("httpport", m_mockDevice1Port);
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
|
||||
m_mockDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
QVERIFY2(!m_mockDeviceId.isNull(), "Newly created mock device must not be null.");
|
||||
}
|
||||
|
||||
void GuhTestBase::cleanupTestCase()
|
||||
{
|
||||
GuhCore::instance()->destroy();
|
||||
}
|
||||
|
||||
QVariant GuhTestBase::injectAndWait(const QString &method, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap call;
|
||||
call.insert("id", m_commandId++);
|
||||
call.insert("method", method);
|
||||
call.insert("params", params);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(call);
|
||||
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
||||
|
||||
m_mockTcpServer->injectData(m_clientId, jsonDoc.toJson());
|
||||
|
||||
if (spy.count() == 0) {
|
||||
spy.wait();
|
||||
}
|
||||
|
||||
// Make sure the response it a valid JSON string
|
||||
QJsonParseError error;
|
||||
jsonDoc = QJsonDocument::fromJson(spy.takeFirst().last().toByteArray(), &error);
|
||||
|
||||
return jsonDoc.toVariant();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
REGISTER_METATYPES
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
app.setAttribute(Qt::AA_Use96Dpi, true);
|
||||
bool success = true;
|
||||
qDebug() << "got testcases" << TESTCASES;
|
||||
foreach (const QString &testcase, QString(TESTCASES).split(' ')) {
|
||||
int id = QMetaType::type(testcase.toLatin1().data());
|
||||
if (id != -1) {
|
||||
GuhTestBase *testcase = static_cast<GuhTestBase*>(QMetaType::create(id));
|
||||
success &= QTest::qExec(testcase, argc, argv);
|
||||
delete testcase;
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
64
tests/auto/guhtestbase.h
Normal file
64
tests/auto/guhtestbase.h
Normal file
@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUHTESTBASE_H
|
||||
#define GUHTESTBASE_H
|
||||
|
||||
#include "typeutils.h"
|
||||
#include "mocktcpserver.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
#include <QVariantMap>
|
||||
#include <QtTest>
|
||||
|
||||
extern VendorId guhVendorId;
|
||||
extern DeviceClassId mockDeviceClassId;
|
||||
extern DeviceClassId mockDeviceAutoClassId;
|
||||
extern ActionTypeId mockAction1Id;
|
||||
extern EventTypeId mockEvent1Id;
|
||||
extern StateTypeId mockIntStateId;
|
||||
|
||||
class MockTcpServer;
|
||||
|
||||
class GuhTestBase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuhTestBase(QObject *parent = 0);
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
|
||||
protected:
|
||||
QVariant injectAndWait(const QString &method, const QVariantMap ¶ms = QVariantMap());
|
||||
|
||||
protected:
|
||||
MockTcpServer *m_mockTcpServer;
|
||||
QUuid m_clientId;
|
||||
int m_commandId;
|
||||
|
||||
int m_mockDevice1Port;
|
||||
int m_mockDevice2Port;
|
||||
|
||||
DeviceId m_mockDeviceId;
|
||||
|
||||
};
|
||||
|
||||
#endif // GUHTESTBASE_H
|
||||
156
tests/auto/testdevices.cpp
Normal file
156
tests/auto/testdevices.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#include "testdevices.h"
|
||||
#include "guhcore.h"
|
||||
#include "devicemanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSignalSpy>
|
||||
|
||||
TestDevices::TestDevices(QObject *parent) :
|
||||
GuhTestBase(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void TestDevices::getSupportedVendors()
|
||||
{
|
||||
QVariant supportedVendors = injectAndWait("Devices.GetSupportedVendors");
|
||||
qDebug() << "response" << supportedVendors;
|
||||
|
||||
// Make sure there is exactly 1 supported Vendor named "guh"
|
||||
QVariantList vendorList = supportedVendors.toMap().value("params").toMap().value("vendors").toList();
|
||||
QCOMPARE(vendorList.count(), 1);
|
||||
VendorId vendorId = VendorId(vendorList.first().toMap().value("id").toString());
|
||||
QCOMPARE(vendorId, guhVendorId);
|
||||
}
|
||||
|
||||
void TestDevices::getSupportedDevices_data()
|
||||
{
|
||||
QTest::addColumn<VendorId>("vendorId");
|
||||
QTest::addColumn<int>("resultCount");
|
||||
|
||||
QTest::newRow("vendor guh") << guhVendorId << 2;
|
||||
QTest::newRow("no filter") << VendorId() << 2;
|
||||
QTest::newRow("invalid vendor") << VendorId("93e7d361-8025-4354-b17e-b68406c800bc") << 0;
|
||||
}
|
||||
|
||||
void TestDevices::getSupportedDevices()
|
||||
{
|
||||
QFETCH(VendorId, vendorId);
|
||||
QFETCH(int, resultCount);
|
||||
|
||||
QVariantMap params;
|
||||
if (!vendorId.isNull()) {
|
||||
params.insert("vendorId", vendorId);
|
||||
}
|
||||
QVariant supportedDevices = injectAndWait("Devices.GetSupportedDevices", params);
|
||||
|
||||
// Make sure there is exactly 1 supported device class with the name Mock Wifi Device
|
||||
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), resultCount);
|
||||
if (resultCount > 0) {
|
||||
QString deviceName = supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().first().toMap().value("name").toString();
|
||||
QVERIFY(deviceName.startsWith(QString("Mock Device")));
|
||||
}
|
||||
}
|
||||
|
||||
void TestDevices::addConfiguredDevice_data()
|
||||
{
|
||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||
QTest::addColumn<QVariantMap>("deviceParams");
|
||||
QTest::addColumn<bool>("success");
|
||||
|
||||
QVariantMap deviceParams;
|
||||
deviceParams.insert("httpport", m_mockDevice1Port - 1);
|
||||
QTest::newRow("User, JustAdd") << mockDeviceClassId << deviceParams << true;
|
||||
QTest::newRow("Auto, JustAdd") << mockDeviceAutoClassId << deviceParams << false;
|
||||
}
|
||||
|
||||
void TestDevices::addConfiguredDevice()
|
||||
{
|
||||
QFETCH(DeviceClassId, deviceClassId);
|
||||
QFETCH(QVariantMap, deviceParams);
|
||||
QFETCH(bool, success);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", deviceClassId);
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
qDebug() << "response is" << response;
|
||||
|
||||
QCOMPARE(response.toMap().value("status").toString(), QString("success"));
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), success);
|
||||
|
||||
if (success) {
|
||||
QUuid deviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
params.clear();
|
||||
params.insert("deviceId", deviceId.toString());
|
||||
injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void TestDevices::getConfiguredDevices()
|
||||
{
|
||||
QVariant response = injectAndWait("Devices.GetConfiguredDevices");
|
||||
|
||||
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||
qDebug() << "got devices" << devices;
|
||||
QCOMPARE(devices.count(), 2); // There should be one auto created mock device and the one created in initTestcase()
|
||||
}
|
||||
|
||||
void TestDevices::removeDevice()
|
||||
{
|
||||
QVERIFY(!m_mockDeviceId.isNull());
|
||||
QSettings settings;
|
||||
settings.beginGroup(m_mockDeviceId.toString());
|
||||
// Make sure we have some config values for this device
|
||||
QVERIFY(settings.allKeys().count() > 0);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", m_mockDeviceId);
|
||||
|
||||
QVariant response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
|
||||
// Make sure the device is gone from settings too
|
||||
QCOMPARE(settings.allKeys().count(), 0);
|
||||
}
|
||||
|
||||
void TestDevices::storedDevices()
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", mockDeviceClassId);
|
||||
QVariantMap deviceParams;
|
||||
deviceParams.insert("httpport", 8888);
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
DeviceId addedDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
QVERIFY(!addedDeviceId.isNull());
|
||||
|
||||
// Destroy and recreate the core instance to check if settings are loaded at startup
|
||||
GuhCore::instance()->destroy();
|
||||
QSignalSpy spy(GuhCore::instance()->deviceManager(), SIGNAL(loaded()));
|
||||
spy.wait();
|
||||
m_mockTcpServer = MockTcpServer::servers().first();
|
||||
|
||||
|
||||
response = injectAndWait("Devices.GetConfiguredDevices", QVariantMap());
|
||||
|
||||
foreach (const QVariant device, response.toMap().value("params").toMap().value("devices").toList()) {
|
||||
qDebug() << "found stored device" << device;
|
||||
if (DeviceId(device.toMap().value("id").toString()) == addedDeviceId) {
|
||||
// foreach (const QVariant ¶mVariant, device.toMap().value("params").toList()) {
|
||||
// if ()
|
||||
// }
|
||||
|
||||
qDebug() << "found added device" << device.toMap().value("params").toList().first().toMap();
|
||||
qDebug() << "expected deviceParams:" << deviceParams;
|
||||
QCOMPARE(device.toMap().value("params").toList().first().toMap(), deviceParams);
|
||||
}
|
||||
}
|
||||
|
||||
params.clear();
|
||||
params.insert("deviceId", addedDeviceId);
|
||||
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||
}
|
||||
|
||||
32
tests/auto/testdevices.h
Normal file
32
tests/auto/testdevices.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef TESTDEVICES_H
|
||||
#define TESTDEVICES_H
|
||||
|
||||
#include "guhtestbase.h"
|
||||
|
||||
class TestDevices : public GuhTestBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestDevices(QObject *parent = 0);
|
||||
TestDevices (const TestDevices &other) {}
|
||||
TestDevices& operator=(const TestDevices &other) {}
|
||||
|
||||
private slots:
|
||||
|
||||
void getSupportedVendors();
|
||||
|
||||
void getSupportedDevices_data();
|
||||
void getSupportedDevices();
|
||||
|
||||
void addConfiguredDevice_data();
|
||||
void addConfiguredDevice();
|
||||
|
||||
void getConfiguredDevices();
|
||||
|
||||
void removeDevice();
|
||||
|
||||
void storedDevices();
|
||||
|
||||
};
|
||||
|
||||
#endif // TESTDEVICES_H
|
||||
@ -16,6 +16,8 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "guhtestbase.h"
|
||||
#include "testjsonrpc.h"
|
||||
#include "guhcore.h"
|
||||
#include "devicemanager.h"
|
||||
#include "mocktcpserver.h"
|
||||
@ -27,140 +29,7 @@
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QCoreApplication>
|
||||
|
||||
Q_IMPORT_PLUGIN(DevicePluginMock)
|
||||
|
||||
int mockDevice1Port = 1337;
|
||||
int mockDevice2Port = 7331;
|
||||
|
||||
extern VendorId guhVendorId;
|
||||
extern DeviceClassId mockDeviceClassId;
|
||||
extern DeviceClassId mockDeviceAutoClassId;
|
||||
extern ActionTypeId mockAction1Id;
|
||||
extern EventTypeId mockEvent1Id;
|
||||
extern StateTypeId mockIntStateId;
|
||||
|
||||
class TestJSONRPC: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void initTestcase();
|
||||
void cleanupTestCase();
|
||||
|
||||
void testBasicCall();
|
||||
void version();
|
||||
void introspect();
|
||||
|
||||
void getSupportedVendors();
|
||||
|
||||
void getSupportedDevices_data();
|
||||
void getSupportedDevices();
|
||||
|
||||
void addConfiguredDevice_data();
|
||||
void addConfiguredDevice();
|
||||
|
||||
void getConfiguredDevices();
|
||||
|
||||
void executeAction_data();
|
||||
void executeAction();
|
||||
|
||||
void getActionTypes_data();
|
||||
void getActionTypes();
|
||||
|
||||
void getEventTypes_data();
|
||||
void getEventTypes();
|
||||
|
||||
void getStateTypes_data();
|
||||
void getStateTypes();
|
||||
|
||||
void enableDisableNotifications_data();
|
||||
void enableDisableNotifications();
|
||||
|
||||
void stateChangeEmitsNotifications();
|
||||
|
||||
void removeDevice();
|
||||
|
||||
void storedDevices();
|
||||
|
||||
void getRules();
|
||||
|
||||
void apiChangeBumpsVersion();
|
||||
|
||||
private:
|
||||
QVariant injectAndWait(const QString &method, const QVariantMap ¶ms);
|
||||
QStringList extractRefs(const QVariant &variant);
|
||||
|
||||
private:
|
||||
MockTcpServer *m_mockTcpServer;
|
||||
QUuid m_clientId;
|
||||
int m_commandId;
|
||||
DeviceId m_mockDeviceId;
|
||||
};
|
||||
|
||||
void TestJSONRPC::initTestcase()
|
||||
{
|
||||
QCoreApplication::instance()->setOrganizationName("guh-test");
|
||||
|
||||
// If testcase asserts cleanup won't do. Lets clear any previous test run settings leftovers
|
||||
QSettings settings;
|
||||
settings.clear();
|
||||
|
||||
m_commandId = 0;
|
||||
|
||||
GuhCore::instance();
|
||||
|
||||
// Wait for the DeviceManager to signal that it has loaded plugins and everything
|
||||
QSignalSpy spy(GuhCore::instance()->deviceManager(), SIGNAL(loaded()));
|
||||
QVERIFY(spy.isValid());
|
||||
QVERIFY(spy.wait());
|
||||
|
||||
// If Guh should create more than one TcpServer at some point, this needs to be updated.
|
||||
QCOMPARE(MockTcpServer::servers().count(), 1);
|
||||
m_mockTcpServer = MockTcpServer::servers().first();
|
||||
m_clientId = QUuid::createUuid();
|
||||
|
||||
// Lets add one instance of the mockdevice
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", "{753f0d32-0468-4d08-82ed-1964aab03298}");
|
||||
QVariantMap deviceParams;
|
||||
deviceParams.insert("httpport", mockDevice1Port);
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
|
||||
m_mockDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
QVERIFY2(!m_mockDeviceId.isNull(), "Newly created mock device must not be null.");
|
||||
}
|
||||
|
||||
void TestJSONRPC::cleanupTestCase()
|
||||
{
|
||||
QSettings settings;
|
||||
// settings.clear();
|
||||
}
|
||||
|
||||
QVariant TestJSONRPC::injectAndWait(const QString &method, const QVariantMap ¶ms = QVariantMap())
|
||||
{
|
||||
QVariantMap call;
|
||||
call.insert("id", m_commandId++);
|
||||
call.insert("method", method);
|
||||
call.insert("params", params);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(call);
|
||||
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
||||
|
||||
m_mockTcpServer->injectData(m_clientId, jsonDoc.toJson());
|
||||
|
||||
if (spy.count() == 0) {
|
||||
spy.wait();
|
||||
}
|
||||
|
||||
// Make sure the response it a valid JSON string
|
||||
QJsonParseError error;
|
||||
jsonDoc = QJsonDocument::fromJson(spy.takeFirst().last().toByteArray(), &error);
|
||||
|
||||
return jsonDoc.toVariant();
|
||||
}
|
||||
#include <QMetaType>
|
||||
|
||||
QStringList TestJSONRPC::extractRefs(const QVariant &variant)
|
||||
{
|
||||
@ -212,17 +81,6 @@ void TestJSONRPC::testBasicCall()
|
||||
QCOMPARE(jsonDoc.toVariant().toMap().value("id").toInt(), 42);
|
||||
}
|
||||
|
||||
void TestJSONRPC::version()
|
||||
{
|
||||
QVariant response = injectAndWait("JSONRPC.Version");
|
||||
|
||||
QString version = response.toMap().value("params").toMap().value("version").toString();
|
||||
qDebug() << "Got version:" << version << "( Expected:" << GUH_VERSION_STRING << ")";
|
||||
|
||||
QVERIFY2(!version.isEmpty(), "Version is empty.");
|
||||
QCOMPARE(version, QString(GUH_VERSION_STRING));
|
||||
}
|
||||
|
||||
void TestJSONRPC::introspect()
|
||||
{
|
||||
QVariant response = injectAndWait("JSONRPC.Introspect");
|
||||
@ -245,92 +103,6 @@ void TestJSONRPC::introspect()
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::getSupportedVendors()
|
||||
{
|
||||
QVariant supportedVendors = injectAndWait("Devices.GetSupportedVendors");
|
||||
qDebug() << "response" << supportedVendors;
|
||||
|
||||
// Make sure there is exactly 1 supported Vendor named "guh"
|
||||
QVariantList vendorList = supportedVendors.toMap().value("params").toMap().value("vendors").toList();
|
||||
QCOMPARE(vendorList.count(), 1);
|
||||
VendorId vendorId = VendorId(vendorList.first().toMap().value("id").toString());
|
||||
QCOMPARE(vendorId, guhVendorId);
|
||||
}
|
||||
|
||||
void TestJSONRPC::getSupportedDevices_data()
|
||||
{
|
||||
QTest::addColumn<VendorId>("vendorId");
|
||||
QTest::addColumn<int>("resultCount");
|
||||
|
||||
QTest::newRow("vendor guh") << guhVendorId << 2;
|
||||
QTest::newRow("no filter") << VendorId() << 2;
|
||||
QTest::newRow("invalid vendor") << VendorId("93e7d361-8025-4354-b17e-b68406c800bc") << 0;
|
||||
}
|
||||
|
||||
void TestJSONRPC::getSupportedDevices()
|
||||
{
|
||||
QFETCH(VendorId, vendorId);
|
||||
QFETCH(int, resultCount);
|
||||
|
||||
QVariantMap params;
|
||||
if (!vendorId.isNull()) {
|
||||
params.insert("vendorId", vendorId);
|
||||
}
|
||||
QVariant supportedDevices = injectAndWait("Devices.GetSupportedDevices", params);
|
||||
|
||||
// Make sure there is exactly 1 supported device class with the name Mock Wifi Device
|
||||
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), resultCount);
|
||||
if (resultCount > 0) {
|
||||
QString deviceName = supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().first().toMap().value("name").toString();
|
||||
QVERIFY(deviceName.startsWith(QString("Mock Device")));
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::addConfiguredDevice_data()
|
||||
{
|
||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||
QTest::addColumn<QVariantMap>("deviceParams");
|
||||
QTest::addColumn<bool>("success");
|
||||
|
||||
QVariantMap deviceParams;
|
||||
deviceParams.insert("httpport", mockDevice1Port - 1);
|
||||
QTest::newRow("User, JustAdd") << mockDeviceClassId << deviceParams << true;
|
||||
QTest::newRow("Auto, JustAdd") << mockDeviceAutoClassId << deviceParams << false;
|
||||
}
|
||||
|
||||
void TestJSONRPC::addConfiguredDevice()
|
||||
{
|
||||
QFETCH(DeviceClassId, deviceClassId);
|
||||
QFETCH(QVariantMap, deviceParams);
|
||||
QFETCH(bool, success);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", deviceClassId);
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
qDebug() << "response is" << response;
|
||||
|
||||
QCOMPARE(response.toMap().value("status").toString(), QString("success"));
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), success);
|
||||
|
||||
if (success) {
|
||||
QUuid deviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
params.clear();
|
||||
params.insert("deviceId", deviceId.toString());
|
||||
injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::getConfiguredDevices()
|
||||
{
|
||||
QVariant response = injectAndWait("Devices.GetConfiguredDevices");
|
||||
|
||||
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||
qDebug() << "got devices" << devices;
|
||||
QCOMPARE(devices.count(), 2); // There should be one auto created mock device and the one created in initTestcase()
|
||||
}
|
||||
|
||||
void TestJSONRPC::executeAction_data()
|
||||
{
|
||||
QTest::addColumn<DeviceId>("deviceId");
|
||||
@ -363,13 +135,14 @@ void TestJSONRPC::executeAction()
|
||||
params.insert("deviceId", deviceId);
|
||||
params.insert("params", actionParams);
|
||||
QVariant response = injectAndWait("Actions.ExecuteAction", params);
|
||||
qDebug() << "executeActionresponse" << response;
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), success);
|
||||
|
||||
// Fetch action execution history from mock device
|
||||
QNetworkAccessManager nam;
|
||||
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(mockDevice1Port)));
|
||||
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port)));
|
||||
QNetworkReply *reply = nam.get(request);
|
||||
spy.wait();
|
||||
QCOMPARE(spy.count(), 1);
|
||||
@ -383,7 +156,7 @@ void TestJSONRPC::executeAction()
|
||||
|
||||
// cleanup for the next run
|
||||
spy.clear();
|
||||
request.setUrl(QUrl(QString("http://localhost:%1/clearactionhistory").arg(mockDevice1Port)));
|
||||
request.setUrl(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port)));
|
||||
reply = nam.get(request);
|
||||
spy.wait();
|
||||
QCOMPARE(spy.count(), 1);
|
||||
@ -502,7 +275,7 @@ void TestJSONRPC::stateChangeEmitsNotifications()
|
||||
// trigger state change in mock device
|
||||
int newVal = 1111;
|
||||
QUuid stateTypeId("80baec19-54de-4948-ac46-31eabfaceb83");
|
||||
QNetworkRequest request(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(mockDevice1Port).arg(stateTypeId.toString()).arg(newVal)));
|
||||
QNetworkRequest request(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(stateTypeId.toString()).arg(newVal)));
|
||||
QNetworkReply *reply = nam.get(request);
|
||||
reply->deleteLater();
|
||||
|
||||
@ -525,7 +298,7 @@ void TestJSONRPC::stateChangeEmitsNotifications()
|
||||
// Fire the a statechange once again
|
||||
clientSpy.clear();
|
||||
newVal = 42;
|
||||
request.setUrl(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(mockDevice1Port).arg(stateTypeId.toString()).arg(newVal)));
|
||||
request.setUrl(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(stateTypeId.toString()).arg(newVal)));
|
||||
reply = nam.get(request);
|
||||
reply->deleteLater();
|
||||
|
||||
@ -544,117 +317,8 @@ void TestJSONRPC::stateChangeEmitsNotifications()
|
||||
|
||||
}
|
||||
|
||||
void TestJSONRPC::removeDevice()
|
||||
{
|
||||
QVERIFY(!m_mockDeviceId.isNull());
|
||||
QSettings settings;
|
||||
settings.beginGroup(m_mockDeviceId.toString());
|
||||
// Make sure we have some config values for this device
|
||||
QVERIFY(settings.allKeys().count() > 0);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", m_mockDeviceId);
|
||||
|
||||
QVariant response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
|
||||
// Make sure the device is gone from settings too
|
||||
QCOMPARE(settings.allKeys().count(), 0);
|
||||
}
|
||||
|
||||
void TestJSONRPC::storedDevices()
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", mockDeviceClassId);
|
||||
QVariantMap deviceParams;
|
||||
deviceParams.insert("httpport", 8888);
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
DeviceId addedDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
QVERIFY(!addedDeviceId.isNull());
|
||||
|
||||
// Destroy and recreate the core instance to check if settings are loaded at startup
|
||||
GuhCore::instance()->destroy();
|
||||
QSignalSpy spy(GuhCore::instance()->deviceManager(), SIGNAL(loaded()));
|
||||
spy.wait();
|
||||
m_mockTcpServer = MockTcpServer::servers().first();
|
||||
|
||||
|
||||
response = injectAndWait("Devices.GetConfiguredDevices", QVariantMap());
|
||||
|
||||
foreach (const QVariant device, response.toMap().value("params").toMap().value("devices").toList()) {
|
||||
qDebug() << "found stored device" << device;
|
||||
if (DeviceId(device.toMap().value("id").toString()) == addedDeviceId) {
|
||||
// foreach (const QVariant ¶mVariant, device.toMap().value("params").toList()) {
|
||||
// if ()
|
||||
// }
|
||||
|
||||
qDebug() << "found added device" << device.toMap().value("params").toList().first().toMap();
|
||||
qDebug() << "expected deviceParams:" << deviceParams;
|
||||
QCOMPARE(device.toMap().value("params").toList().first().toMap(), deviceParams);
|
||||
}
|
||||
}
|
||||
|
||||
params.clear();
|
||||
params.insert("deviceId", addedDeviceId);
|
||||
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||
}
|
||||
|
||||
void TestJSONRPC::getRules()
|
||||
{
|
||||
QVariant response = injectAndWait("Rules.GetRules", QVariantMap());
|
||||
qDebug() << "got rules response" << response;
|
||||
}
|
||||
|
||||
void TestJSONRPC::apiChangeBumpsVersion()
|
||||
{
|
||||
QString oldFilePath = QString(TESTS_SOURCE_DIR) + "/api.json";
|
||||
QString newFilePath = QString(TESTS_SOURCE_DIR) + "/api.json.new";
|
||||
|
||||
QVariant response = injectAndWait("JSONRPC.Version", QVariantMap());
|
||||
QByteArray newVersion = response.toMap().value("params").toMap().value("version").toByteArray();
|
||||
|
||||
response = injectAndWait("JSONRPC.Introspect", QVariantMap());
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(response.toMap().value("params"));
|
||||
QByteArray newApi = jsonDoc.toJson();
|
||||
|
||||
|
||||
QFile oldApiFile(oldFilePath);
|
||||
QVERIFY(oldApiFile.exists() && oldApiFile.open(QIODevice::ReadOnly));
|
||||
|
||||
QByteArray oldVersion = oldApiFile.readLine().trimmed();
|
||||
QByteArray oldApi = oldApiFile.readAll();
|
||||
|
||||
qDebug() << "version" << oldVersion << newVersion;
|
||||
|
||||
if (oldVersion == newVersion && oldApi == newApi) {
|
||||
// All fine. no changes
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldVersion == newVersion && oldApi != newApi) {
|
||||
QVERIFY2(false, "JSONRPC API has changed but version is still the same. You need to bump the API version.");
|
||||
}
|
||||
|
||||
QFile newApiFile(newFilePath);
|
||||
QVERIFY(newApiFile.open(QIODevice::ReadWrite));
|
||||
if (newApiFile.size() > 0) {
|
||||
newApiFile.resize(0);
|
||||
}
|
||||
|
||||
newApiFile.write(newVersion + '\n');
|
||||
newApiFile.write(newApi);
|
||||
newApiFile.flush();
|
||||
|
||||
QProcess p;
|
||||
p.execute("diff", QStringList() << "-u" << oldFilePath << newFilePath);
|
||||
p.waitForFinished();
|
||||
qDebug() << p.readAll();
|
||||
|
||||
QVERIFY2(false, QString("JSONRPC API has changed. Update %1.").arg(oldFilePath).toLatin1().data());
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestJSONRPC)
|
||||
#include "testjsonrpc.moc"
|
||||
|
||||
43
tests/auto/testjsonrpc.h
Normal file
43
tests/auto/testjsonrpc.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef TESTJSONRPC_H
|
||||
#define TESTJSONRPC_H
|
||||
|
||||
#include "guhtestbase.h"
|
||||
|
||||
class TestJSONRPC: public GuhTestBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestJSONRPC(QObject *parent=0): GuhTestBase(parent) {}
|
||||
TestJSONRPC (const TestJSONRPC &other) {}
|
||||
TestJSONRPC& operator=(const TestJSONRPC &other) {}
|
||||
|
||||
private slots:
|
||||
void testBasicCall();
|
||||
void introspect();
|
||||
|
||||
void executeAction_data();
|
||||
void executeAction();
|
||||
|
||||
void getActionTypes_data();
|
||||
void getActionTypes();
|
||||
|
||||
void getEventTypes_data();
|
||||
void getEventTypes();
|
||||
|
||||
void getStateTypes_data();
|
||||
void getStateTypes();
|
||||
|
||||
void enableDisableNotifications_data();
|
||||
void enableDisableNotifications();
|
||||
|
||||
void stateChangeEmitsNotifications();
|
||||
|
||||
void getRules();
|
||||
|
||||
private:
|
||||
QStringList extractRefs(const QVariant &variant);
|
||||
|
||||
};
|
||||
Q_DECLARE_METATYPE(TestJSONRPC)
|
||||
|
||||
#endif
|
||||
89
tests/auto/testversioning.cpp
Normal file
89
tests/auto/testversioning.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/****************************************************************************
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "testversioning.h"
|
||||
#include "guhcore.h"
|
||||
#include "devicemanager.h"
|
||||
#include "mocktcpserver.h"
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QCoreApplication>
|
||||
#include <QTcpSocket>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QCoreApplication>
|
||||
|
||||
void TestVersioning::version()
|
||||
{
|
||||
QVariant response = injectAndWait("JSONRPC.Version");
|
||||
|
||||
QString version = response.toMap().value("params").toMap().value("version").toString();
|
||||
qDebug() << "Got version:" << version << "( Expected:" << GUH_VERSION_STRING << ")";
|
||||
|
||||
QVERIFY2(!version.isEmpty(), "Version is empty.");
|
||||
QCOMPARE(version, QString(GUH_VERSION_STRING));
|
||||
}
|
||||
|
||||
void TestVersioning::apiChangeBumpsVersion()
|
||||
{
|
||||
QString oldFilePath = QString(TESTS_SOURCE_DIR) + "/api.json";
|
||||
QString newFilePath = QString(TESTS_SOURCE_DIR) + "/api.json.new";
|
||||
|
||||
QVariant response = injectAndWait("JSONRPC.Version", QVariantMap());
|
||||
QByteArray newVersion = response.toMap().value("params").toMap().value("version").toByteArray();
|
||||
|
||||
response = injectAndWait("JSONRPC.Introspect", QVariantMap());
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(response.toMap().value("params"));
|
||||
QByteArray newApi = jsonDoc.toJson();
|
||||
|
||||
|
||||
QFile oldApiFile(oldFilePath);
|
||||
QVERIFY(oldApiFile.exists() && oldApiFile.open(QIODevice::ReadOnly));
|
||||
|
||||
QByteArray oldVersion = oldApiFile.readLine().trimmed();
|
||||
QByteArray oldApi = oldApiFile.readAll();
|
||||
|
||||
qDebug() << "version" << oldVersion << newVersion;
|
||||
|
||||
if (oldVersion == newVersion && oldApi == newApi) {
|
||||
// All fine. no changes
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldVersion == newVersion && oldApi != newApi) {
|
||||
QVERIFY2(false, "JSONRPC API has changed but version is still the same. You need to bump the API version.");
|
||||
}
|
||||
|
||||
QFile newApiFile(newFilePath);
|
||||
QVERIFY(newApiFile.open(QIODevice::ReadWrite));
|
||||
if (newApiFile.size() > 0) {
|
||||
newApiFile.resize(0);
|
||||
}
|
||||
|
||||
newApiFile.write(newVersion + '\n');
|
||||
newApiFile.write(newApi);
|
||||
newApiFile.flush();
|
||||
|
||||
QProcess p;
|
||||
p.execute("diff", QStringList() << "-u" << oldFilePath << newFilePath);
|
||||
p.waitForFinished();
|
||||
qDebug() << p.readAll();
|
||||
|
||||
QVERIFY2(false, QString("JSONRPC API has changed. Update %1.").arg(oldFilePath).toLatin1().data());
|
||||
}
|
||||
20
tests/auto/testversioning.h
Normal file
20
tests/auto/testversioning.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef TESTVERSIONING_H
|
||||
#define TESTVERSIONING_H
|
||||
|
||||
#include "guhtestbase.h"
|
||||
|
||||
class TestVersioning: public GuhTestBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestVersioning () {}
|
||||
TestVersioning (const TestVersioning &other) {}
|
||||
TestVersioning& operator=(const TestVersioning &other) {}
|
||||
|
||||
private slots:
|
||||
void version();
|
||||
void apiChangeBumpsVersion();
|
||||
};
|
||||
Q_DECLARE_METATYPE(TestVersioning);
|
||||
|
||||
#endif //TESTVERSIONING_H
|
||||
Reference in New Issue
Block a user