add websocket tests
bump guh version add websockets as reccommended dependency
This commit is contained in:
parent
d322699152
commit
214cbb7f3e
@ -9,8 +9,8 @@ https=false
|
|||||||
publicFolder=/usr/share/guh-webinterface/public
|
publicFolder=/usr/share/guh-webinterface/public
|
||||||
|
|
||||||
[WebSocketServer]
|
[WebSocketServer]
|
||||||
port=4444
|
|
||||||
https=false
|
https=false
|
||||||
|
port=4444
|
||||||
|
|
||||||
[SSL-Configuration]
|
[SSL-Configuration]
|
||||||
certificate=/etc/ssl/certs/guhd-certificate.crt
|
certificate=/etc/ssl/certs/guhd-certificate.crt
|
||||||
|
|||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
|||||||
|
guh (0.6.0) vivid; urgency=medium
|
||||||
|
|
||||||
|
* Add websocket server
|
||||||
|
|
||||||
|
-- Simon Stürz <simon.stuerz@guh.guru> Sat, 04 Aug 2015 16:13:43 +0200
|
||||||
|
|
||||||
guh (0.5.0) vivid; urgency=medium
|
guh (0.5.0) vivid; urgency=medium
|
||||||
|
|
||||||
* Add webserver and REST API
|
* Add webserver and REST API
|
||||||
|
|||||||
2
debian/control
vendored
2
debian/control
vendored
@ -30,6 +30,8 @@ Depends: libqt5network5,
|
|||||||
libguh1 (= ${binary:Version}),
|
libguh1 (= ${binary:Version}),
|
||||||
${shlibs:Depends},
|
${shlibs:Depends},
|
||||||
${misc:Depends}
|
${misc:Depends}
|
||||||
|
Recommends:
|
||||||
|
libqt5websockets5
|
||||||
Description: Server daemon for home automation systems
|
Description: Server daemon for home automation systems
|
||||||
guh is an open source home automation server, which allows to control
|
guh is an open source home automation server, which allows to control
|
||||||
a lot of different devices from many different manufacturers. With the
|
a lot of different devices from many different manufacturers. With the
|
||||||
|
|||||||
2
guh.pri
2
guh.pri
@ -26,7 +26,7 @@ enable433gpio {
|
|||||||
DEFINES += GPIO433
|
DEFINES += GPIO433
|
||||||
}
|
}
|
||||||
|
|
||||||
# check webserver support
|
# check websocket support
|
||||||
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) {
|
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) {
|
||||||
DEFINES += WEBSOCKET
|
DEFINES += WEBSOCKET
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,8 +104,8 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
|
|||||||
connect(m_websocketServer, SIGNAL(clientConnected(const QUuid &)), this, SLOT(clientConnected(const QUuid &)));
|
connect(m_websocketServer, SIGNAL(clientConnected(const QUuid &)), this, SLOT(clientConnected(const QUuid &)));
|
||||||
connect(m_websocketServer, SIGNAL(clientDisconnected(const QUuid &)), this, SLOT(clientDisconnected(const QUuid &)));
|
connect(m_websocketServer, SIGNAL(clientDisconnected(const QUuid &)), this, SLOT(clientDisconnected(const QUuid &)));
|
||||||
connect(m_websocketServer, SIGNAL(dataAvailable(QUuid, QString, QString, QVariantMap)), this, SLOT(processData(QUuid, QString, QString, QVariantMap)));
|
connect(m_websocketServer, SIGNAL(dataAvailable(QUuid, QString, QString, QVariantMap)), this, SLOT(processData(QUuid, QString, QString, QVariantMap)));
|
||||||
m_websocketServer->startServer();
|
|
||||||
|
|
||||||
|
m_websocketServer->startServer();
|
||||||
m_interfaces.append(m_websocketServer);
|
m_interfaces.append(m_websocketServer);
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(sslConfiguration)
|
Q_UNUSED(sslConfiguration)
|
||||||
|
|||||||
@ -43,15 +43,22 @@ class TestWebSocketServer: public GuhTestBase
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
#ifdef WEBSOCKET
|
#ifdef WEBSOCKET
|
||||||
|
|
||||||
void testHandshake();
|
void testHandshake();
|
||||||
|
|
||||||
void pingTest();
|
void pingTest();
|
||||||
|
|
||||||
void introspect();
|
void testBasicCall_data();
|
||||||
#endif
|
void testBasicCall();
|
||||||
private:
|
|
||||||
|
|
||||||
|
void introspect();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_socketCommandId;
|
||||||
|
|
||||||
|
QVariant injectSocketAndWait(const QString &method, const QVariantMap ¶ms = QVariantMap());
|
||||||
|
QVariant injectSocketData(const QByteArray &data);
|
||||||
|
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WEBSOCKET
|
#ifdef WEBSOCKET
|
||||||
@ -88,11 +95,127 @@ void TestWebSocketServer::pingTest()
|
|||||||
spyPong.wait();
|
spyPong.wait();
|
||||||
QVERIFY2(spyPong.count() > 0, "no pong");
|
QVERIFY2(spyPong.count() > 0, "no pong");
|
||||||
qDebug() << "ping response" << spyPong.first().at(0) << spyPong.first().at(1).toString();
|
qDebug() << "ping response" << spyPong.first().at(0) << spyPong.first().at(1).toString();
|
||||||
|
socket->close();
|
||||||
|
socket->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TestWebSocketServer::testBasicCall_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QByteArray>("data");
|
||||||
|
QTest::addColumn<bool>("valid");
|
||||||
|
|
||||||
|
QTest::newRow("valid call") << QByteArray("{\"id\":42, \"method\":\"JSONRPC.Introspect\"}") << true;
|
||||||
|
QTest::newRow("missing id") << QByteArray("{\"method\":\"JSONRPC.Introspect\"}")<< false;
|
||||||
|
QTest::newRow("missing method") << QByteArray("{\"id\":42}") << false;
|
||||||
|
QTest::newRow("borked") << QByteArray("{\"id\":42, \"method\":\"JSO")<< false;
|
||||||
|
QTest::newRow("invalid function") << QByteArray("{\"id\":42, \"method\":\"JSONRPC.Foobar\"}") << false;
|
||||||
|
QTest::newRow("invalid namespace") << QByteArray("{\"id\":42, \"method\":\"FOO.Introspect\"}") << false;
|
||||||
|
QTest::newRow("missing dot") << QByteArray("{\"id\":42, \"method\":\"JSONRPCIntrospect\"}") << false;
|
||||||
|
QTest::newRow("invalid params") << QByteArray("{\"id\":42, \"method\":\"JSONRPC.Introspect\", \"params\":{\"törööö\":\"chooo-chooo\"}}") << false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestWebSocketServer::testBasicCall()
|
||||||
|
{
|
||||||
|
QFETCH(QByteArray, data);
|
||||||
|
QFETCH(bool, valid);
|
||||||
|
|
||||||
|
QVariant response = injectSocketData(data);
|
||||||
|
if (valid)
|
||||||
|
QVERIFY2(response.toMap().value("status").toString() == "success", "Call wasn't parsed correctly by guh.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TestWebSocketServer::introspect()
|
void TestWebSocketServer::introspect()
|
||||||
{
|
{
|
||||||
|
QVariant response = injectSocketAndWait("JSONRPC.Introspect");
|
||||||
|
|
||||||
|
QVariantMap methods = response.toMap().value("params").toMap().value("methods").toMap();
|
||||||
|
QVariantMap notifications = response.toMap().value("params").toMap().value("notifications").toMap();
|
||||||
|
QVariantMap types = response.toMap().value("params").toMap().value("types").toMap();
|
||||||
|
|
||||||
|
QVERIFY2(methods.count() > 0, "No methods in Introspect response!");
|
||||||
|
QVERIFY2(notifications.count() > 0, "No notifications in Introspect response!");
|
||||||
|
QVERIFY2(types.count() > 0, "No types in Introspect response!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TestWebSocketServer::injectSocketAndWait(const QString &method, const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
|
||||||
|
QVariantMap call;
|
||||||
|
call.insert("id", m_socketCommandId);
|
||||||
|
call.insert("method", method);
|
||||||
|
call.insert("params", params);
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(call);
|
||||||
|
|
||||||
|
QWebSocket *socket = new QWebSocket("guh tests", QWebSocketProtocol::Version13);
|
||||||
|
QSignalSpy spyConnection(socket, SIGNAL(connected()));
|
||||||
|
socket->open(QUrl(QStringLiteral("ws://localhost:4444")));
|
||||||
|
spyConnection.wait();
|
||||||
|
if (spyConnection.count() == 0) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSignalSpy spy(socket, SIGNAL(textMessageReceived(QString)));
|
||||||
|
socket->sendTextMessage(QString(jsonDoc.toJson()));
|
||||||
|
spy.wait();
|
||||||
|
|
||||||
|
socket->close();
|
||||||
|
socket->deleteLater();
|
||||||
|
|
||||||
|
for (int i = 0; i < spy.count(); i++) {
|
||||||
|
// Make sure the response it a valid JSON string
|
||||||
|
QJsonParseError error;
|
||||||
|
jsonDoc = QJsonDocument::fromJson(spy.at(i).last().toByteArray(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "JSON parser error" << error.errorString();
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||||
|
|
||||||
|
// skip notifications
|
||||||
|
if (response.contains("notification"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (response.value("id").toInt() == m_socketCommandId) {
|
||||||
|
m_socketCommandId++;
|
||||||
|
return jsonDoc.toVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_socketCommandId++;
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TestWebSocketServer::injectSocketData(const QByteArray &data)
|
||||||
|
{
|
||||||
|
QWebSocket *socket = new QWebSocket("guh tests", QWebSocketProtocol::Version13);
|
||||||
|
QSignalSpy spyConnection(socket, SIGNAL(connected()));
|
||||||
|
socket->open(QUrl(QStringLiteral("ws://localhost:4444")));
|
||||||
|
spyConnection.wait();
|
||||||
|
if (spyConnection.count() == 0) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSignalSpy spy(socket, SIGNAL(textMessageReceived(QString)));
|
||||||
|
socket->sendTextMessage(QString(data));
|
||||||
|
spy.wait();
|
||||||
|
|
||||||
|
socket->close();
|
||||||
|
socket->deleteLater();
|
||||||
|
|
||||||
|
for (int i = 0; i < spy.count(); i++) {
|
||||||
|
// Make sure the response it a valid JSON string
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(spy.at(i).last().toByteArray(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "JSON parser error" << error.errorString();
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
return jsonDoc.toVariant();
|
||||||
|
}
|
||||||
|
m_socketCommandId++;
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user