Commit 2c0d56c7 authored by Don Gagne's avatar Don Gagne

Merge pull request #1063 from DonLakeFlyer/MavlinkLogTest

Mavlink log test
parents dfe7c2ed 505220e0
......@@ -478,7 +478,8 @@ HEADERS += \
src/uas/QGXPX4UAS.h \
src/QGCFileDialog.h \
src/QGCMessageBox.h \
src/QGCComboBox.h
src/QGCComboBox.h \
src/QGCTemporaryFile.h
SOURCES += \
src/main.cc \
......@@ -616,7 +617,9 @@ SOURCES += \
src/CmdLineOptParser.cc \
src/uas/QGXPX4UAS.cc \
src/QGCFileDialog.cc \
src/QGCComboBox.cc
src/QGCComboBox.cc \
src/QGCTemporaryFile.cc
#
# Unit Test specific configuration goes here
......@@ -654,7 +657,8 @@ HEADERS += \
src/qgcunittest/PX4RCCalibrationTest.h \
src/qgcunittest/LinkManagerTest.h \
src/qgcunittest/MainWindowTest.h \
src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.h
src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.h \
src/qgcunittest/MavlinkLogTest.h
SOURCES += \
src/qgcunittest/UnitTest.cc \
......@@ -675,7 +679,8 @@ SOURCES += \
src/qgcunittest/PX4RCCalibrationTest.cc \
src/qgcunittest/LinkManagerTest.cc \
src/qgcunittest/MainWindowTest.cc \
src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.cc
src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.cc \
src/qgcunittest/MavlinkLogTest.cc
}
#
......
......@@ -32,7 +32,6 @@ This file is part of the QGROUNDCONTROL project
#include <QApplication>
#include <QSettings>
#include <QTemporaryFile>
#include "GAudioOutput.h"
#include "MG.h"
......
......@@ -30,7 +30,6 @@ This file is part of the QGROUNDCONTROL project
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QTemporaryFile>
#include <QTextStream>
#include <QStringList>
#include <QFileInfo>
......
......@@ -56,6 +56,7 @@
#include "LinkManager.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCTemporaryFile.h"
#ifdef QGC_RTLAB_ENABLED
#include "OpalLink.h"
......@@ -309,12 +310,15 @@ void QGCApplication::setSavedFilesLocation(QString& location)
bool QGCApplication::validatePossibleSavedFilesLocation(QString& location)
{
// Make sure we can write to the directory
QString filename = QDir(location).filePath("QGCTempXXXXXXXX.tmp");
QTemporaryFile tempFile(filename);
QGCTemporaryFile tempFile(filename);
if (!tempFile.open()) {
return false;
}
tempFile.remove();
return true;
}
......
/*=====================================================================
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/>.
======================================================================*/
/// @file
/// @brief This class mimics QTemporaryFile. We have our own implementation due to the fact that
/// QTemporaryFile implemenation differs cross platform making it unusable for our use-case.
/// Look for bug reports on QTemporaryFile keeping the file locked for details.
///
/// @author Don Gagne <don@thegagnes.com>
#include "QGCTemporaryFile.h"
#include <QDir>
#include <QStandardPaths>
QGCTemporaryFile::QGCTemporaryFile(const QString& fileTemplate, QObject* parent) :
QFile(parent),
_template(fileTemplate)
{
}
bool QGCTemporaryFile::open(QFile::OpenMode openMode)
{
QDir tempDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
// Generate unique, non-existing filename
static const char rgDigits[] = "0123456789";
QString tempFilename;
do {
QString uniqueStr;
for (int i=0; i<6; i++) {
uniqueStr += rgDigits[qrand() % 10];
}
if (_template.contains("XXXXXX")) {
tempFilename = _template.replace("XXXXXX", uniqueStr, Qt::CaseSensitive);
} else {
tempFilename = _template + uniqueStr;
}
} while (tempDir.exists(tempFilename));
setFileName(tempDir.filePath(tempFilename));
return QFile::open(openMode);
}
/*=====================================================================
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 QGCTemporaryFile_H
#define QGCTemporaryFile_H
#include <QFile>
/// @file
/// @brief This class mimics QTemporaryFile. We have our own implementation due to the fact that
/// QTemporaryFile implemenation differs cross platform making it unusable for our use-case.
/// Look for bug reports on QTemporaryFile keeping the file locked for details.
///
/// @author Don Gagne <don@thegagnes.com>
class QGCTemporaryFile : public QFile {
Q_OBJECT
public:
/// @brief Creates a new temp file object. QGC temp files are always created in the
// QStandardPaths::TempLocation directory.
// @param template Template for file name following QTemporaryFile rules. Template should NOT include
// directory path, only file name.
QGCTemporaryFile(const QString& fileTemplate, QObject* parent = NULL);
/// @brief Opens the file in ReadWrite mode.
/// @returns false - open failed
bool open(OpenMode openMode = ReadWrite);
private:
QString _template;
};
#endif
......@@ -56,15 +56,13 @@ MAVLinkProtocol::MAVLinkProtocol() :
_should_exit(false),
_logSuspendError(false),
_logSuspendReplay(false),
_tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)),
_protocolStatusMessageConnected(false),
_saveTempFlightDataLogConnected(false)
{
qRegisterMetaType<mavlink_message_t>("mavlink_message_t");
_tempLogFile.setFileTemplate(QString("%1/%2.%3").arg(QStandardPaths::writableLocation(QStandardPaths::TempLocation)).arg(_tempLogFileTemplate).arg(_logFileExtension));
_tempLogFile.setAutoRemove(false);
m_authKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
loadSettings();
moveToThread(this);
......@@ -220,7 +218,7 @@ void MAVLinkProtocol::linkStatusChanged(bool connected)
// Track the links which are connected to the protocol
QList<LinkInterface*> _connectedLinks; ///< List of all links connected to protocol
qDebug() << "linkStatusChanged" << connected;
//qDebug() << "linkStatusChanged" << connected;
if (link) {
......
......@@ -37,12 +37,12 @@ This file is part of the QGROUNDCONTROL project
#include <QFile>
#include <QMap>
#include <QByteArray>
#include <QTemporaryFile>
#include "ProtocolInterface.h"
#include "LinkInterface.h"
#include "QGCMAVLink.h"
#include "QGC.h"
#include "QGCTemporaryFile.h"
/**
* @brief MAVLink micro air vehicle protocol reference implementation.
......@@ -282,9 +282,9 @@ private:
bool _logSuspendError; ///< true: Logging suspended due to error
bool _logSuspendReplay; ///< true: Logging suspended due to replay
QTemporaryFile _tempLogFile; ///< File to log to
static const char* _tempLogFileTemplate; ///< Template for temporary log file
static const char* _logFileExtension; ///< Extension for log files
QGCTemporaryFile _tempLogFile; ///< File to log to
static const char* _tempLogFileTemplate; ///< Template for temporary log file
static const char* _logFileExtension; ///< Extension for log files
bool _protocolStatusMessageConnected; ///< true: protocolStatusMessage signal has been connected
bool _saveTempFlightDataLogConnected; ///< true: saveTempFlightDataLog signal has been connected
......
/*=====================================================================
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/>.
======================================================================*/
/// @file
/// @brief Test for mavlink log collection
///
/// @author Don Gagne <don@thegagnes.com>
#include "MavlinkLogTest.h"
#include "MainWindow.h"
#include "MockLink.h"
#include "QGCTemporaryFile.h"
UT_REGISTER_TEST(MavlinkLogTest)
const char* MavlinkLogTest::_tempLogFileTemplate = "FlightDataXXXXXX"; ///< Template for temporary log file
const char* MavlinkLogTest::_logFileExtension = "mavlink"; ///< Extension for log files
const char* MavlinkLogTest::_saveLogFilename = "qgroundcontrol.mavlink.ut"; ///< Filename to save log files to
MavlinkLogTest::MavlinkLogTest(void)
{
}
void MavlinkLogTest::init(void)
{
UnitTest::init();
// Make sure temp directory is clear of mavlink logs
QDir tmpDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
QStringList logFiles(tmpDir.entryList(QStringList(QString("*.%1").arg(_logFileExtension)), QDir::Files));
foreach(QString logFile, logFiles) {
bool success = tmpDir.remove(logFile);
Q_UNUSED(success);
Q_ASSERT(success);
}
}
void MavlinkLogTest::cleanup(void)
{
UnitTest::cleanup();
// Make sure no left over logs in temp directory
QDir tmpDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
QStringList logFiles(tmpDir.entryList(QStringList(QString("*.%1").arg(_logFileExtension)), QDir::Files));
QCOMPARE(logFiles.count(), 0);
}
void MavlinkLogTest::_createTempLogFile(bool zeroLength)
{
QGCTemporaryFile tempLogFile(QString("%1.%2").arg(_tempLogFileTemplate).arg(_logFileExtension));
tempLogFile.open();
if (!zeroLength) {
tempLogFile.write("foo");
}
tempLogFile.close();
}
void MavlinkLogTest::_bootLogDetectionCancel_test(void)
{
// Create a fake mavlink log
_createTempLogFile(false);
// We should get a message box, followed by a getSaveFileName dialog.
setExpectedMessageBox(QMessageBox::Ok);
setExpectedFileDialog(getSaveFileName, QStringList());
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
checkExpectedMessageBox();
checkExpectedFileDialog();
mainWindow->close();
delete mainWindow;
}
void MavlinkLogTest::_bootLogDetectionSave_test(void)
{
// Create a fake mavlink log
_createTempLogFile(false);
// We should get a message box, followed by a getSaveFileName dialog.
setExpectedMessageBox(QMessageBox::Ok);
QDir logSaveDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
QString logSaveFile(logSaveDir.filePath(_saveLogFilename));
setExpectedFileDialog(getSaveFileName, QStringList(logSaveFile));
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
checkExpectedMessageBox();
checkExpectedFileDialog();
// Make sure the file is there and delete it
QCOMPARE(logSaveDir.remove(_saveLogFilename), true);
mainWindow->close();
delete mainWindow;
}
void MavlinkLogTest::_bootLogDetectionZeroLength_test(void)
{
// Create a fake eempty mavlink log
_createTempLogFile(true);
// Zero length log files should not generate any additional UI pop-ups. It should just be deleted silently.
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
mainWindow->close();
delete mainWindow;
}
void MavlinkLogTest::_connectLog_test(void)
{
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
LinkManager* linkMgr = LinkManager::instance();
Q_CHECK_PTR(linkMgr);
MockLink* link = new MockLink();
Q_CHECK_PTR(link);
// FIXME: LinkManager/MainWindow needs to be re-architected so that you don't have to addLink to MainWindow to get things to work
mainWindow->addLink(link);
linkMgr->connectLink(link);
QTest::qWait(5000); // Give enough time for UI to settle and heartbeats to go through
// On Disconnect: We should get a getSaveFileName dialog.
QDir logSaveDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
QString logSaveFile(logSaveDir.filePath(_saveLogFilename));
setExpectedFileDialog(getSaveFileName, QStringList(logSaveFile));
linkMgr->disconnectLink(link);
QTest::qWait(1000); // Need to allow signals to move between threads
checkExpectedFileDialog();
// Make sure the file is there and delete it
QCOMPARE(logSaveDir.remove(_saveLogFilename), true);
// MainWindow deletes itself on close
mainWindow->close();
QTest::qWait(1000); // Need to allow signals to move between threads to shutdown MainWindow
}
void MavlinkLogTest::_connectLogWindowClose_test(void)
{
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
LinkManager* linkMgr = LinkManager::instance();
Q_CHECK_PTR(linkMgr);
MockLink* link = new MockLink();
Q_CHECK_PTR(link);
// FIXME: LinkManager/MainWindow needs to be re-architected so that you don't have to addLink to MainWindow to get things to work
mainWindow->addLink(link);
linkMgr->connectLink(link);
QTest::qWait(5000); // Give enough time for UI to settle and heartbeats to go through
// On Disconnect: We should get a getSaveFileName dialog.
QDir logSaveDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
QString logSaveFile(logSaveDir.filePath(_saveLogFilename));
setExpectedFileDialog(getSaveFileName, QStringList(logSaveFile));
// MainWindow deletes itself on close
mainWindow->close();
QTest::qWait(1000); // Need to allow signals to move between threads
checkExpectedFileDialog();
// Make sure the file is there and delete it
QCOMPARE(logSaveDir.remove(_saveLogFilename), true);
}
/*=====================================================================
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/>.
======================================================================*/
/// @file
/// @brief Test for mavlink log collection
///
/// @author Don Gagne <don@thegagnes.com>
#ifndef MAVLINKLOGTEST_H
#define MAVLINKLOGTEST_H
#include "UnitTest.h"
class MavlinkLogTest : public UnitTest
{
Q_OBJECT
public:
MavlinkLogTest(void);
private slots:
void init(void);
void cleanup(void);
void _bootLogDetectionCancel_test(void);
void _bootLogDetectionSave_test(void);
void _bootLogDetectionZeroLength_test(void);
void _connectLog_test(void);
void _connectLogWindowClose_test(void);
private:
void _createTempLogFile(bool zeroLength);
static const char* _tempLogFileTemplate; ///< Template for temporary log file
static const char* _logFileExtension; ///< Extension for log files
static const char* _saveLogFilename; ///< Filename to save log files to
};
#endif
......@@ -382,6 +382,7 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg)
mavlink_message_t responseMsg;
char paramId[MAVLINK_MSG_ID_PARAM_VALUE_LEN];
Q_ASSERT(param.key().length() <= MAVLINK_MSG_ID_PARAM_VALUE_LEN);
strncpy(paramId, param.key().toLocal8Bit().constData(), MAVLINK_MSG_ID_PARAM_VALUE_LEN);
mavlink_msg_param_value_pack(_vehicleSystemId,
_vehicleComponentId,
......
......@@ -279,7 +279,8 @@ UASManager::~UASManager()
storeSettings();
// Delete all systems
foreach (UASInterface* mav, systems) {
delete mav;
// deleteLater so it ends up on correct thread
mav->deleteLater();
}
}
......
......@@ -480,7 +480,7 @@ void UASParameterDataModel::loadParamMetaInfoFromStream(QTextStream& stream)
{
// tooltip
paramDescriptions.insert(parts.at(0).trimmed(), parts.at(6).trimmed());
qDebug() << "PARAM META:" << parts.at(0).trimmed();
//qDebug() << "PARAM META:" << parts.at(0).trimmed();
}
}
}
......
......@@ -782,6 +782,8 @@ void MainWindow::closeEvent(QCloseEvent *event)
storeSettings();
mavlink->storeSettings();
UASManager::instance()->storeSettings();
// FIXME: If connected links, should prompt before close
LinkManager::instance()->disconnectAll();
event->accept();
}
......@@ -1039,7 +1041,7 @@ void MainWindow::enableAutoReconnect(bool enabled)
bool MainWindow::loadStyle(QGC_MAINWINDOW_STYLE style)
{
qDebug() << "LOAD STYLE" << style;
//qDebug() << "LOAD STYLE" << style;
bool success = true;
QString styles;
......@@ -1587,7 +1589,7 @@ void MainWindow::loadViewState()
{
if (widgetname != "")
{
qDebug() << "Loading widget:" << widgetname;
//qDebug() << "Loading widget:" << widgetname;
loadDockWidget(widgetname);
}
}
......
......@@ -118,7 +118,7 @@ void TerminalConsole::fillPortsInfo(QComboBox &comboxBox)
<< (info.productIdentifier() ? QString::number(info.productIdentifier(), 16) : QString());
comboxBox.insertItem(0,list.first(), list);
qDebug() << "Inserting " << list.first();
//qDebug() << "Inserting " << list.first();
}
}
......
......@@ -471,7 +471,7 @@ void LinechartPlot::setCurveColor(QString id, QColor color)
// Change the color of the curve.
curve->setPen(QPen(QBrush(color), curveWidth));
qDebug() << "Setting curve" << id << "to" << color;
//qDebug() << "Setting curve" << id << "to" << color;
// And change the color of the symbol, making sure to preserve the symbol style
const QwtSymbol *oldSymbol = curve->symbol();
......
......@@ -260,6 +260,8 @@ void QGCMapWidget::loadSettings(bool changePosition)
trailInterval = settings.value("TRAIL_INTERVAL", trailInterval).toFloat();
settings.endGroup();
#if 0
// FIXME: NYI
// SET CORRECT MENU CHECKBOXES
// Set the correct trail interval
if (trailType == mapcontrol::UAVTrailType::ByDistance)
......@@ -272,6 +274,7 @@ void QGCMapWidget::loadSettings(bool changePosition)
// XXX
qDebug() << "WARNING: Settings loading for trail type (ByTimeElapsed) not implemented";
}
#endif
// SET TRAIL TYPE
foreach (mapcontrol::UAVItem* uav, GetUAVS())
......
......@@ -31,7 +31,7 @@ void MenuActionHelper::removeDockWidget()
QObject *dockWidget = QObject::sender();
Q_ASSERT(dockWidget);
qDebug() << "Dockwidget:" << dockWidget->objectName() << "of type" << dockWidget->metaObject()->className();
//qDebug() << "Dockwidget:" << dockWidget->objectName() << "of type" << dockWidget->metaObject()->className();
QAction *action = m_menuToDockNameMap.key(dockWidget->objectName());
if(action) {
......
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