mirror of https://github.com/nymea/nymea.git
add websocket tests
bump guh version add websockets as reccommended dependencypull/135/head
parent
d322699152
commit
214cbb7f3e
|
|
@ -9,8 +9,8 @@ https=false
|
|||
publicFolder=/usr/share/guh-webinterface/public
|
||||
|
||||
[WebSocketServer]
|
||||
port=4444
|
||||
https=false
|
||||
port=4444
|
||||
|
||||
[SSL-Configuration]
|
||||
certificate=/etc/ssl/certs/guhd-certificate.crt
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
* Add webserver and REST API
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ Depends: libqt5network5,
|
|||
libguh1 (= ${binary:Version}),
|
||||
${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
Recommends:
|
||||
libqt5websockets5
|
||||
Description: Server daemon for home automation systems
|
||||
guh is an open source home automation server, which allows to control
|
||||
a lot of different devices from many different manufacturers. With the
|
||||
|
|
|
|||
2
guh.pri
2
guh.pri
|
|
@ -26,7 +26,7 @@ enable433gpio {
|
|||
DEFINES += GPIO433
|
||||
}
|
||||
|
||||
# check webserver support
|
||||
# check websocket support
|
||||
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) {
|
||||
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(clientDisconnected(const QUuid &)), this, SLOT(clientDisconnected(const QUuid &)));
|
||||
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);
|
||||
#else
|
||||
Q_UNUSED(sslConfiguration)
|
||||
|
|
|
|||
|
|
@ -43,15 +43,22 @@ class TestWebSocketServer: public GuhTestBase
|
|||
|
||||
private slots:
|
||||
#ifdef WEBSOCKET
|
||||
|
||||
void testHandshake();
|
||||
|
||||
void pingTest();
|
||||
|
||||
void introspect();
|
||||
#endif
|
||||
private:
|
||||
void testBasicCall_data();
|
||||
void testBasicCall();
|
||||
|
||||
void introspect();
|
||||
|
||||
private:
|
||||
int m_socketCommandId;
|
||||
|
||||
QVariant injectSocketAndWait(const QString &method, const QVariantMap ¶ms = QVariantMap());
|
||||
QVariant injectSocketData(const QByteArray &data);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef WEBSOCKET
|
||||
|
|
@ -88,11 +95,127 @@ void TestWebSocketServer::pingTest()
|
|||
spyPong.wait();
|
||||
QVERIFY2(spyPong.count() > 0, "no pong");
|
||||
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()
|
||||
{
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue