Commit be2780d7 authored by Don Gagne's avatar Don Gagne

Modify TCPLinkTest for new threading model

parent 780606e8
......@@ -188,7 +188,8 @@ DebugBuild {
src/qgcunittest/MockQGCUASParamManager.h \
src/qgcunittest/MultiSignalSpy.h \
src/qgcunittest/FlightModeConfigTest.h \
src/qgcunittest/TCPLinkTest.h
src/qgcunittest/TCPLinkTest.h \
src/qgcunittest/TCPLoopBackServer.h
SOURCES += \
src/qgcunittest/UASUnitTest.cc \
......@@ -197,7 +198,8 @@ DebugBuild {
src/qgcunittest/MockQGCUASParamManager.cc \
src/qgcunittest/MultiSignalSpy.cc \
src/qgcunittest/FlightModeConfigTest.cc \
src/qgcunittest/TCPLinkTest.cc
src/qgcunittest/TCPLinkTest.cc \
src/qgcunittest/TCPLoopBackServer.cc
}
#
......
......@@ -306,3 +306,15 @@ void TCPLink::_resetName(void)
_name = QString("TCP Link (host:%1 port:%2)").arg(_hostAddress.toString()).arg(_port);
emit nameChanged(_name);
}
void TCPLink::waitForBytesWritten(int msecs)
{
Q_ASSERT(_socket);
_socket->waitForBytesWritten(msecs);
}
void TCPLink::waitForReadyRead(int msecs)
{
Q_ASSERT(_socket);
_socket->waitForReadyRead(msecs);
}
......@@ -60,6 +60,8 @@ public:
quint16 getPort(void) const { return _port; }
QTcpSocket* getSocket(void) { return _socket; }
void signalBytesWritten(void);
// LinkInterface methods
virtual int getId(void) const;
virtual QString getName(void) const;
......@@ -80,6 +82,9 @@ public slots:
// From LinkInterface
virtual void writeBytes(const char* data, qint64 length);
void waitForBytesWritten(int msecs);
void waitForReadyRead(int msecs);
protected slots:
void _socketError(QAbstractSocket::SocketError socketError);
......@@ -90,7 +95,7 @@ protected slots:
protected:
// From LinkInterface->QThread
virtual void run(void);
private:
void _resetName(void);
bool _hardwareConnect(void);
......
......@@ -25,6 +25,7 @@
#include <QEventLoop>
#include <QCoreApplication>
#include <QDebug>
#include <QTest>
/// @file
/// @brief This class allows you to keep track of signal counts on a set of signals associated with an object.
......@@ -218,7 +219,10 @@ bool MultiSignalSpy::waitForSignalByIndex(
Q_ASSERT(spy);
while (spy->count() == 0 && !_timeout) {
QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 500);
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();
QCoreApplication::flush();
QTest::qSleep(100);
}
// Clean up and return status
......
......@@ -22,7 +22,7 @@
======================================================================*/
#include "TCPLinkTest.h"
#include <QTcpServer>
#include "TCPLoopBackServer.h"
/// @file
/// @brief TCPLink class unit test
......@@ -143,51 +143,46 @@ void TCPLinkUnitTest::_connectSucceed_test(void)
Q_ASSERT(_multiSpy->checkNoSignals() == true);
// Start the server side
QTcpServer* server = new QTcpServer(this);
QCOMPARE(server->listen(_hostAddress, _port), true);
TCPLoopBackServer* server = new TCPLoopBackServer(_hostAddress, _port);
Q_CHECK_PTR(server);
// Connect to the server
QCOMPARE(_link->connect(), true);
// Wait for the connection to come through on server side
QCOMPARE(server->waitForNewConnection(1000), true);
QTcpSocket* serverSocket = server->nextPendingConnection();
Q_ASSERT(serverSocket);
// Make sure we get the two different connected signals
QCOMPARE(_multiSpy->waitForSignalByIndex(connectedSignalIndex, 1000), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(connectedSignalMask | connected2SignalMask), true);
QList<QVariant> arguments = _multiSpy->getSpyByIndex(connected2SignalIndex)->takeFirst();
QCOMPARE(arguments.at(0).toBool(), true);
_multiSpy->clearSignalsByMask(connectedSignalMask);
// Test server->link data path
QByteArray bytesOut("test");
// Write data from server to link
serverSocket->write(bytesOut);
// Make sure we get the bytesReceived signal, with the correct data
QCOMPARE(_multiSpy->waitForSignalByIndex(bytesReceivedSignalIndex, 1000), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(bytesReceivedSignalMask), true);
arguments = _multiSpy->getSpyByIndex(bytesReceivedSignalIndex)->takeFirst();
QCOMPARE(arguments.at(1), QVariant(bytesOut));
_multiSpy->clearSignalByIndex(bytesReceivedSignalIndex);
_multiSpy->clearAllSignals();
// Test link->server data path
QByteArray bytesOut("test");
// Write data from link to server
const char* bytesWrittenSignal = SIGNAL(bytesWritten(qint64));
MultiSignalSpy bytesWrittenSpy;
QCOMPARE(bytesWrittenSpy.init(_link->getSocket(), &bytesWrittenSignal, 1), true);
_link->writeBytes(bytesOut.data(), bytesOut.size());
QCOMPARE(_link->getSocket()->waitForBytesWritten(1000), true);
_multiSpy->clearAllSignals();
// We emit this signal such that it will be queued and run on the TCPLink thread. This in turn
// allows the TCPLink object to pump the bytes through.
connect(this, SIGNAL(waitForBytesWritten(int)), _link, SLOT(waitForBytesWritten(int)));
emit waitForBytesWritten(1000);
// Make sure we get readyRead on server
QCOMPARE(serverSocket->waitForReadyRead(1000), true);
// Check for loopback, both from signal received and actual bytes returned
QCOMPARE(_multiSpy->waitForSignalByIndex(bytesReceivedSignalIndex, 1000), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(bytesReceivedSignalMask), true);
// Read the data and make sure it matches
QByteArray bytesIn = serverSocket->read(bytesOut.size() + 100);
QCOMPARE(bytesIn, bytesOut);
arguments = _multiSpy->getSpyByIndex(bytesReceivedSignalIndex)->takeFirst();
QVERIFY(arguments.at(1).toByteArray() == bytesOut);
_multiSpy->clearAllSignals();
// Disconnect the link
_link->disconnect();
......@@ -196,27 +191,21 @@ void TCPLinkUnitTest::_connectSucceed_test(void)
QCOMPARE(_multiSpy->checkOnlySignalByMask(disconnectedSignalMask | connected2SignalMask), true);
arguments = _multiSpy->getSpyByIndex(connected2SignalIndex)->takeFirst();
QCOMPARE(arguments.at(0).toBool(), false);
_multiSpy->clearSignalsByMask(disconnectedSignalMask);
// Make sure we get disconnected signals from the server side
QCOMPARE(serverSocket->waitForDisconnected(1000), true );
_multiSpy->clearAllSignals();
// Try to connect again to make sure everything was cleaned up correctly from previous connection
// Connect to the server
QCOMPARE(_link->connect(), true);
// Wait for the connection to come through on server side
QCOMPARE(server->waitForNewConnection(1000), true);
serverSocket = server->nextPendingConnection();
Q_ASSERT(serverSocket);
// Make sure we get the two different connected signals
QCOMPARE(_multiSpy->waitForSignalByIndex(connectedSignalIndex, 1000), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(connectedSignalMask | connected2SignalMask), true);
arguments = _multiSpy->getSpyByIndex(connected2SignalIndex)->takeFirst();
QCOMPARE(arguments.at(0).toBool(), true);
_multiSpy->clearSignalsByMask(connectedSignalMask);
_multiSpy->clearAllSignals();
server->quit();
QTest::qWait(500); // Wait a little for server thread to terminate
delete server;
}
......@@ -43,6 +43,10 @@ class TCPLinkUnitTest : public QObject
public:
TCPLinkUnitTest(void);
signals:
void waitForBytesWritten(int msecs);
void waitForReadyRead(int msecs);
private slots:
void init(void);
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "TCPLoopBackServer.h"
TCPLoopBackServer::TCPLoopBackServer(QHostAddress hostAddress, quint16 port) :
_hostAddress(hostAddress),
_port(port),
_tcpSocket(NULL)
{
moveToThread(this);
start(HighPriority);
}
void TCPLoopBackServer::run(void)
{
// Start the server side
_tcpServer = new QTcpServer(this);
Q_CHECK_PTR(_tcpServer);
bool connected = QObject::connect(_tcpServer, SIGNAL(newConnection()), this, SLOT(_newConnection()));
Q_ASSERT(connected);
Q_ASSERT(_tcpServer->listen(_hostAddress, _port));
// Fall into main event loop
exec();
}
void TCPLoopBackServer::_newConnection(void)
{
Q_ASSERT(_tcpServer);
_tcpSocket = _tcpServer->nextPendingConnection();
Q_ASSERT(_tcpSocket);
bool connected = QObject::connect(_tcpSocket, SIGNAL(readyRead()), this, SLOT(_readBytes()));
Q_ASSERT(connected);
}
void TCPLoopBackServer::_readBytes(void)
{
Q_ASSERT(_tcpSocket);
QByteArray bytesIn = _tcpSocket->read(_tcpSocket->bytesAvailable());
Q_ASSERT(_tcpSocket->write(bytesIn) == bytesIn.count());
Q_ASSERT(_tcpSocket->waitForBytesWritten(1000));
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef TCPLOOPBACKSERVER_H
#define TCPLOOPBACKSERVER_H
#include <QThread>
#include <QTcpServer>
#include <QTcpSocket>
class TCPLoopBackServer : public QThread
{
Q_OBJECT
public:
TCPLoopBackServer(QHostAddress hostAddress, quint16 port);
signals:
void newConnection(void);
protected:
virtual void run(void);
private slots:
void _newConnection(void);
void _readBytes(void);
private:
QHostAddress _hostAddress;
quint16 _port;
QTcpServer* _tcpServer;
QTcpSocket* _tcpSocket;
};
#endif
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment