Add coverage report support

This commit is contained in:
Simon Stürz 2018-08-06 17:51:46 +02:00
parent 538cb3d799
commit f20173df9f
11 changed files with 206 additions and 32 deletions

1
.gitignore vendored
View File

@ -71,3 +71,4 @@ Thumbs.db
*.dll
*.exe
coverage-html

View File

@ -40,6 +40,18 @@ In order to run the test, you can call `make check` in the build directory or ru
$ nymea-remoteproxy-tests
## Test coverage report
If you want to create a line coverage report from the tests simply run following command in the source directory:
$ apt install lcov
$ ./create-coverage-html.sh
The resulting coverage report will be place in the `coverage-html` directory.
# Usage
In order to get information about the server you can start the command with the `--help` parameter.

16
create-coverage-html.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
# Export the library path for now
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/libnymea-remoteproxy:$(pwd)/libnymea-remoteproxyclient
# Build
qmake CONFIG+=coverage
make -j$(nproc)
make coverage-html
# Clean up source directory
rm -v libnymea-remoteproxy/libnymea-remoteproxy.so*
rm -v libnymea-remoteproxyclient/libnymea-remoteproxyclient.so*
rm -v server/nymea-remoteproxy
rm -v tests/nymea-remoteproxy-tests
make clean

View File

@ -45,7 +45,8 @@ JsonReply *AuthenticationHandler::Authenticate(const QVariantMap &params, const
void AuthenticationHandler::onAuthenticationFinished()
{
AuthenticationReply *authReply = static_cast<AuthenticationReply *>(sender());
JsonReply *jsonReply = m_runningAuthentications.value(authReply);
//AuthenticationReply *authReply = static_cast<AuthenticationReply *>(sender());
//JsonReply *jsonReply = m_runningAuthentications.take(authReply);
//emit asyncReply()
}

View File

@ -155,3 +155,19 @@ void JsonRpcServer::setup()
registerHandler(new AuthenticationHandler(this));
}
void JsonRpcServer::clientConnected(const QUuid &clientId)
{
Q_UNUSED(clientId)
}
void JsonRpcServer::clientDisconnected(const QUuid &clientId)
{
Q_UNUSED(clientId)
}
void JsonRpcServer::processData(const QUuid &clientId, const QByteArray &data)
{
Q_UNUSED(clientId)
Q_UNUSED(data)
}

View File

@ -46,8 +46,8 @@ private slots:
void clientConnected(const QUuid &clientId);
void clientDisconnected(const QUuid &clientId);
void processData(const QUuid &clientId, const QByteArray &data);
void sendNotification(const QVariantMap &params);
void asyncReplyFinished();
// void sendNotification(const QVariantMap &params);
// void asyncReplyFinished();
};

View File

@ -127,13 +127,13 @@ void WebSocketServer::onPing(quint64 elapsedTime, const QByteArray &payload)
bool WebSocketServer::startServer()
{
m_server = new QWebSocketServer(QCoreApplication::applicationName(), QWebSocketServer::SecureMode, this);
m_server->setSslConfiguration(m_sslConfiguration);
m_server->setSslConfiguration(sslConfiguration());
connect (m_server, &QWebSocketServer::newConnection, this, &WebSocketServer::onClientConnected);
connect (m_server, &QWebSocketServer::acceptError, this, &WebSocketServer::onServerError);
qCDebug(dcWebSocketServer()) << "Starting server" << m_server->serverName() << m_serverUrl.toString();
if (!m_server->listen(QHostAddress(m_serverUrl.host()), static_cast<quint16>(m_serverUrl.port()))) {
qCDebug(dcWebSocketServer()) << "Starting server" << m_server->serverName() << serverUrl().toString();
if (!m_server->listen(QHostAddress(m_serverUrl.host()), static_cast<quint16>(serverUrl().port()))) {
qCWarning(dcWebSocketServer()) << "Server" << m_server->serverName() << "could not listen on" << serverUrl().toString();
return false;
}
@ -151,7 +151,7 @@ bool WebSocketServer::stopServer()
// Delete the server object
if (m_server) {
qCDebug(dcWebSocketServer()) << "Stop server" << m_server->serverName() << m_serverUrl.toString();
qCDebug(dcWebSocketServer()) << "Stop server" << m_server->serverName() << serverUrl().toString();
m_server->close();
delete m_server;
m_server = nullptr;

View File

@ -13,3 +13,54 @@ QMAKE_LFLAGS *= -std=c++11
top_srcdir=$$PWD
top_builddir=$$shadowed($$PWD)
coverage {
message("Building with coverage report")
# Note: this works only if you build in the source dir
OBJECTS_DIR =
MOC_DIR =
LIBS += -lgcov
QMAKE_CXXFLAGS += --coverage
QMAKE_LDFLAGS += --coverage
QMAKE_EXTRA_TARGETS += coverage cov
QMAKE_EXTRA_TARGETS += clean-gcno clean-gcda coverage-html \
generate-coverage-html clean-coverage-html coverage-gcovr \
generate-gcovr generate-coverage-gcovr clean-coverage-gcovr
clean-gcno.commands = \
"@echo Removing old coverage instrumentation"; \
"find -name '*.gcno' -print | xargs -r rm"
clean-gcda.commands = \
"@echo Removing old coverage results"; \
"find -name '*.gcda' -print | xargs -r rm"
coverage-html.depends = clean-gcda check generate-coverage-html
generate-coverage-html.commands = \
"@echo Collecting coverage data"; \
"lcov --directory $${top_srcdir} --capture --output-file coverage.info --no-checksum --compat-libtool"; \
"lcov --extract coverage.info \"*/server/*.cpp\" --extract coverage.info \"*/libnymea-remoteproxy/*.cpp\" --extract coverage.info \"*/libnymea-remoteproxyclient/*.cpp\" -o coverage.info"; \
"lcov --remove coverage.info \"moc_*.cpp\" --remove coverage.info \"*/test/*\" -o coverage.info"; \
"LANG=C genhtml --prefix $${top_srcdir} --output-directory coverage-html --title \"nymea-remoteproxy coverage\" --legend --show-details coverage.info"
clean-coverage-html.depends = clean-gcda
clean-coverage-html.commands = \
"lcov --directory $${top_srcdir} -z"; \
"rm -rf coverage.info coverage-html"
coverage-gcovr.depends = clean-gcda check generate-coverage-gcovr
generate-coverage-gcovr.commands = \
"@echo Generating coverage GCOVR report"; \
"gcovr -x -r $${top_srcdir} -o $${top_srcdir}/coverage.xml -e \".*/moc_.*\" -e \"tests/.*\" -e \".*\\.h\""
clean-coverage-gcovr.depends = clean-gcda
clean-coverage-gcovr.commands = \
"rm -rf $${top_srcdir}/coverage.xml"
QMAKE_CLEAN += *.gcda *.gcno coverage.info coverage.xml
}

View File

@ -5,4 +5,3 @@ SUBDIRS += server libnymea-remoteproxy libnymea-remoteproxyclient tests
server.depends = libnymea-remoteproxy
tests.depends = libnymea-remoteproxy libnymea-remoteproxyclient

View File

@ -6,6 +6,8 @@
#include <QMetaType>
#include <QSignalSpy>
#include <QWebSocket>
#include <QWebSocketServer>
RemoteProxyTests::RemoteProxyTests(QObject *parent) :
QObject(parent)
@ -51,18 +53,30 @@ void RemoteProxyTests::restartEngine()
QVERIFY(Engine::exists());
}
void RemoteProxyTests::startEngine()
{
if (!Engine::exists()) {
Engine::instance();
QVERIFY(Engine::exists());
}
}
void RemoteProxyTests::startServer()
{
restartEngine();
startEngine();
QString serverName = "nymea-remoteproxy-testserver";
Engine::instance()->setAuthenticationServerUrl(QUrl("https://localhost"));
Engine::instance()->setServerName(serverName);
Engine::instance()->setAuthenticator(m_authenticator);
Engine::instance()->setWebSocketServerPort(m_port);
Engine::instance()->setWebSocketServerHostAddress(QHostAddress::LocalHost);
Engine::instance()->setSslConfiguration(m_sslConfiguration);
Engine::instance()->start();
QVERIFY(Engine::instance()->serverName() == serverName);
QVERIFY(Engine::instance()->running());
QVERIFY(Engine::instance()->webSocketServer()->running());
}
void RemoteProxyTests::stopServer()
@ -88,32 +102,73 @@ void RemoteProxyTests::cleanupTestCase()
cleanUpEngine();
}
void RemoteProxyTests::authenticate()
{
// // Start the server
// startServer();
// // Connect to the server
// RemoteProxyConnector *connector = new RemoteProxyConnector(this);
// connector->setInsecureConnection(true);
// QSignalSpy spy(connector, &RemoteProxyConnector::connected);
// connector->connectServer(QHostAddress::LocalHost, m_port);
// spy.wait();
// connector->disconnectServer();
// connector->deleteLater();
// Engine::instance()->stop();
}
void RemoteProxyTests::startStopServer()
{
restartEngine();
startEngine();
startServer();
stopServer();
cleanUpEngine();
}
void RemoteProxyTests::webserverConnectionBlocked()
{
// Create a dummy server which blocks the port
QWebSocketServer dummyServer("dummy-server", QWebSocketServer::NonSecureMode);
dummyServer.listen(QHostAddress::LocalHost, m_port);
// Start proxy webserver
Engine::instance()->setWebSocketServerPort(m_port);
Engine::instance()->setAuthenticator(m_authenticator);
Engine::instance()->setWebSocketServerHostAddress(QHostAddress::LocalHost);
Engine::instance()->setSslConfiguration(m_sslConfiguration);
Engine::instance()->start();
// Make sure the server is not running
QVERIFY(Engine::instance()->running());
QVERIFY(!Engine::instance()->webSocketServer()->running());
dummyServer.close();
// Try again
startServer();
// Clean up
stopServer();
cleanUpEngine();
}
void RemoteProxyTests::webserverSocketVersion()
{
// Start the server
startServer();
QUrl serverUrl;
serverUrl.setScheme("wss");
serverUrl.setHost("localhost");
serverUrl.setPort(m_port);
// Create a websocket with invalid version
QWebSocket socket("tests", QWebSocketProtocol::Version8);
socket.open(serverUrl);
// Clean up
stopServer();
cleanUpEngine();
}
void RemoteProxyTests::webserverConnection()
{
// Start the server
startServer();
// Clean up
stopServer();
cleanUpEngine();
}
void RemoteProxyTests::sslConfigurations()
{
// Start the server
@ -147,4 +202,23 @@ void RemoteProxyTests::sslConfigurations()
Engine::instance()->stop();
}
void RemoteProxyTests::authenticate()
{
// // Start the server
// startServer();
// // Connect to the server
// RemoteProxyConnector *connector = new RemoteProxyConnector(this);
// connector->setInsecureConnection(true);
// QSignalSpy spy(connector, &RemoteProxyConnector::connected);
// connector->connectServer(QHostAddress::LocalHost, m_port);
// spy.wait();
// connector->disconnectServer();
// connector->deleteLater();
// Engine::instance()->stop();
}
QTEST_MAIN(RemoteProxyTests)

View File

@ -25,6 +25,7 @@ private:
void cleanUpEngine();
void restartEngine();
void startEngine();
void startServer();
void stopServer();
@ -35,8 +36,11 @@ protected slots:
private slots:
void startStopServer();
void authenticate();
void webserverConnectionBlocked();
void webserverSocketVersion();
void webserverConnection();
void sslConfigurations();
void authenticate();
};