Commit f19760e5 authored by Lorenz Meier's avatar Lorenz Meier

Merge pull request #452 from DonLakeFlyer/TCPLinkUnitTest

TcpLink unit test
parents 9d42f680 f00d8adf
......@@ -751,13 +751,17 @@ CONFIG(debug, debug|release) {
src/qgcunittest/UASUnitTest.h \
src/qgcunittest/MockUASManager.h \
src/qgcunittest/MockUAS.h \
src/qgcunittest/MockQGCUASParamManager.h
src/qgcunittest/MockQGCUASParamManager.h \
src/qgcunittest/MultiSignalSpy.h \
src/qgcunittest/TCPLinkTest.h
SOURCES += \
src/qgcunittest/UASUnitTest.cc \
src/qgcunittest/MockUASManager.cc \
src/qgcunittest/MockUAS.cc \
src/qgcunittest/MockQGCUASParamManager.cc
src/qgcunittest/MockQGCUASParamManager.cc \
src/qgcunittest/MultiSignalSpy.cc \
src/qgcunittest/TCPLinkTest.cc
}
# Enable Google Earth only on Mac OS and Windows with Visual Studio compiler
......
......@@ -413,8 +413,7 @@ bool SerialLink::hardwareConnect()
}
QObject::connect(m_port,SIGNAL(aboutToClose()),this,SIGNAL(disconnected()));
QObject::connect(m_port, SIGNAL(error(SerialLinkPortError_t)),
this, SLOT(linkError(SerialLinkPortError_t)));
QObject::connect(m_port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(linkError(QSerialPort::SerialPortError)));
// port->setCommTimeouts(QSerialPort::CtScheme_NonBlockingRead);
......@@ -444,7 +443,7 @@ bool SerialLink::hardwareConnect()
return true; // successful connection
}
void SerialLink::linkError(SerialLinkPortError_t error)
void SerialLink::linkError(QSerialPort::SerialPortError error)
{
qDebug() << error;
}
......
......@@ -40,9 +40,6 @@ This file is part of the QGROUNDCONTROL project
#include <configuration.h>
#include "SerialLinkInterface.h"
// convenience type for passing errors
typedef QSerialPort::SerialPortError SerialLinkPortError_t;
/**
* @brief The SerialLink class provides cross-platform access to serial links.
* It takes care of the link management and provides a common API to higher
......@@ -137,7 +134,7 @@ public slots:
bool connect();
bool disconnect();
void linkError(SerialLinkPortError_t error);
void linkError(QSerialPort::SerialPortError error);
protected:
quint64 m_bytesRead;
......
......@@ -21,13 +21,6 @@
======================================================================*/
/**
* @file
* @brief Definition of TCP connection (server) for unmanned vehicles
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QTimer>
#include <QList>
#include <QDebug>
......@@ -37,26 +30,29 @@
#include "LinkManager.h"
#include "QGC.h"
#include <QHostInfo>
#include <QSignalSpy>
TCPLink::TCPLink(QHostAddress hostAddress, quint16 socketPort) :
host(hostAddress),
port(socketPort),
socket(NULL),
socketIsConnected(false)
/// @file
/// @brief TCP link type for SITL support
///
/// @author Don Gagne <don@thegagnes.com>
TCPLink::TCPLink(QHostAddress hostAddress, quint16 socketPort) :
_hostAddress(hostAddress),
_port(socketPort),
_socket(NULL),
_socketIsConnected(false)
{
// Set unique ID and add link to the list of links
this->id = getNextLinkId();
this->name = tr("TCP Link (port:%1)").arg(this->port);
emit nameChanged(this->name);
_linkId = getNextLinkId();
_resetName();
qDebug() << "TCP Created " << this->name;
qDebug() << "TCP Created " << _name;
}
TCPLink::~TCPLink()
{
disconnect();
this->deleteLater();
deleteLater();
}
void TCPLink::run()
......@@ -64,45 +60,47 @@ void TCPLink::run()
exec();
}
void TCPLink::setAddress(const QString &text)
void TCPLink::setHostAddress(QHostAddress hostAddress)
{
setAddress(QHostAddress(text));
}
void TCPLink::setAddress(QHostAddress host)
{
bool reconnect(false);
if (this->isConnected())
{
bool reconnect = false;
if (this->isConnected()) {
disconnect();
reconnect = true;
}
this->host = host;
if (reconnect)
{
_hostAddress = hostAddress;
_resetName();
if (reconnect) {
connect();
}
}
void TCPLink::setHostAddress(const QString& hostAddress)
{
setHostAddress(QHostAddress(hostAddress));
}
void TCPLink::setPort(int port)
{
bool reconnect(false);
if(this->isConnected())
{
bool reconnect = false;
if (this->isConnected()) {
disconnect();
reconnect = true;
}
this->port = port;
this->name = tr("TCP Link (port:%1)").arg(this->port);
emit nameChanged(this->name);
if(reconnect)
{
_port = port;
_resetName();
if (reconnect) {
connect();
}
}
#ifdef TCPLINK_READWRITE_DEBUG
void TCPLink::writeDebugBytes(const char *data, qint16 size)
void TCPLink::_writeDebugBytes(const char *data, qint16 size)
{
QString bytes;
QString ascii;
......@@ -119,7 +117,7 @@ void TCPLink::writeDebugBytes(const char *data, qint16 size)
ascii.append(219);
}
}
qDebug() << "Sent" << size << "bytes to" << host.toString() << ":" << port << "data:";
qDebug() << "Sent" << size << "bytes to" << _hostAddress.toString() << ":" << _port << "data:";
qDebug() << bytes;
qDebug() << "ASCII:" << ascii;
}
......@@ -128,9 +126,9 @@ void TCPLink::writeDebugBytes(const char *data, qint16 size)
void TCPLink::writeBytes(const char* data, qint64 size)
{
#ifdef TCPLINK_READWRITE_DEBUG
writeDebugBytes(data, size);
_writeDebugBytes(data, size);
#endif
socket->write(data, size);
_socket->write(data, size);
// Log the amount and time written out for future data rate calculations.
QMutexLocker dataRateLocker(&dataRateMutex);
......@@ -145,14 +143,14 @@ void TCPLink::writeBytes(const char* data, qint64 size)
**/
void TCPLink::readBytes()
{
qint64 byteCount = socket->bytesAvailable();
qint64 byteCount = _socket->bytesAvailable();
if (byteCount)
{
QByteArray buffer;
buffer.resize(byteCount);
socket->read(buffer.data(), buffer.size());
_socket->read(buffer.data(), buffer.size());
emit bytesReceived(this, buffer);
......@@ -166,7 +164,6 @@ void TCPLink::readBytes()
}
}
/**
* @brief Get the number of bytes to read.
*
......@@ -174,7 +171,7 @@ void TCPLink::readBytes()
**/
qint64 TCPLink::bytesAvailable()
{
return socket->bytesAvailable();
return _socket->bytesAvailable();
}
/**
......@@ -184,15 +181,18 @@ qint64 TCPLink::bytesAvailable()
**/
bool TCPLink::disconnect()
{
this->quit();
this->wait();
quit();
wait();
if (socket)
if (_socket)
{
socket->disconnect();
socketIsConnected = false;
delete socket;
socket = NULL;
_socket->disconnectFromHost();
_socketIsConnected = false;
delete _socket;
_socket = NULL;
emit disconnected();
emit connected(false);
}
return true;
......@@ -205,42 +205,54 @@ bool TCPLink::disconnect()
**/
bool TCPLink::connect()
{
if(this->isRunning())
if (isRunning())
{
this->quit();
this->wait();
quit();
wait();
}
bool connected = this->hardwareConnect();
start(HighPriority);
bool connected = _hardwareConnect();
if (connected) {
start(HighPriority);
}
return connected;
}
bool TCPLink::hardwareConnect(void)
bool TCPLink::_hardwareConnect(void)
{
socket = new QTcpSocket();
Q_ASSERT(_socket == NULL);
_socket = new QTcpSocket();
QSignalSpy errorSpy(_socket, SIGNAL(error(QAbstractSocket::SocketError)));
socket->connectToHost(host, port);
_socket->connectToHost(_hostAddress, _port);
QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readBytes()));
QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
QObject::connect(_socket, SIGNAL(readyRead()), this, SLOT(readBytes()));
QObject::connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(_socketError(QAbstractSocket::SocketError)));
// Give the socket a second to connect to the other side otherwise error out
if (!socket->waitForConnected(1000))
if (!_socket->waitForConnected(1000))
{
emit communicationError(getName(), "connection failed");
// Whether a failed connection emits an error signal or not is platform specific.
// So in cases where it is not emitted, we emit one ourselves.
if (errorSpy.count() == 0) {
emit communicationError(getName(), "Connection failed");
}
delete _socket;
_socket = NULL;
return false;
}
socketIsConnected = true;
_socketIsConnected = true;
emit connected(true);
emit connected();
return true;
}
void TCPLink::socketError(QAbstractSocket::SocketError socketError)
void TCPLink::_socketError(QAbstractSocket::SocketError socketError)
{
Q_UNUSED(socketError);
emit communicationError(getName(), "Error on socket: " + socket->errorString());
emit communicationError(getName(), "Error on socket: " + _socket->errorString());
}
/**
......@@ -250,26 +262,19 @@ void TCPLink::socketError(QAbstractSocket::SocketError socketError)
**/
bool TCPLink::isConnected() const
{
return socketIsConnected;
return _socketIsConnected;
}
int TCPLink::getId() const
{
return id;
return _linkId;
}
QString TCPLink::getName() const
{
return name;
}
void TCPLink::setName(QString name)
{
this->name = name;
emit nameChanged(this->name);
return _name;
}
qint64 TCPLink::getConnectionSpeed() const
{
return 54000000; // 54 Mbit
......@@ -284,3 +289,9 @@ qint64 TCPLink::getCurrentOutDataRate() const
{
return 0;
}
void TCPLink::_resetName(void)
{
_name = QString("TCP Link (host:%1 port:%2)").arg(_hostAddress.toString()).arg(_port);
emit nameChanged(_name);
}
......@@ -21,12 +21,10 @@
======================================================================*/
/**
* @file
* @brief TCP connection (server) for unmanned vehicles
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
/// @file
/// @brief TCP link type for SITL support
///
/// @author Don Gagne <don@thegagnes.com>
#ifndef TCPLINK_H
#define TCPLINK_H
......@@ -50,66 +48,65 @@ public:
TCPLink(QHostAddress hostAddress = QHostAddress::LocalHost, quint16 socketPort = 5760);
~TCPLink();
void requestReset() { }
void setHostAddress(QHostAddress hostAddress);
bool isConnected() const;
qint64 bytesAvailable();
int getPort() const {
return port;
}
QHostAddress getHostAddress() const {
return host;
}
QHostAddress getHostAddress(void) const { return _hostAddress; }
quint16 getPort(void) const { return _port; }
QTcpSocket* getSocket(void) { return _socket; }
QString getName() const;
int getBaudRate() const;
int getBaudRateType() const;
int getFlowType() const;
int getParityType() const;
int getDataBitsType() const;
int getStopBitsType() const;
// LinkInterface methods
virtual int getId(void) const;
virtual QString getName(void) const;
virtual bool isConnected(void) const;
virtual bool connect(void);
virtual bool disconnect(void);
virtual qint64 bytesAvailable(void);
virtual void requestReset(void) {};
// Extensive statistics for scientific purposes
qint64 getConnectionSpeed() const;
qint64 getCurrentInDataRate() const;
qint64 getCurrentOutDataRate() const;
void run();
int getId() const;
public slots:
void setAddress(QHostAddress host);
void setPort(int port);
void readBytes();
void writeBytes(const char* data, qint64 length);
bool connect();
bool disconnect();
void socketError(QAbstractSocket::SocketError socketError);
void setAddress(const QString &text);
void setHostAddress(const QString& hostAddress);
void setPort(int port);
// From LinkInterface
virtual void writeBytes(const char* data, qint64 length);
protected slots:
void _socketError(QAbstractSocket::SocketError socketError);
// From LinkInterface
virtual void readBytes(void);
protected:
QString name;
QHostAddress host;
quint16 port;
int id;
QTcpSocket* socket;
bool socketIsConnected;
QMutex dataMutex;
void setName(QString name);
// From LinkInterface->QThread
virtual void run(void);
private:
bool hardwareConnect(void);
void _resetName(void);
bool _hardwareConnect(void);
#ifdef TCPLINK_READWRITE_DEBUG
void writeDebugBytes(const char *data, qint16 size);
void _writeDebugBytes(const char *data, qint16 size);
#endif
QString _name;
QHostAddress _hostAddress;
quint16 _port;
int _linkId;
QTcpSocket* _socket;
bool _socketIsConnected;
signals:
//Signals are defined by LinkInterface
quint64 _bitsSentTotal;
quint64 _bitsSentCurrent;
quint64 _bitsSentMax;
quint64 _bitsReceivedTotal;
quint64 _bitsReceivedCurrent;
quint64 _bitsReceivedMax;
quint64 _connectionStartTime;
QMutex _statisticsMutex;
};
#endif // TCPLINK_H
/*=====================================================================
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 "MultiSignalSpy.h"
#include <QEventLoop>
#include <QCoreApplication>
#include <QDebug>
/// @file
/// @brief This class allows you to keep track of signal counts on a set of signals associated with an object.
/// Mainly used for writing object unit tests.
///
/// @author Don Gagne <don@thegagnes.com>
MultiSignalSpy::MultiSignalSpy(QObject* parent) :
QObject(parent),
_signalEmitter(NULL),
_rgSignals(NULL),
_cSignals(0)
{
}
MultiSignalSpy::~MultiSignalSpy()
{
Q_ASSERT(_rgSignals);
for (size_t i=0; i<_cSignals; i++) {
delete _rgSpys[i];
}
}
/// Initializes the class. Must be called once before use.
/// @return true if success, false for failure
bool MultiSignalSpy::init(
QObject* signalEmitter, ///< [in] object which the signals are emitted from
const char** rgSignals, ///< [in] array of signals to spy on
size_t cSignals) ///< [in] numbers of signals in rgSignals
{
if (!signalEmitter || !rgSignals || cSignals == 0) {
qDebug() << "Invalid arguments";
return false;
}
_signalEmitter = signalEmitter;
_rgSignals = rgSignals;
_cSignals = cSignals;
// Allocate and connect QSignalSpy's
_rgSpys = new QSignalSpy*[_cSignals];
Q_ASSERT(_rgSpys != NULL);
for (size_t i=0; i<_cSignals; i++) {
_rgSpys[i] = new QSignalSpy(_signalEmitter, _rgSignals[i]);
if (_rgSpys[i] == NULL) {
qDebug() << "Unabled to allocated QSignalSpy";
return false;
}
if (!_rgSpys[i]->isValid()) {
qDebug() << "Invalid signal";
return false;
}
}
return true;
}
/// @param mask bit mask specifying which signals to check. The lowest order bit represents
/// index 0 into the rgSignals array and so on up the bit mask.
/// @return true if signal count = 1 for the specified signals
bool MultiSignalSpy::checkSignalByMask(quint16 mask)
{
for (size_t i=0; i<_cSignals; i++) {
if ((1 << i) & mask) {
QSignalSpy* spy = _rgSpys[i];
Q_ASSERT(spy != NULL);
if (spy->count() != 1) {
return false;
}
}
}
return true;
}
/// @return true if signal count = 1 for specified signals and signal count of 0
/// for all other signals
bool MultiSignalSpy::checkOnlySignalByMask(quint16 mask)
{
for (size_t i=0; i<_cSignals; i++) {
QSignalSpy* spy = _rgSpys[i];
Q_ASSERT(spy != NULL);
if ((1 << i) & mask) {
if (spy->count() != 1) {
return false;
}
} else {
if (spy->count() != 0) {
return false;
}
}
}
return true;
}
/// @return true if signal count = 0 for specified signals
bool MultiSignalSpy::checkNoSignalByMask(quint16 mask)
{
for (size_t i=0; i<_cSignals; i++) {
if ((1 << i) & mask) {
QSignalSpy* spy = _rgSpys[i];
Q_ASSERT(spy != NULL);
if (spy->count() != 0) {
return false;
}
}
}
return true;
}
/// @return true if signal count = 0 on all signals
bool MultiSignalSpy::checkNoSignals(void)
{
return checkNoSignalByMask(~0);
}
/// @return QSignalSpy for the specified signal
QSignalSpy* MultiSignalSpy::getSpyByIndex(quint16 index)
{
Q_ASSERT(index < _cSignals);
Q_ASSERT(_rgSpys[index] != NULL);
return _rgSpys[index];
}
/// Sets the signal count to 0 for the specified signal
void MultiSignalSpy::clearSignalByIndex(quint16 index)
{
Q_ASSERT(index < _cSignals);
Q_ASSERT(_rgSpys[index] != NULL);
_rgSpys[index]->clear();
}
/// Sets the signal count to 0 for all specified signals
void MultiSignalSpy::clearSignalsByMask(quint16 mask)
{
for (size_t i=0; i<_cSignals; i++) {
if ((1 << i) & mask) {
QSignalSpy* spy = _rgSpys[i];
Q_ASSERT(spy != NULL);
spy->clear();
}
}
}
/// Sets the signal count to 0 for all signals
void MultiSignalSpy::clearAllSignals(void)
{
for (quint16 i=0;i<_cSignals; i++) {
clearSignalByIndex(i);
}
}
void MultiSignalSpy::timerEvent(QTimerEvent * event)
{
Q_UNUSED(event);
_timeout = true;
}
/// Waits the specified signal
/// @return false for timeout
bool MultiSignalSpy::waitForSignalByIndex(
quint16 index, ///< [in] index of signal to wait on
int msec) ///< [in] numbers of milleconds to wait before timeout, -1 wait forever
{
// Check input parameters
if (msec < -1 || msec == 0)
return false;
// activate the timeout
_timeout = false;
int timerId;
if (msec != -1) {
timerId = startTimer(msec);
Q_ASSERT(timerId);
} else {
timerId = 0;
}
// Begin waiting
QSignalSpy* spy = _rgSpys[index];
Q_ASSERT(spy);
while (spy->count() == 0 && !_timeout) {
QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents);
}
// Clean up and return status
if (timerId) {
killTimer(timerId);
}
return spy->count() != 0;
}
/*=====================================================================
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 MULTISIGNALSPY_H
#define MULTISIGNALSPY_H
#include <QObject>
#include <QSignalSpy>
/// @file
/// @brief This class allows you to keep track of signal counts on a set of signals associated with an object.
/// Mainly used for writing object unit tests.
///
/// @author Don Gagne <don@thegagnes.com>
class MultiSignalSpy : public QObject
{
Q_OBJECT
public:
MultiSignalSpy(QObject* parent = NULL);
~MultiSignalSpy();
bool init(QObject* signalEmitter, const char** rgSignals, size_t cSignals);
bool checkSignalByMask(quint16 mask);
bool checkOnlySignalByMask(quint16 mask);
bool checkNoSignalByMask(quint16 mask);
bool checkNoSignals(void);
void clearSignalByIndex(quint16 index);
void clearSignalsByMask(quint16 mask);
void clearAllSignals(void);
bool waitForSignalByIndex(quint16 index, int msec);
QSignalSpy* getSpyByIndex(quint16 index);
private:
// QObject overrides
void timerEvent(QTimerEvent * event);
QObject* _signalEmitter;
const char** _rgSignals;
QSignalSpy** _rgSpys;
size_t _cSignals;
bool _timeout;
};
#endif
/*=====================================================================
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 "TCPLinkTest.h"
#include <QTcpServer>
/// @file
/// @brief TCPLink class unit test
///
/// @author Don Gagne <don@thegagnes.com>
TCPLinkUnitTest::TCPLinkUnitTest(void) :
_link(NULL),
_hostAddress(QHostAddress::LocalHost),
_port(5760),
_multiSpy(NULL)
{
}
// Called before every test
void TCPLinkUnitTest::init(void)
{
Q_ASSERT(_link == NULL);
Q_ASSERT(_multiSpy == NULL);
_link = new TCPLink(_hostAddress, _port);
Q_ASSERT(_link != NULL);
_rgSignals[bytesReceivedSignalIndex] = SIGNAL(bytesReceived(LinkInterface*, QByteArray));
_rgSignals[connectedSignalIndex] = SIGNAL(connected(void));
_rgSignals[disconnectedSignalIndex] = SIGNAL(disconnected(void));
_rgSignals[connected2SignalIndex] = SIGNAL(connected(bool));
_rgSignals[nameChangedSignalIndex] = SIGNAL(nameChanged(QString));
_rgSignals[communicationErrorSignalIndex] = SIGNAL(communicationError(const QString&, const QString&));
_rgSignals[communicationUpdateSignalIndex] = SIGNAL(communicationUpdate(const QString&, const QString&));
_rgSignals[deleteLinkSignalIndex] = SIGNAL(deleteLink(LinkInterface* const));
_multiSpy = new MultiSignalSpy();
QCOMPARE(_multiSpy->init(_link, _rgSignals, _cSignals), true);
}
// Called after every test
void TCPLinkUnitTest::cleanup(void)
{
Q_ASSERT(_multiSpy);
Q_ASSERT(_link);
delete _multiSpy;
delete _link;
_multiSpy = NULL;
_link = NULL;
}
void TCPLinkUnitTest::_properties_test(void)
{
Q_ASSERT(_link);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
// Make sure we get the right values back
QHostAddress hostAddressOut;
quint16 portOut;
hostAddressOut = _link->getHostAddress();
QCOMPARE(_hostAddress, hostAddressOut);
portOut = _link->getPort();
QCOMPARE(_port, portOut);
}
void TCPLinkUnitTest::_nameChangedSignal_test(void)
{
Q_ASSERT(_link);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
_link->setHostAddress(QHostAddress("127.1.1.1"));
QCOMPARE(_multiSpy->checkOnlySignalByMask(nameChangedSignalMask), true);
_multiSpy->clearSignalByIndex(nameChangedSignalIndex);
_link->setPort(42);
QCOMPARE(_multiSpy->checkOnlySignalByMask(nameChangedSignalMask), true);
_multiSpy->clearSignalByIndex(nameChangedSignalIndex);
}
void TCPLinkUnitTest::_connectFail_test(void)
{
Q_ASSERT(_link);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
QCOMPARE(_link->connect(), false);
// Make sure we get a linkError signal with the right link name
QCOMPARE(_multiSpy->waitForSignalByIndex(communicationErrorSignalIndex, 1000), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(communicationErrorSignalMask), true);
QList<QVariant> arguments = _multiSpy->getSpyByIndex(communicationErrorSignalIndex)->takeFirst();
QCOMPARE(arguments.at(0).toString(), _link->getName());
_multiSpy->clearSignalByIndex(communicationErrorSignalIndex);
// Try to connect again to make sure everything was cleaned up correctly from previous failed connection
QCOMPARE(_link->connect(), false);
// Make sure we get a linkError signal with the right link name
QCOMPARE(_multiSpy->waitForSignalByIndex(communicationErrorSignalIndex, 1000), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(communicationErrorSignalMask), true);
arguments = _multiSpy->getSpyByIndex(communicationErrorSignalIndex)->takeFirst();
QCOMPARE(arguments.at(0).toString(), _link->getName());
_multiSpy->clearSignalByIndex(communicationErrorSignalIndex);
}
void TCPLinkUnitTest::_connectSucceed_test(void)
{
Q_ASSERT(_link);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
// Start the server side
QTcpServer* server = new QTcpServer(this);
QCOMPARE(server->listen(_hostAddress, _port), true);
// 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);
// Test link->server data path
// Write data from link to server
_link->writeBytes(bytesOut.data(), bytesOut.size());
QCOMPARE(_link->getSocket()->waitForBytesWritten(1000), true);
// Make sure we get readyRead on server
QCOMPARE(serverSocket->waitForReadyRead(1000), true);
// Read the data and make sure it matches
QByteArray bytesIn = serverSocket->read(bytesOut.size() + 100);
QCOMPARE(bytesIn, bytesOut);
// Disconnect the link
_link->disconnect();
// Make sure we get the disconnected signals on link side
QCOMPARE(_multiSpy->waitForSignalByIndex(disconnectedSignalIndex, 1000), true);
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 );
// 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);
delete server;
}
/*=====================================================================
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 TCPLINKTEST_H
#define TCPLINKTEST_H
#include <QObject>
#include <QtTest/QtTest>
#include <QApplication>
#include "AutoTest.h"
#include "TCPLink.h"
#include "MultiSignalSpy.h"
/// @file
/// @brief TCPLink class unit test
///
/// @author Don Gagne <don@thegagnes.com>
class TCPLinkUnitTest : public QObject
{
Q_OBJECT
public:
TCPLinkUnitTest(void);
private slots:
void init(void);
void cleanup(void);
void _properties_test(void);
void _nameChangedSignal_test(void);
void _connectFail_test(void);
void _connectSucceed_test(void);
private:
enum {
bytesReceivedSignalIndex = 0,
connectedSignalIndex,
disconnectedSignalIndex,
connected2SignalIndex,
nameChangedSignalIndex,
communicationErrorSignalIndex,
communicationUpdateSignalIndex,
deleteLinkSignalIndex,
maxSignalIndex
};
enum {
bytesReceivedSignalMask = 1 << bytesReceivedSignalIndex,
connectedSignalMask = 1 << connectedSignalIndex,
disconnectedSignalMask = 1 << disconnectedSignalIndex,
connected2SignalMask = 1 << connected2SignalIndex,
nameChangedSignalMask = 1 << nameChangedSignalIndex,
communicationErrorSignalMask = 1 << communicationErrorSignalIndex,
communicationUpdateSignalMask = 1 << communicationUpdateSignalIndex,
deleteLinkSignalMask = 1 << deleteLinkSignalIndex,
};
TCPLink* _link;
QHostAddress _hostAddress;
quint16 _port;
MultiSignalSpy* _multiSpy;
static const size_t _cSignals = maxSignalIndex;
const char* _rgSignals[_cSignals];
};
DECLARE_TEST(TCPLinkUnitTest)
#endif
......@@ -14,7 +14,7 @@ QGCTCPLinkConfiguration::QGCTCPLinkConfiguration(TCPLink* link, QWidget *parent)
QString addr = link->getHostAddress().toString();
ui->hostAddressLineEdit->setText(addr);
connect(ui->portSpinBox, SIGNAL(valueChanged(int)), link, SLOT(setPort(int)));
connect(ui->hostAddressLineEdit, SIGNAL(textChanged (const QString &)), link, SLOT(setAddress(const QString &)));
connect(ui->hostAddressLineEdit, SIGNAL(textChanged (const QString &)), link, SLOT(setHostAddress(const QString &)));
}
QGCTCPLinkConfiguration::~QGCTCPLinkConfiguration()
......
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