Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
bc71d49d
Commit
bc71d49d
authored
May 12, 2015
by
Lorenz Meier
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1557 from DonLakeFlyer/FileManager
File Manager fixes and unit test
parents
886b40b5
f534aa7e
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
417 additions
and
481 deletions
+417
-481
QGCApplication.pro
QGCApplication.pro
+4
-3
MockLink.cc
src/comm/MockLink.cc
+29
-18
MockLink.h
src/comm/MockLink.h
+9
-1
MockLinkFileServer.cc
src/comm/MockLinkFileServer.cc
+88
-73
MockLinkFileServer.h
src/comm/MockLinkFileServer.h
+27
-26
FileManagerTest.cc
src/qgcunittest/FileManagerTest.cc
+201
-269
FileManagerTest.h
src/qgcunittest/FileManagerTest.h
+5
-12
MockMavlinkInterface.cc
src/qgcunittest/MockMavlinkInterface.cc
+0
-9
MockMavlinkInterface.h
src/qgcunittest/MockMavlinkInterface.h
+0
-44
FileManager.cc
src/uas/FileManager.cc
+51
-22
FileManager.h
src/uas/FileManager.h
+3
-4
No files found.
QGCApplication.pro
View file @
bc71d49d
...
@@ -236,6 +236,7 @@ HEADERS += \
...
@@ -236,6 +236,7 @@ HEADERS += \
src
/
comm
/
LinkManager
.
h
\
src
/
comm
/
LinkManager
.
h
\
src
/
comm
/
MAVLinkProtocol
.
h
\
src
/
comm
/
MAVLinkProtocol
.
h
\
src
/
comm
/
MockLink
.
h
\
src
/
comm
/
MockLink
.
h
\
src
/
comm
/
MockLinkFileServer
.
h
\
src
/
comm
/
MockLinkMissionItemHandler
.
h
\
src
/
comm
/
MockLinkMissionItemHandler
.
h
\
src
/
comm
/
ProtocolInterface
.
h
\
src
/
comm
/
ProtocolInterface
.
h
\
src
/
comm
/
QGCFlightGearLink
.
h
\
src
/
comm
/
QGCFlightGearLink
.
h
\
...
@@ -374,6 +375,7 @@ SOURCES += \
...
@@ -374,6 +375,7 @@ SOURCES += \
src
/
comm
/
LinkManager
.
cc
\
src
/
comm
/
LinkManager
.
cc
\
src
/
comm
/
MAVLinkProtocol
.
cc
\
src
/
comm
/
MAVLinkProtocol
.
cc
\
src
/
comm
/
MockLink
.
cc
\
src
/
comm
/
MockLink
.
cc
\
src
/
comm
/
MockLinkFileServer
.
cc
\
src
/
comm
/
MockLinkMissionItemHandler
.
cc
\
src
/
comm
/
MockLinkMissionItemHandler
.
cc
\
src
/
comm
/
QGCFlightGearLink
.
cc
\
src
/
comm
/
QGCFlightGearLink
.
cc
\
src
/
comm
/
QGCJSBSimLink
.
cc
\
src
/
comm
/
QGCJSBSimLink
.
cc
\
...
@@ -518,8 +520,6 @@ INCLUDEPATH += \
...
@@ -518,8 +520,6 @@ INCLUDEPATH += \
HEADERS
+=
\
HEADERS
+=
\
src
/
qgcunittest
/
FlightGearTest
.
h
\
src
/
qgcunittest
/
FlightGearTest
.
h
\
src
/
qgcunittest
/
MockMavlinkFileServer
.
h
\
src
/
qgcunittest
/
MockMavlinkInterface
.
h
\
src
/
qgcunittest
/
MultiSignalSpy
.
h
\
src
/
qgcunittest
/
MultiSignalSpy
.
h
\
src
/
qgcunittest
/
TCPLinkTest
.
h
\
src
/
qgcunittest
/
TCPLinkTest
.
h
\
src
/
qgcunittest
/
TCPLoopBackServer
.
h
\
src
/
qgcunittest
/
TCPLoopBackServer
.
h
\
...
@@ -534,10 +534,10 @@ HEADERS += \
...
@@ -534,10 +534,10 @@ HEADERS += \
src
/
qgcunittest
/
PX4RCCalibrationTest
.
h
\
src
/
qgcunittest
/
PX4RCCalibrationTest
.
h
\
src
/
qgcunittest
/
UnitTest
.
h
\
src
/
qgcunittest
/
UnitTest
.
h
\
src
/
VehicleSetup
/
SetupViewTest
.
h
\
src
/
VehicleSetup
/
SetupViewTest
.
h
\
src
/
qgcunittest
/
FileManagerTest
.
h
\
SOURCES
+=
\
SOURCES
+=
\
src
/
qgcunittest
/
FlightGearTest
.
cc
\
src
/
qgcunittest
/
FlightGearTest
.
cc
\
src
/
qgcunittest
/
MockMavlinkFileServer
.
cc
\
src
/
qgcunittest
/
MultiSignalSpy
.
cc
\
src
/
qgcunittest
/
MultiSignalSpy
.
cc
\
src
/
qgcunittest
/
TCPLinkTest
.
cc
\
src
/
qgcunittest
/
TCPLinkTest
.
cc
\
src
/
qgcunittest
/
TCPLoopBackServer
.
cc
\
src
/
qgcunittest
/
TCPLoopBackServer
.
cc
\
...
@@ -552,6 +552,7 @@ SOURCES += \
...
@@ -552,6 +552,7 @@ SOURCES += \
src
/
qgcunittest
/
PX4RCCalibrationTest
.
cc
\
src
/
qgcunittest
/
PX4RCCalibrationTest
.
cc
\
src
/
qgcunittest
/
UnitTest
.
cc
\
src
/
qgcunittest
/
UnitTest
.
cc
\
src
/
VehicleSetup
/
SetupViewTest
.
cc
\
src
/
VehicleSetup
/
SetupViewTest
.
cc
\
src
/
qgcunittest
/
FileManagerTest
.
cc
\
}
#
DebugBuild
|
WindowsDebugAndRelease
}
#
DebugBuild
|
WindowsDebugAndRelease
}
#
AndroidBuild
}
#
AndroidBuild
...
...
src/comm/MockLink.cc
View file @
bc71d49d
...
@@ -75,7 +75,8 @@ MockLink::MockLink(MockConfiguration* config) :
...
@@ -75,7 +75,8 @@ MockLink::MockLink(MockConfiguration* config) :
_mavlinkStarted
(
false
),
_mavlinkStarted
(
false
),
_mavBaseMode
(
MAV_MODE_FLAG_MANUAL_INPUT_ENABLED
|
MAV_MODE_FLAG_CUSTOM_MODE_ENABLED
),
_mavBaseMode
(
MAV_MODE_FLAG_MANUAL_INPUT_ENABLED
|
MAV_MODE_FLAG_CUSTOM_MODE_ENABLED
),
_mavState
(
MAV_STATE_STANDBY
),
_mavState
(
MAV_STATE_STANDBY
),
_autopilotType
(
MAV_AUTOPILOT_PX4
)
_autopilotType
(
MAV_AUTOPILOT_PX4
),
_fileServer
(
NULL
)
{
{
_config
=
config
;
_config
=
config
;
union
px4_custom_mode
px4_cm
;
union
px4_custom_mode
px4_cm
;
...
@@ -84,6 +85,9 @@ MockLink::MockLink(MockConfiguration* config) :
...
@@ -84,6 +85,9 @@ MockLink::MockLink(MockConfiguration* config) :
px4_cm
.
main_mode
=
PX4_CUSTOM_MAIN_MODE_MANUAL
;
px4_cm
.
main_mode
=
PX4_CUSTOM_MAIN_MODE_MANUAL
;
_mavCustomMode
=
px4_cm
.
data
;
_mavCustomMode
=
px4_cm
.
data
;
_fileServer
=
new
MockLinkFileServer
(
_vehicleSystemId
,
_vehicleComponentId
,
this
);
Q_CHECK_PTR
(
_fileServer
);
_missionItemHandler
=
new
MockLinkMissionItemHandler
(
_vehicleSystemId
,
this
);
_missionItemHandler
=
new
MockLinkMissionItemHandler
(
_vehicleSystemId
,
this
);
Q_CHECK_PTR
(
_missionItemHandler
);
Q_CHECK_PTR
(
_missionItemHandler
);
...
@@ -218,7 +222,6 @@ void MockLink::_loadParams(void)
...
@@ -218,7 +222,6 @@ void MockLink::_loadParams(void)
void
MockLink
::
_sendHeartBeat
(
void
)
void
MockLink
::
_sendHeartBeat
(
void
)
{
{
mavlink_message_t
msg
;
mavlink_message_t
msg
;
uint8_t
buffer
[
MAVLINK_MAX_PACKET_LEN
];
mavlink_msg_heartbeat_pack
(
_vehicleSystemId
,
mavlink_msg_heartbeat_pack
(
_vehicleSystemId
,
_vehicleComponentId
,
_vehicleComponentId
,
...
@@ -229,6 +232,13 @@ void MockLink::_sendHeartBeat(void)
...
@@ -229,6 +232,13 @@ void MockLink::_sendHeartBeat(void)
_mavCustomMode
,
// custom mode
_mavCustomMode
,
// custom mode
_mavState
);
// MAV_STATE
_mavState
);
// MAV_STATE
respondWithMavlinkMessage
(
msg
);
}
void
MockLink
::
respondWithMavlinkMessage
(
const
mavlink_message_t
&
msg
)
{
uint8_t
buffer
[
MAVLINK_MAX_PACKET_LEN
];
int
cBuffer
=
mavlink_msg_to_send_buffer
(
buffer
,
&
msg
);
int
cBuffer
=
mavlink_msg_to_send_buffer
(
buffer
,
&
msg
);
QByteArray
bytes
((
char
*
)
buffer
,
cBuffer
);
QByteArray
bytes
((
char
*
)
buffer
,
cBuffer
);
emit
bytesReceived
(
this
,
bytes
);
emit
bytesReceived
(
this
,
bytes
);
...
@@ -333,6 +343,10 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
...
@@ -333,6 +343,10 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
break;
break;
#endif
#endif
case
MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL
:
_handleFTP
(
msg
);
break
;
default:
default:
qDebug
()
<<
"MockLink: Unhandled mavlink message, id:"
<<
msg
.
msgid
;
qDebug
()
<<
"MockLink: Unhandled mavlink message, id:"
<<
msg
.
msgid
;
break
;
break
;
...
@@ -340,15 +354,6 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
...
@@ -340,15 +354,6 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
}
}
}
}
void
MockLink
::
_emitMavlinkMessage
(
const
mavlink_message_t
&
msg
)
{
uint8_t
outputBuffer
[
MAVLINK_MAX_PACKET_LEN
];
int
cBuffer
=
mavlink_msg_to_send_buffer
(
outputBuffer
,
&
msg
);
QByteArray
bytes
((
char
*
)
outputBuffer
,
cBuffer
);
emit
bytesReceived
(
this
,
bytes
);
}
void
MockLink
::
_handleHeartBeat
(
const
mavlink_message_t
&
msg
)
void
MockLink
::
_handleHeartBeat
(
const
mavlink_message_t
&
msg
)
{
{
Q_UNUSED
(
msg
);
Q_UNUSED
(
msg
);
...
@@ -494,7 +499,7 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg)
...
@@ -494,7 +499,7 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg)
paramType
,
// MAV_PARAM_TYPE
paramType
,
// MAV_PARAM_TYPE
cParameters
,
// Total number of parameters
cParameters
,
// Total number of parameters
paramIndex
++
);
// Index of this parameter
paramIndex
++
);
// Index of this parameter
_emit
MavlinkMessage
(
responseMsg
);
respondWith
MavlinkMessage
(
responseMsg
);
// Only first parameter the first time through
// Only first parameter the first time through
break
;
break
;
...
@@ -533,7 +538,7 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg)
...
@@ -533,7 +538,7 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg)
paramType
,
// MAV_PARAM_TYPE
paramType
,
// MAV_PARAM_TYPE
cParameters
,
// Total number of parameters
cParameters
,
// Total number of parameters
paramIndex
++
);
// Index of this parameter
paramIndex
++
);
// Index of this parameter
_emit
MavlinkMessage
(
responseMsg
);
respondWith
MavlinkMessage
(
responseMsg
);
}
}
}
}
}
}
...
@@ -571,7 +576,7 @@ void MockLink::_handleParamSet(const mavlink_message_t& msg)
...
@@ -571,7 +576,7 @@ void MockLink::_handleParamSet(const mavlink_message_t& msg)
request
.
param_type
,
// Send same type back
request
.
param_type
,
// Send same type back
_mapParamName2Value
[
componentId
].
count
(),
// Total number of parameters
_mapParamName2Value
[
componentId
].
count
(),
// Total number of parameters
_mapParamName2Value
[
componentId
].
keys
().
indexOf
(
paramId
));
// Index of this parameter
_mapParamName2Value
[
componentId
].
keys
().
indexOf
(
paramId
));
// Index of this parameter
_emit
MavlinkMessage
(
responseMsg
);
respondWith
MavlinkMessage
(
responseMsg
);
}
}
void
MockLink
::
_handleParamRequestRead
(
const
mavlink_message_t
&
msg
)
void
MockLink
::
_handleParamRequestRead
(
const
mavlink_message_t
&
msg
)
...
@@ -613,7 +618,7 @@ void MockLink::_handleParamRequestRead(const mavlink_message_t& msg)
...
@@ -613,7 +618,7 @@ void MockLink::_handleParamRequestRead(const mavlink_message_t& msg)
_mapParamName2MavParamType
[
paramId
],
// Parameter type
_mapParamName2MavParamType
[
paramId
],
// Parameter type
_mapParamName2Value
[
componentId
].
count
(),
// Total number of parameters
_mapParamName2Value
[
componentId
].
count
(),
// Total number of parameters
_mapParamName2Value
[
componentId
].
keys
().
indexOf
(
paramId
));
// Index of this parameter
_mapParamName2Value
[
componentId
].
keys
().
indexOf
(
paramId
));
// Index of this parameter
_emit
MavlinkMessage
(
responseMsg
);
respondWith
MavlinkMessage
(
responseMsg
);
}
}
void
MockLink
::
_handleMissionRequestList
(
const
mavlink_message_t
&
msg
)
void
MockLink
::
_handleMissionRequestList
(
const
mavlink_message_t
&
msg
)
...
@@ -632,7 +637,7 @@ void MockLink::_handleMissionRequestList(const mavlink_message_t& msg)
...
@@ -632,7 +637,7 @@ void MockLink::_handleMissionRequestList(const mavlink_message_t& msg)
msg
.
sysid
,
// Target is original sender
msg
.
sysid
,
// Target is original sender
msg
.
compid
,
// Target is original sender
msg
.
compid
,
// Target is original sender
_missionItems
.
count
());
// Number of mission items
_missionItems
.
count
());
// Number of mission items
_emit
MavlinkMessage
(
responseMsg
);
respondWith
MavlinkMessage
(
responseMsg
);
}
}
void
MockLink
::
_handleMissionRequest
(
const
mavlink_message_t
&
msg
)
void
MockLink
::
_handleMissionRequest
(
const
mavlink_message_t
&
msg
)
...
@@ -660,7 +665,7 @@ void MockLink::_handleMissionRequest(const mavlink_message_t& msg)
...
@@ -660,7 +665,7 @@ void MockLink::_handleMissionRequest(const mavlink_message_t& msg)
item
.
autocontinue
,
item
.
autocontinue
,
item
.
param1
,
item
.
param2
,
item
.
param3
,
item
.
param4
,
item
.
param1
,
item
.
param2
,
item
.
param3
,
item
.
param4
,
item
.
x
,
item
.
y
,
item
.
z
);
item
.
x
,
item
.
y
,
item
.
z
);
_emit
MavlinkMessage
(
responseMsg
);
respondWith
MavlinkMessage
(
responseMsg
);
}
}
void
MockLink
::
_handleMissionItem
(
const
mavlink_message_t
&
msg
)
void
MockLink
::
_handleMissionItem
(
const
mavlink_message_t
&
msg
)
...
@@ -711,5 +716,11 @@ void MockLink::emitRemoteControlChannelRawChanged(int channel, uint16_t raw)
...
@@ -711,5 +716,11 @@ void MockLink::emitRemoteControlChannelRawChanged(int channel, uint16_t raw)
chanRaw
[
16
],
// channel raw value
chanRaw
[
16
],
// channel raw value
chanRaw
[
17
],
// channel raw value
chanRaw
[
17
],
// channel raw value
0
);
// rss
0
);
// rss
_emitMavlinkMessage
(
responseMsg
);
respondWithMavlinkMessage
(
responseMsg
);
}
void
MockLink
::
_handleFTP
(
const
mavlink_message_t
&
msg
)
{
Q_ASSERT
(
_fileServer
);
_fileServer
->
handleFTPMessage
(
msg
);
}
}
src/comm/MockLink.h
View file @
bc71d49d
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include <QLoggingCategory>
#include <QLoggingCategory>
#include "MockLinkMissionItemHandler.h"
#include "MockLinkMissionItemHandler.h"
#include "MockLinkFileServer.h"
#include "LinkManager.h"
#include "LinkManager.h"
#include "QGCMAVLink.h"
#include "QGCMAVLink.h"
...
@@ -72,6 +73,11 @@ public:
...
@@ -72,6 +73,11 @@ public:
void
setAutopilotType
(
MAV_AUTOPILOT
autopilot
)
{
_autopilotType
=
autopilot
;
}
void
setAutopilotType
(
MAV_AUTOPILOT
autopilot
)
{
_autopilotType
=
autopilot
;
}
void
emitRemoteControlChannelRawChanged
(
int
channel
,
uint16_t
raw
);
void
emitRemoteControlChannelRawChanged
(
int
channel
,
uint16_t
raw
);
/// Sends the specified mavlink message to QGC
void
respondWithMavlinkMessage
(
const
mavlink_message_t
&
msg
);
MockLinkFileServer
*
getFileServer
(
void
)
{
return
_fileServer
;
}
// These are left unimplemented in order to cause linker errors which indicate incorrect usage of
// These are left unimplemented in order to cause linker errors which indicate incorrect usage of
// connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
// connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
bool
connect
(
void
);
bool
connect
(
void
);
...
@@ -109,7 +115,6 @@ private:
...
@@ -109,7 +115,6 @@ private:
void
_handleIncomingNSHBytes
(
const
char
*
bytes
,
int
cBytes
);
void
_handleIncomingNSHBytes
(
const
char
*
bytes
,
int
cBytes
);
void
_handleIncomingMavlinkBytes
(
const
uint8_t
*
bytes
,
int
cBytes
);
void
_handleIncomingMavlinkBytes
(
const
uint8_t
*
bytes
,
int
cBytes
);
void
_loadParams
(
void
);
void
_loadParams
(
void
);
void
_emitMavlinkMessage
(
const
mavlink_message_t
&
msg
);
void
_handleHeartBeat
(
const
mavlink_message_t
&
msg
);
void
_handleHeartBeat
(
const
mavlink_message_t
&
msg
);
void
_handleSetMode
(
const
mavlink_message_t
&
msg
);
void
_handleSetMode
(
const
mavlink_message_t
&
msg
);
void
_handleParamRequestList
(
const
mavlink_message_t
&
msg
);
void
_handleParamRequestList
(
const
mavlink_message_t
&
msg
);
...
@@ -118,6 +123,7 @@ private:
...
@@ -118,6 +123,7 @@ private:
void
_handleMissionRequestList
(
const
mavlink_message_t
&
msg
);
void
_handleMissionRequestList
(
const
mavlink_message_t
&
msg
);
void
_handleMissionRequest
(
const
mavlink_message_t
&
msg
);
void
_handleMissionRequest
(
const
mavlink_message_t
&
msg
);
void
_handleMissionItem
(
const
mavlink_message_t
&
msg
);
void
_handleMissionItem
(
const
mavlink_message_t
&
msg
);
void
_handleFTP
(
const
mavlink_message_t
&
msg
);
float
_floatUnionForParam
(
int
componentId
,
const
QString
&
paramName
);
float
_floatUnionForParam
(
int
componentId
,
const
QString
&
paramName
);
void
_setParamFloatUnionIntoMap
(
int
componentId
,
const
QString
&
paramName
,
float
paramFloat
);
void
_setParamFloatUnionIntoMap
(
int
componentId
,
const
QString
&
paramName
,
float
paramFloat
);
...
@@ -144,6 +150,8 @@ private:
...
@@ -144,6 +150,8 @@ private:
MockConfiguration
*
_config
;
MockConfiguration
*
_config
;
MAV_AUTOPILOT
_autopilotType
;
MAV_AUTOPILOT
_autopilotType
;
MockLinkFileServer
*
_fileServer
;
};
};
#endif
#endif
src/
qgcunittest/MockMavl
inkFileServer.cc
→
src/
comm/MockL
inkFileServer.cc
View file @
bc71d49d
...
@@ -21,18 +21,19 @@
...
@@ -21,18 +21,19 @@
======================================================================*/
======================================================================*/
#include "MockMavlinkFileServer.h"
#include "MockLinkFileServer.h"
#include "MockLink.h"
const
MockMavlinkFileServer
::
ErrorMode_t
MockMavlinkFileServer
::
rgFailureModes
[]
=
{
MockMavlinkFileServer
::
errModeNoResponse
,
const
MockLinkFileServer
::
ErrorMode_t
MockLinkFileServer
::
rgFailureModes
[]
=
{
MockMavlinkFileServer
::
errModeNakResponse
,
MockLinkFileServer
::
errModeNoResponse
,
MockMavlinkFileServer
::
errModeNoSecondResponse
,
MockLinkFileServer
::
errModeNakResponse
,
MockMavlinkFileServer
::
errModeNakSecondResponse
,
MockLinkFileServer
::
errModeNoSecondResponse
,
MockMavlinkFileServer
::
errModeBadSequence
,
MockLinkFileServer
::
errModeNakSecondResponse
,
MockLinkFileServer
::
errModeBadSequence
,
};
};
const
size_t
Mock
MavlinkFileServer
::
cFailureModes
=
sizeof
(
MockMavlinkFileServer
::
rgFailureModes
)
/
sizeof
(
MockMavl
inkFileServer
::
rgFailureModes
[
0
]);
const
size_t
Mock
LinkFileServer
::
cFailureModes
=
sizeof
(
MockLinkFileServer
::
rgFailureModes
)
/
sizeof
(
MockL
inkFileServer
::
rgFailureModes
[
0
]);
const
Mock
MavlinkFileServer
::
FileTestCase
MockMavlinkFileServer
::
rgFileTestCases
[
MockMavl
inkFileServer
::
cFileTestCases
]
=
{
const
Mock
LinkFileServer
::
FileTestCase
MockLinkFileServer
::
rgFileTestCases
[
MockL
inkFileServer
::
cFileTestCases
]
=
{
// File fits one Read Ack packet, partially filling data
// File fits one Read Ack packet, partially filling data
{
"partial.qgc"
,
sizeof
(((
FileManager
::
Request
*
)
0
)
->
data
)
-
1
,
1
,
false
},
{
"partial.qgc"
,
sizeof
(((
FileManager
::
Request
*
)
0
)
->
data
)
-
1
,
1
,
false
},
// File fits one Read Ack packet, exactly filling all data
// File fits one Read Ack packet, exactly filling all data
...
@@ -42,19 +43,20 @@ const MockMavlinkFileServer::FileTestCase MockMavlinkFileServer::rgFileTestCases
...
@@ -42,19 +43,20 @@ const MockMavlinkFileServer::FileTestCase MockMavlinkFileServer::rgFileTestCases
};
};
// We only support a single fixed session
// We only support a single fixed session
const
uint8_t
Mock
Mavl
inkFileServer
::
_sessionId
=
1
;
const
uint8_t
Mock
L
inkFileServer
::
_sessionId
=
1
;
Mock
MavlinkFileServer
::
MockMavlinkFileServer
(
uint8_t
systemIdQGC
,
uint8_t
systemIdServer
)
:
Mock
LinkFileServer
::
MockLinkFileServer
(
uint8_t
systemIdServer
,
uint8_t
componentIdServer
,
MockLink
*
mockLink
)
:
_errMode
(
errModeNone
),
_errMode
(
errModeNone
),
_systemIdServer
(
systemIdServer
),
_systemIdServer
(
systemIdServer
),
_systemIdQGC
(
systemIdQGC
)
_componentIdServer
(
componentIdServer
),
_mockLink
(
mockLink
)
{
{
}
}
/// @brief Handles List command requests. Only supports root folder paths.
/// @brief Handles List command requests. Only supports root folder paths.
/// File list returned is set using the setFileList method.
/// File list returned is set using the setFileList method.
void
Mock
MavlinkFileServer
::
_listCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
Mock
LinkFileServer
::
_listCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
{
// FIXME: Does not support directories that span multiple packets
// FIXME: Does not support directories that span multiple packets
...
@@ -65,17 +67,18 @@ void MockMavlinkFileServer::_listCommand(FileManager::Request* request, uint16_t
...
@@ -65,17 +67,18 @@ void MockMavlinkFileServer::_listCommand(FileManager::Request* request, uint16_t
// We only support root path
// We only support root path
path
=
(
char
*
)
&
request
->
data
[
0
];
path
=
(
char
*
)
&
request
->
data
[
0
];
if
(
!
path
.
isEmpty
()
&&
path
!=
"/"
)
{
if
(
!
path
.
isEmpty
()
&&
path
!=
"/"
)
{
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
return
;
return
;
}
}
// Offset requested is past the end of the list
// Offset requested is past the end of the list
if
(
request
->
hdr
.
offset
>
(
uint32_t
)
_fileList
.
size
())
{
if
(
request
->
hdr
.
offset
>
(
uint32_t
)
_fileList
.
size
())
{
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
return
;
return
;
}
}
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
req_opcode
=
FileManager
::
kCmdListDirectory
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
offset
=
request
->
hdr
.
offset
;
ackResponse
.
hdr
.
offset
=
request
->
hdr
.
offset
;
ackResponse
.
hdr
.
size
=
0
;
ackResponse
.
hdr
.
size
=
0
;
...
@@ -92,22 +95,22 @@ void MockMavlinkFileServer::_listCommand(FileManager::Request* request, uint16_t
...
@@ -92,22 +95,22 @@ void MockMavlinkFileServer::_listCommand(FileManager::Request* request, uint16_t
bufPtr
+=
cchFilename
+
1
;
bufPtr
+=
cchFilename
+
1
;
}
}
_
emitResponse
(
&
ackResponse
,
outgoingSeqNumber
);
_
sendResponse
(
senderSystemId
,
senderComponentId
,
&
ackResponse
,
outgoingSeqNumber
);
}
else
if
(
_errMode
==
errModeNakSecondResponse
)
{
}
else
if
(
_errMode
==
errModeNakSecondResponse
)
{
// Nak error all subsequent requests
// Nak error all subsequent requests
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
return
;
return
;
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
// No response for all subsequent requests
// No response for all subsequent requests
return
;
return
;
}
else
{
}
else
{
// FIXME: Does not support directories that span multiple packets
// FIXME: Does not support directories that span multiple packets
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
}
}
}
}
/// @brief Handles Open command requests.
/// @brief Handles Open command requests.
void
Mock
MavlinkFileServer
::
_openCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
Mock
LinkFileServer
::
_openCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
{
FileManager
::
Request
response
;
FileManager
::
Request
response
;
QString
path
;
QString
path
;
...
@@ -129,7 +132,7 @@ void MockMavlinkFileServer::_openCommand(FileManager::Request* request, uint16_t
...
@@ -129,7 +132,7 @@ void MockMavlinkFileServer::_openCommand(FileManager::Request* request, uint16_t
}
}
}
}
if
(
!
found
)
{
if
(
!
found
)
{
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdOpenFileRO
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdOpenFileRO
);
return
;
return
;
}
}
...
@@ -141,16 +144,16 @@ void MockMavlinkFileServer::_openCommand(FileManager::Request* request, uint16_t
...
@@ -141,16 +144,16 @@ void MockMavlinkFileServer::_openCommand(FileManager::Request* request, uint16_t
response
.
hdr
.
size
=
sizeof
(
uint32_t
);
response
.
hdr
.
size
=
sizeof
(
uint32_t
);
response
.
openFileLength
=
_readFileLength
;
response
.
openFileLength
=
_readFileLength
;
_
emitResponse
(
&
response
,
outgoingSeqNumber
);
_
sendResponse
(
senderSystemId
,
senderComponentId
,
&
response
,
outgoingSeqNumber
);
}
}
void
Mock
MavlinkFileServer
::
_readCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
Mock
LinkFileServer
::
_readCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
{
FileManager
::
Request
response
;
FileManager
::
Request
response
;
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
return
;
return
;
}
}
...
@@ -161,7 +164,7 @@ void MockMavlinkFileServer::_readCommand(FileManager::Request* request, uint16_t
...
@@ -161,7 +164,7 @@ void MockMavlinkFileServer::_readCommand(FileManager::Request* request, uint16_t
// If we get here it means the client is requesting additional data past the first request
// If we get here it means the client is requesting additional data past the first request
if
(
_errMode
==
errModeNakSecondResponse
)
{
if
(
_errMode
==
errModeNakSecondResponse
)
{
// Nak error all subsequent requests
// Nak error all subsequent requests
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
return
;
return
;
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
// No rsponse for all subsequent requests
// No rsponse for all subsequent requests
...
@@ -170,7 +173,7 @@ void MockMavlinkFileServer::_readCommand(FileManager::Request* request, uint16_t
...
@@ -170,7 +173,7 @@ void MockMavlinkFileServer::_readCommand(FileManager::Request* request, uint16_t
}
}
if
(
readOffset
>=
_readFileLength
)
{
if
(
readOffset
>=
_readFileLength
)
{
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
return
;
return
;
}
}
...
@@ -188,16 +191,16 @@ void MockMavlinkFileServer::_readCommand(FileManager::Request* request, uint16_t
...
@@ -188,16 +191,16 @@ void MockMavlinkFileServer::_readCommand(FileManager::Request* request, uint16_t
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdReadFile
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdReadFile
;
_
emitResponse
(
&
response
,
outgoingSeqNumber
);
_
sendResponse
(
senderSystemId
,
senderComponentId
,
&
response
,
outgoingSeqNumber
);
}
}
void
Mock
MavlinkFileServer
::
_streamCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
Mock
LinkFileServer
::
_streamCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
{
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
FileManager
::
Request
response
;
FileManager
::
Request
response
;
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
return
;
return
;
}
}
...
@@ -212,7 +215,7 @@ void MockMavlinkFileServer::_streamCommand(FileManager::Request* request, uint16
...
@@ -212,7 +215,7 @@ void MockMavlinkFileServer::_streamCommand(FileManager::Request* request, uint16
// If we get here it means the client is requesting additional data past the first request
// If we get here it means the client is requesting additional data past the first request
if
(
_errMode
==
errModeNakSecondResponse
)
{
if
(
_errMode
==
errModeNakSecondResponse
)
{
// Nak error all subsequent requests
// Nak error all subsequent requests
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
return
;
return
;
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
// No response for all subsequent requests
// No response for all subsequent requests
...
@@ -234,103 +237,115 @@ void MockMavlinkFileServer::_streamCommand(FileManager::Request* request, uint16
...
@@ -234,103 +237,115 @@ void MockMavlinkFileServer::_streamCommand(FileManager::Request* request, uint16
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdBurstReadFile
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdBurstReadFile
;
_
emitResponse
(
&
response
,
outgoingSeqNumber
);
_
sendResponse
(
senderSystemId
,
senderComponentId
,
&
response
,
outgoingSeqNumber
);
outgoingSeqNumber
=
_nextSeqNumber
(
outgoingSeqNumber
);
outgoingSeqNumber
=
_nextSeqNumber
(
outgoingSeqNumber
);
ackOffset
+=
cDataAck
;
ackOffset
+=
cDataAck
;
}
}
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
}
}
/// @brief Handles Terminate commands
void
MockLinkFileServer
::
_terminateCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_terminateCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
{
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
_sendNak
(
FileManager
::
kErrInvalidSession
,
outgoingSeqNumber
,
FileManager
::
kCmdTerminateSession
);
_sendNak
(
senderSystemId
,
senderComponentId
,
FileManager
::
kErrInvalidSession
,
outgoingSeqNumber
,
FileManager
::
kCmdTerminateSession
);
return
;
return
;
}
}
_sendAck
(
outgoingSeqNumber
,
FileManager
::
kCmdTerminateSession
);
_sendAck
(
senderSystemId
,
senderComponentId
,
outgoingSeqNumber
,
FileManager
::
kCmdTerminateSession
);
// Let our test harness know that we got a terminate command. This is used to validate the a Terminate is correctly
// sent after an Open.
emit
terminateCommandReceived
();
emit
terminateCommandReceived
();
}
}
/// @brief Handles messages sent to the FTP server.
void
MockLinkFileServer
::
_resetCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
sendMessage
(
mavlink_message_t
message
)
{
{
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
_sendAck
(
senderSystemId
,
senderComponentId
,
outgoingSeqNumber
,
FileManager
::
kCmdResetSessions
);
emit
resetCommandReceived
();
}
void
MockLinkFileServer
::
handleFTPMessage
(
const
mavlink_message_t
&
message
)
{
if
(
message
.
msgid
!=
MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL
)
{
return
;
}
FileManager
::
Request
ackResponse
;
FileManager
::
Request
ackResponse
;
Q_ASSERT
(
message
.
msgid
==
MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL
);
mavlink_file_transfer_protocol_t
requestFTP
;
mavlink_msg_file_transfer_protocol_decode
(
&
message
,
&
requestFTP
);
mavlink_file_transfer_protocol_t
requestFileTransferProtocol
;
if
(
requestFTP
.
target_system
!=
_systemIdServer
)
{
mavlink_msg_file_transfer_protocol_decode
(
&
message
,
&
requestFileTransferProtocol
)
;
return
;
FileManager
::
Request
*
request
=
(
FileManager
::
Request
*
)
&
requestFileTransferProtocol
.
payload
[
0
];
}
Q_ASSERT
(
requestFileTransferProtocol
.
target_system
==
_systemIdServer
)
;
FileManager
::
Request
*
request
=
(
FileManager
::
Request
*
)
&
requestFTP
.
payload
[
0
]
;
uint16_t
incomingSeqNumber
=
request
->
hdr
.
seqNumber
;
uint16_t
incomingSeqNumber
=
request
->
hdr
.
seqNumber
;
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
incomingSeqNumber
);
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
incomingSeqNumber
);
if
(
request
->
hdr
.
opcode
!=
FileManager
::
kCmdResetSessions
&&
request
->
hdr
.
opcode
!=
FileManager
::
kCmdTerminateSession
)
{
if
(
_errMode
==
errModeNoResponse
)
{
if
(
_errMode
==
errModeNoResponse
)
{
// Don't respond to any requests, this shold cause the client to eventually timeout waiting for the ack
// Don't respond to any requests, this shold cause the client to eventually timeout waiting for the ack
return
;
return
;
}
else
if
(
_errMode
==
errModeNakResponse
)
{
}
else
if
(
_errMode
==
errModeNakResponse
)
{
// Nak all requests, the actual error send back doesn't really matter as long as it's an error
// Nak all requests, the actual error send back doesn't really matter as long as it's an error
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
(
FileManager
::
Opcode
)
request
->
hdr
.
opcode
);
_sendNak
(
message
.
sysid
,
message
.
compid
,
FileManager
::
kErrFail
,
outgoingSeqNumber
,
(
FileManager
::
Opcode
)
request
->
hdr
.
opcode
);
return
;
return
;
}
}
}
switch
(
request
->
hdr
.
opcode
)
{
switch
(
request
->
hdr
.
opcode
)
{
case
FileManager
:
:
kCmdTestNoAck
:
case
FileManager
:
:
kCmdTestNoAck
:
// ignored, ack not sent back, for testing only
// ignored, ack not sent back, for testing only
break
;
break
;
case
FileManager
:
:
kCmdResetSessions
:
// terminates all sessions
// Fall through to send back Ack
case
FileManager
:
:
kCmdNone
:
case
FileManager
:
:
kCmdNone
:
// ignored, always acked
// ignored, always acked
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
size
=
0
;
ackResponse
.
hdr
.
size
=
0
;
_
emitResponse
(
&
ackResponse
,
outgoingSeqNumber
);
_
sendResponse
(
message
.
sysid
,
message
.
compid
,
&
ackResponse
,
outgoingSeqNumber
);
break
;
break
;
case
FileManager
:
:
kCmdListDirectory
:
case
FileManager
:
:
kCmdListDirectory
:
_listCommand
(
request
,
incomingSeqNumber
);
_listCommand
(
message
.
sysid
,
message
.
compid
,
request
,
incomingSeqNumber
);
break
;
break
;
case
FileManager
:
:
kCmdOpenFileRO
:
case
FileManager
:
:
kCmdOpenFileRO
:
_openCommand
(
request
,
incomingSeqNumber
);
_openCommand
(
message
.
sysid
,
message
.
compid
,
request
,
incomingSeqNumber
);
break
;
break
;
case
FileManager
:
:
kCmdReadFile
:
case
FileManager
:
:
kCmdReadFile
:
_readCommand
(
request
,
incomingSeqNumber
);
_readCommand
(
message
.
sysid
,
message
.
compid
,
request
,
incomingSeqNumber
);
break
;
break
;
case
FileManager
:
:
kCmdBurstReadFile
:
case
FileManager
:
:
kCmdBurstReadFile
:
_streamCommand
(
request
,
incomingSeqNumber
);
_streamCommand
(
message
.
sysid
,
message
.
compid
,
request
,
incomingSeqNumber
);
break
;
break
;
case
FileManager
:
:
kCmdTerminateSession
:
case
FileManager
:
:
kCmdTerminateSession
:
_terminateCommand
(
request
,
incomingSeqNumber
);
_terminateCommand
(
message
.
sysid
,
message
.
compid
,
request
,
incomingSeqNumber
);
break
;
case
FileManager
:
:
kCmdResetSessions
:
_resetCommand
(
message
.
sysid
,
message
.
compid
,
incomingSeqNumber
);
break
;
break
;
default:
default:
// nack for all NYI opcodes
// nack for all NYI opcodes
_sendNak
(
FileManager
::
kErrUnknownCommand
,
outgoingSeqNumber
,
(
FileManager
::
Opcode
)
request
->
hdr
.
opcode
);
_sendNak
(
message
.
sysid
,
message
.
compid
,
FileManager
::
kErrUnknownCommand
,
outgoingSeqNumber
,
(
FileManager
::
Opcode
)
request
->
hdr
.
opcode
);
break
;
break
;
}
}
}
}
/// @brief Sends an Ack
/// @brief Sends an Ack
void
Mock
MavlinkFileServer
::
_sendAck
(
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
)
void
Mock
LinkFileServer
::
_sendAck
(
uint8_t
targetSystemId
,
uint8_t
targetComponentId
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
)
{
{
FileManager
::
Request
ackResponse
;
FileManager
::
Request
ackResponse
;
...
@@ -339,11 +354,11 @@ void MockMavlinkFileServer::_sendAck(uint16_t seqNumber, FileManager::Opcode req
...
@@ -339,11 +354,11 @@ void MockMavlinkFileServer::_sendAck(uint16_t seqNumber, FileManager::Opcode req
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
size
=
0
;
ackResponse
.
hdr
.
size
=
0
;
_
emitResponse
(
&
ackResponse
,
seqNumber
);
_
sendResponse
(
targetSystemId
,
targetComponentId
,
&
ackResponse
,
seqNumber
);
}
}
/// @brief Sends a Nak with the specified error code.
/// @brief Sends a Nak with the specified error code.
void
Mock
MavlinkFileServer
::
_sendNak
(
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
)
void
Mock
LinkFileServer
::
_sendNak
(
uint8_t
targetSystemId
,
uint8_t
targetComponentId
,
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
)
{
{
FileManager
::
Request
nakResponse
;
FileManager
::
Request
nakResponse
;
...
@@ -353,11 +368,11 @@ void MockMavlinkFileServer::_sendNak(FileManager::ErrorCode error, uint16_t seqN
...
@@ -353,11 +368,11 @@ void MockMavlinkFileServer::_sendNak(FileManager::ErrorCode error, uint16_t seqN
nakResponse
.
hdr
.
size
=
1
;
nakResponse
.
hdr
.
size
=
1
;
nakResponse
.
data
[
0
]
=
error
;
nakResponse
.
data
[
0
]
=
error
;
_
emitResponse
(
&
nakResponse
,
seqNumber
);
_
sendResponse
(
targetSystemId
,
targetComponentId
,
&
nakResponse
,
seqNumber
);
}
}
/// @brief Emits a Request through the messageReceived signal.
/// @brief Emits a Request through the messageReceived signal.
void
Mock
MavlinkFileServer
::
_emitResponse
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
Mock
LinkFileServer
::
_sendResponse
(
uint8_t
targetSystemId
,
uint8_t
targetComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
{
mavlink_message_t
mavlinkMessage
;
mavlink_message_t
mavlinkMessage
;
...
@@ -367,16 +382,16 @@ void MockMavlinkFileServer::_emitResponse(FileManager::Request* request, uint16_
...
@@ -367,16 +382,16 @@ void MockMavlinkFileServer::_emitResponse(FileManager::Request* request, uint16_
0
,
// Component ID
0
,
// Component ID
&
mavlinkMessage
,
// Mavlink Message to pack into
&
mavlinkMessage
,
// Mavlink Message to pack into
0
,
// Target network
0
,
// Target network
_systemIdQGC
,
// QGC Target System ID
targetSystemId
,
0
,
// Target component
targetComponentId
,
(
uint8_t
*
)
request
);
// Payload
(
uint8_t
*
)
request
);
// Payload
emit
messageReceived
(
NULL
,
mavlinkMessage
);
_mockLink
->
respondWithMavlinkMessage
(
mavlinkMessage
);
}
}
/// @brief Generates the next sequence number given an incoming sequence number. Handles generating
/// @brief Generates the next sequence number given an incoming sequence number. Handles generating
/// bad sequence numbers when errModeBadSequence is set.
/// bad sequence numbers when errModeBadSequence is set.
uint16_t
Mock
Mavl
inkFileServer
::
_nextSeqNumber
(
uint16_t
seqNumber
)
uint16_t
Mock
L
inkFileServer
::
_nextSeqNumber
(
uint16_t
seqNumber
)
{
{
uint16_t
outgoingSeqNumber
=
seqNumber
+
1
;
uint16_t
outgoingSeqNumber
=
seqNumber
+
1
;
...
...
src/
qgcunittest/MockMavl
inkFileServer.h
→
src/
comm/MockL
inkFileServer.h
View file @
bc71d49d
...
@@ -21,29 +21,25 @@
...
@@ -21,29 +21,25 @@
======================================================================*/
======================================================================*/
#ifndef MOCKMAVLINKFILESERVER_H
#define MOCKMAVLINKFILESERVER_H
#include "MockMavlinkInterface.h"
#include "FileManager.h"
/// @file
/// @file
/// @brief Mock implementation of Mavlink FTP server. Used as mavlink plugin to MockUAS.
/// Only root directory access is supported.
///
/// @author Don Gagne <don@thegagnes.com>
/// @author Don Gagne <don@thegagnes.com>
#ifndef MockLinkFileServer_H
#define MockLinkFileServer_H
#include "FileManager.h"
#include <QStringList>
#include <QStringList>
class
MockMavlinkFileServer
:
public
MockMavlinkInterface
class
MockLink
;
/// Mock implementation of Mavlink FTP server.
class
MockLinkFileServer
:
public
QObject
{
{
Q_OBJECT
Q_OBJECT
public:
public:
/// @brief Constructor for MockMavlinkFileServer
MockLinkFileServer
(
uint8_t
systemIdServer
,
uint8_t
componentIdServer
,
MockLink
*
mockLink
);
/// @param System ID for QGroundControl App
/// @pqram System ID for this Server
MockMavlinkFileServer
(
uint8_t
systemIdQGC
,
uint8_t
systemIdServer
);
/// @brief Sets the list of files returned by the List command. Prepend names with F or D
/// @brief Sets the list of files returned by the List command. Prepend names with F or D
/// to indicate (F)ile or (D)irectory.
/// to indicate (F)ile or (D)irectory.
...
@@ -70,8 +66,8 @@ public:
...
@@ -70,8 +66,8 @@ public:
/// @brief The number of ErrorModes in the rgFailureModes array.
/// @brief The number of ErrorModes in the rgFailureModes array.
static
const
size_t
cFailureModes
;
static
const
size_t
cFailureModes
;
//
From MockMavlinkInterfac
e
//
/ Called to handle an FTP messag
e
v
irtual
void
sendMessage
(
mavlink_message_t
message
);
v
oid
handleFTPMessage
(
const
mavlink_message_t
&
message
);
/// @brief Used to represent a single test case for download testing.
/// @brief Used to represent a single test case for download testing.
struct
FileTestCase
{
struct
FileTestCase
{
...
@@ -88,18 +84,22 @@ public:
...
@@ -88,18 +84,22 @@ public:
static
const
FileTestCase
rgFileTestCases
[
cFileTestCases
];
static
const
FileTestCase
rgFileTestCases
[
cFileTestCases
];
signals:
signals:
///
@brief
You can connect to this signal to be notified when the server receives a Terminate command.
/// You can connect to this signal to be notified when the server receives a Terminate command.
void
terminateCommandReceived
(
void
);
void
terminateCommandReceived
(
void
);
/// You can connect to this signal to be notified when the server receives a Reset command.
void
resetCommandReceived
(
void
);
private:
private:
void
_sendAck
(
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
);
void
_sendAck
(
uint8_t
targetSystemId
,
uint8_t
targetComponentId
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
);
void
_sendNak
(
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
);
void
_sendNak
(
uint8_t
targetSystemId
,
uint8_t
targetComponentId
,
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
);
void
_emitResponse
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_sendResponse
(
uint8_t
targetSystemId
,
uint8_t
targetComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_listCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_listCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_openCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_openCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_readCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_readCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_streamCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_streamCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_terminateCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_terminateCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_resetCommand
(
uint8_t
senderSystemId
,
uint8_t
senderComponentId
,
uint16_t
seqNumber
);
uint16_t
_nextSeqNumber
(
uint16_t
seqNumber
);
uint16_t
_nextSeqNumber
(
uint16_t
seqNumber
);
QStringList
_fileList
;
///< List of files returned by List command
QStringList
_fileList
;
///< List of files returned by List command
...
@@ -108,7 +108,8 @@ private:
...
@@ -108,7 +108,8 @@ private:
uint8_t
_readFileLength
;
///< Length of active file being read
uint8_t
_readFileLength
;
///< Length of active file being read
ErrorMode_t
_errMode
;
///< Currently set error mode, as specified by setErrorMode
ErrorMode_t
_errMode
;
///< Currently set error mode, as specified by setErrorMode
const
uint8_t
_systemIdServer
;
///< System ID for server
const
uint8_t
_systemIdServer
;
///< System ID for server
const
uint8_t
_systemIdQGC
;
///< QGC System ID
const
uint8_t
_componentIdServer
;
///< Component ID for server
MockLink
*
_mockLink
;
///< MockLink to communicate through
};
};
#endif
#endif
src/qgcunittest/FileManagerTest.cc
View file @
bc71d49d
...
@@ -21,37 +21,21 @@
...
@@ -21,37 +21,21 @@
======================================================================*/
======================================================================*/
#include "FileManagerTest.h"
/// @file
/// @file
/// @brief FileManager unit test. Note: All code here assumes all work between
/// the unit test, mack mavlink file server and file manager is happening on
/// the same thread.
///
/// @author Don Gagne <don@thegagnes.com>
/// @author Don Gagne <don@thegagnes.com>
#include "FileManagerTest.h"
#include "UASManager.h"
UT_REGISTER_TEST
(
FileManagerTest
)
UT_REGISTER_TEST
(
FileManagerTest
)
FileManagerTest
::
FileManagerTest
(
void
)
:
FileManagerTest
::
FileManagerTest
(
void
)
:
_mockFileServer
(
_systemIdQGC
,
_systemIdServer
),
_mockLink
(
NULL
),
_fileServer
(
NULL
),
_fileManager
(
NULL
),
_fileManager
(
NULL
),
_multiSpy
(
NULL
)
_multiSpy
(
NULL
)
{
{
}
// Called once before all test cases are run
void
FileManagerTest
::
initTestCase
(
void
)
{
_mockUAS
=
new
MockUAS
();
Q_CHECK_PTR
(
_mockUAS
);
_mockUAS
->
setMockSystemId
(
_systemIdServer
);
_mockUAS
->
setMockMavlinkPlugin
(
&
_mockFileServer
);
}
void
FileManagerTest
::
cleanupTestCase
(
void
)
{
delete
_mockUAS
;
}
}
// Called before every test case
// Called before every test case
...
@@ -59,26 +43,37 @@ void FileManagerTest::init(void)
...
@@ -59,26 +43,37 @@ void FileManagerTest::init(void)
{
{
UnitTest
::
init
();
UnitTest
::
init
();
Q_ASSERT
(
_multiSpy
==
NULL
);
_mockLink
=
new
MockLink
();
Q_CHECK_PTR
(
_mockLink
);
LinkManager
::
instance
()
->
_addLink
(
_mockLink
);
LinkManager
::
instance
()
->
connectLink
(
_mockLink
);
_fileServer
=
_mockLink
->
getFileServer
();
QVERIFY
(
_fileServer
!=
NULL
);
// Wait or the UAS to show up
UASManagerInterface
*
uasManager
=
UASManager
::
instance
();
QSignalSpy
spyUasCreate
(
uasManager
,
SIGNAL
(
UASCreated
(
UASInterface
*
)));
if
(
!
uasManager
->
getActiveUAS
())
{
QCOMPARE
(
spyUasCreate
.
wait
(
10000
),
true
);
}
UASInterface
*
uas
=
uasManager
->
getActiveUAS
();
QVERIFY
(
uas
!=
NULL
);
_fileManager
=
new
FileManager
(
NULL
,
_mockUAS
,
_systemIdQGC
);
_fileManager
=
uas
->
getFileManager
();
Q_CHECK_PTR
(
_fileManager
);
QVERIFY
(
_fileManager
!=
NULL
);
Q_ASSERT
(
_multiSpy
==
NULL
);
// Reset any internal state back to normal
// Reset any internal state back to normal
_
mockFileServer
.
setErrorMode
(
MockMavl
inkFileServer
::
errModeNone
);
_
fileServer
->
setErrorMode
(
MockL
inkFileServer
::
errModeNone
);
_fileListReceived
.
clear
();
_fileListReceived
.
clear
();
connect
(
&
_mockFileServer
,
&
MockMavlinkFileServer
::
messageReceived
,
_fileManager
,
&
FileManager
::
receiveMessage
);
connect
(
_fileManager
,
&
FileManager
::
listEntry
,
this
,
&
FileManagerTest
::
listEntry
);
connect
(
_fileManager
,
&
FileManager
::
listEntry
,
this
,
&
FileManagerTest
::
listEntry
);
_rgSignals
[
listEntrySignalIndex
]
=
SIGNAL
(
listEntry
(
const
QString
&
));
_rgSignals
[
listEntrySignalIndex
]
=
SIGNAL
(
listEntry
(
const
QString
&
));
_rgSignals
[
listCompleteSignalIndex
]
=
SIGNAL
(
listComplete
(
void
));
_rgSignals
[
commandCompleteSignalIndex
]
=
SIGNAL
(
commandComplete
(
void
));
_rgSignals
[
commandErrorSignalIndex
]
=
SIGNAL
(
commandError
(
const
QString
&
));
_rgSignals
[
downloadFileLengthSignalIndex
]
=
SIGNAL
(
downloadFileLength
(
unsigned
int
));
_rgSignals
[
downloadFileCompleteSignalIndex
]
=
SIGNAL
(
downloadFileComplete
(
void
));
_rgSignals
[
errorMessageSignalIndex
]
=
SIGNAL
(
errorMessage
(
const
QString
&
));
_multiSpy
=
new
MultiSignalSpy
();
_multiSpy
=
new
MultiSignalSpy
();
Q_CHECK_PTR
(
_multiSpy
);
Q_CHECK_PTR
(
_multiSpy
);
...
@@ -91,10 +86,15 @@ void FileManagerTest::cleanup(void)
...
@@ -91,10 +86,15 @@ void FileManagerTest::cleanup(void)
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_fileManager
);
delete
_fileManager
;
// Disconnecting the link will prompt for log file save
setExpectedFileDialog
(
getSaveFileName
,
QStringList
());
LinkManager
::
instance
()
->
disconnectLink
(
_mockLink
);
_fileServer
=
NULL
;
_mockLink
=
NULL
;
_fileManager
=
NULL
;
delete
_multiSpy
;
delete
_multiSpy
;
_fileManager
=
NULL
;
_multiSpy
=
NULL
;
_multiSpy
=
NULL
;
UnitTest
::
cleanup
();
UnitTest
::
cleanup
();
...
@@ -108,7 +108,6 @@ void FileManagerTest::listEntry(const QString& entry)
...
@@ -108,7 +108,6 @@ void FileManagerTest::listEntry(const QString& entry)
}
}
#if 0
void
FileManagerTest
::
_ackTest
(
void
)
void
FileManagerTest
::
_ackTest
(
void
)
{
{
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_fileManager
);
...
@@ -122,16 +121,17 @@ void FileManagerTest::_ackTest(void)
...
@@ -122,16 +121,17 @@ void FileManagerTest::_ackTest(void)
QVERIFY
(
_multiSpy
->
checkNoSignals
());
QVERIFY
(
_multiSpy
->
checkNoSignals
());
// Setup for no response from ack. This should cause a timeout error
// Setup for no response from ack. This should cause a timeout error
_
mockFileServer.setErrorMode(MockMavl
inkFileServer::errModeNoResponse);
_
fileServer
->
setErrorMode
(
MockL
inkFileServer
::
errModeNoResponse
);
QVERIFY
(
_fileManager
->
_sendCmdTestAck
());
QVERIFY
(
_fileManager
->
_sendCmdTestAck
());
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
_multiSpy
->
waitForSignalByIndex
(
commandErrorSignalIndex
,
_ackTimerTimeoutMsecs
);
QCOMPARE(_multiSpy->checkOnlySignalByMask(
errorMessage
SignalMask), true);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
commandError
SignalMask
),
true
);
_multiSpy
->
clearAllSignals
();
_multiSpy
->
clearAllSignals
();
// Setup for a bad sequence number in the ack. This should cause an error;
// Setup for a bad sequence number in the ack. This should cause an error;
_
mockFileServer.setErrorMode(MockMavl
inkFileServer::errModeBadSequence);
_
fileServer
->
setErrorMode
(
MockL
inkFileServer
::
errModeBadSequence
);
QVERIFY
(
_fileManager
->
_sendCmdTestAck
());
QVERIFY
(
_fileManager
->
_sendCmdTestAck
());
QCOMPARE(_multiSpy->checkOnlySignalByMask(errorMessageSignalMask), true);
_multiSpy
->
waitForSignalByIndex
(
commandErrorSignalIndex
,
_ackTimerTimeoutMsecs
);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
commandErrorSignalMask
),
true
);
_multiSpy
->
clearAllSignals
();
_multiSpy
->
clearAllSignals
();
}
}
...
@@ -144,19 +144,7 @@ void FileManagerTest::_noAckTest(void)
...
@@ -144,19 +144,7 @@ void FileManagerTest::_noAckTest(void)
// This should not get the ack back and timeout.
// This should not get the ack back and timeout.
QVERIFY
(
_fileManager
->
_sendCmdTestNoAck
());
QVERIFY
(
_fileManager
->
_sendCmdTestNoAck
());
QTest
::
qWait
(
_ackTimerTimeoutMsecs
);
// Let the file manager timeout
QTest
::
qWait
(
_ackTimerTimeoutMsecs
);
// Let the file manager timeout
QCOMPARE(_multiSpy->checkOnlySignalByMask(errorMessageSignalMask), true);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
commandErrorSignalMask
),
true
);
}
void FileManagerTest::_resetTest(void)
{
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
// Send a reset command
// We should not get any signals back from this
QVERIFY(_fileManager->_sendCmdReset());
QVERIFY(_multiSpy->checkNoSignals());
}
}
void
FileManagerTest
::
_listTest
(
void
)
void
FileManagerTest
::
_listTest
(
void
)
...
@@ -167,37 +155,49 @@ void FileManagerTest::_listTest(void)
...
@@ -167,37 +155,49 @@ void FileManagerTest::_listTest(void)
// FileManager::listDirectory signalling as follows:
// FileManager::listDirectory signalling as follows:
// Emits a listEntry signal for each list entry
// Emits a listEntry signal for each list entry
// Emits an
errorMessage
signal if:
// Emits an
commandError
signal if:
// It gets a Nak back
// It gets a Nak back
// Sequence number is incorrrect on any response
// Sequence number is incorrrect on any response
// CRC is incorrect on any responses
// CRC is incorrect on any responses
// List entry is formatted incorrectly
// List entry is formatted incorrectly
// It is possible to get a number of good listEntry signals, followed by an
errorMessage
signal
// It is possible to get a number of good listEntry signals, followed by an
commandError
signal
// Emits
list
Complete after it receives the final list entry
// Emits
command
Complete after it receives the final list entry
// If an
errorMessage
signal is signalled no listComplete is signalled
// If an
commandError
signal is signalled no listComplete is signalled
// Send a bogus path
// Send a bogus path
// We should get a single resetStatusMessages signal
// We should get a single commandError signal
// We should get a single errorMessage signal
_fileManager
->
listDirectory
(
"/bogus"
);
_fileManager
->
listDirectory
(
"/bogus"
);
QCOMPARE(_multiSpy->checkOnlySignalByMask(errorMessageSignalMask), true);
_multiSpy
->
waitForSignalByIndex
(
commandErrorSignalIndex
,
_ackTimerTimeoutMsecs
);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
commandErrorSignalMask
),
true
);
_multiSpy
->
clearAllSignals
();
_multiSpy
->
clearAllSignals
();
// Setup the mock file server with a valid directory list
// Setup the mock file server with a valid directory list
QStringList
fileList
;
QStringList
fileList
;
fileList
<<
"Ddir"
<<
"Ffoo"
<<
"Fbar"
;
fileList
<<
"Ddir"
<<
"Ffoo"
<<
"Fbar"
;
_mockFileServer.setFileList(fileList);
_fileServer
->
setFileList
(
fileList
);
// Send a list command at the root of the directory tree which should succeed
_fileManager
->
listDirectory
(
"/"
);
QTest
::
qWait
(
_ackTimerTimeoutMsecs
);
// Let the file manager timeout
QCOMPARE
(
_multiSpy
->
checkSignalByMask
(
commandCompleteSignalMask
),
true
);
QCOMPARE
(
_multiSpy
->
checkNoSignalByMask
(
commandErrorSignalMask
),
true
);
QCOMPARE
(
_multiSpy
->
getSpyByIndex
(
listEntrySignalIndex
)
->
count
(),
fileList
.
count
());
QVERIFY
(
_fileListReceived
==
fileList
);
// Set everything back to initial state
_fileListReceived
.
clear
();
_multiSpy
->
clearAllSignals
();
// Run through the various server side failure modes
// Run through the various server side failure modes
for (size_t i=0; i<Mock
Mavl
inkFileServer::cFailureModes; i++) {
for
(
size_t
i
=
0
;
i
<
Mock
L
inkFileServer
::
cFailureModes
;
i
++
)
{
Mock
MavlinkFileServer::ErrorMode_t errMode = MockMavl
inkFileServer::rgFailureModes[i];
Mock
LinkFileServer
::
ErrorMode_t
errMode
=
MockL
inkFileServer
::
rgFailureModes
[
i
];
qDebug
()
<<
"Testing failure mode:"
<<
errMode
;
qDebug
()
<<
"Testing failure mode:"
<<
errMode
;
_
mockFileServer.
setErrorMode(errMode);
_
fileServer
->
setErrorMode
(
errMode
);
_fileManager
->
listDirectory
(
"/"
);
_fileManager
->
listDirectory
(
"/"
);
QTest
::
qWait
(
_ackTimerTimeoutMsecs
);
// Let the file manager timeout
QTest
::
qWait
(
_ackTimerTimeoutMsecs
);
// Let the file manager timeout
if (errMode == Mock
MavlinkFileServer::errModeNoSecondResponse || errMode == MockMavl
inkFileServer::errModeNakSecondResponse) {
if
(
errMode
==
Mock
LinkFileServer
::
errModeNoSecondResponse
||
errMode
==
MockL
inkFileServer
::
errModeNakSecondResponse
)
{
// For simulated server errors on subsequent Acks, the first Ack will go through. This means we should have gotten some
// For simulated server errors on subsequent Acks, the first Ack will go through. This means we should have gotten some
// partial results. In the case of the directory list test set, all entries fit into the first ack, so we should have
// partial results. In the case of the directory list test set, all entries fit into the first ack, so we should have
// gotten back all of them.
// gotten back all of them.
...
@@ -205,145 +205,108 @@ void FileManagerTest::_listTest(void)
...
@@ -205,145 +205,108 @@ void FileManagerTest::_listTest(void)
_multiSpy
->
clearSignalByIndex
(
listEntrySignalIndex
);
_multiSpy
->
clearSignalByIndex
(
listEntrySignalIndex
);
// And then it should have errored out because the next list Request would have failed.
// And then it should have errored out because the next list Request would have failed.
QCOMPARE(_multiSpy->checkOnlySignalByMask(
errorMessage
SignalMask), true);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
commandError
SignalMask
),
true
);
}
else
{
}
else
{
// For the simulated errors which failed the intial response we should not have gotten any results back at all.
// For the simulated errors which failed the intial response we should not have gotten any results back at all.
// Just an error.
// Just an error.
QCOMPARE(_multiSpy->checkOnlySignalByMask(
errorMessage
SignalMask), true);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
commandError
SignalMask
),
true
);
}
}
// Set everything back to initial state
// Set everything back to initial state
_fileListReceived
.
clear
();
_fileListReceived
.
clear
();
_multiSpy
->
clearAllSignals
();
_multiSpy
->
clearAllSignals
();
_
mockFileServer.setErrorMode(MockMavl
inkFileServer::errModeNone);
_
fileServer
->
setErrorMode
(
MockL
inkFileServer
::
errModeNone
);
}
}
// Send a list command at the root of the directory tree which should succeed
_fileManager->listDirectory("/");
QCOMPARE(_multiSpy->checkSignalByMask(listCompleteSignalMask), true);
QCOMPARE(_multiSpy->checkNoSignalByMask(errorMessageSignalMask), true);
QCOMPARE(_multiSpy->getSpyByIndex(listEntrySignalIndex)->count(), fileList.count());
QVERIFY(_fileListReceived == fileList);
}
}
#if 0
// Trying to write test code for read and burst mode download as well as implement support in MockLineFileServer reached a point
// of diminishing returns where the test code and mock server were generating more bugs in themselves than finding problems.
void FileManagerTest::_readDownloadTest(void)
void FileManagerTest::_readDownloadTest(void)
{
{
Q_ASSERT(_fileManager);
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
// FileManager::downloadPath works as follows:
// We setup a spy on the Reset command signal of the mock file server so that we can determine that a
// Sends an Open Command to the server
// Reset command was correctly sent after the Open/Read commands complete.
// Expects an Ack Response back from the server with the correct sequence numner
QSignalSpy resetSpy(_fileServer, SIGNAL(resetCommandReceived()));
// Emits an errorMessage signal if it gets a Nak back
// Emits an downloadFileLength signal with the file length if it gets back a good Ack
// Sends subsequent Read commands to the server until it gets the full file contents back
// Emits a downloadFileProgress for each read command ack it gets back
// Sends Terminate command to server when download is complete to close Open command
// Mock file server will signal terminateCommandReceived when it gets a Terminate command
// Sends downloadFileComplete signal to indicate the download is complete
// Emits an errorMessage signal if sequence number is incorrrect on any response
// Emits an errorMessage signal if CRC is incorrect on any responses
// Expected signals if the Open command fails for any reason
quint16 signalMaskOpenFailure = errorMessageSignalMask;
// Expected signals if the Read command fails for any reason
quint16 signalMaskReadFailure = downloadFileLengthSignalMask | errorMessageSignalMask;
// Expected signals if the downloadPath command succeeds
quint16 signalMaskDownloadSuccess = downloadFileLengthSignalMask | downloadFileCompleteSignalMask;
// Send a bogus path
// Send a bogus path
// We should get a single resetStatusMessages signal
// We should get a single errorMessage signal
_fileManager->downloadPath("bogus", QDir::temp());
_fileManager->downloadPath("bogus", QDir::temp());
QCOMPARE(_multiSpy->checkOnlySignalByMask(signalMaskOpenFailure), true);
_multiSpy->waitForSignalByIndex(commandErrorSignalIndex, _ackTimerTimeoutMsecs);
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandErrorSignalMask), true);
_multiSpy->clearAllSignals();
_multiSpy->clearAllSignals();
QCOMPARE(resetSpy.count(), 0);
// Clean previous downloads
// Clean previous downloads
for (size_t i=0; i<Mock
Mavl
inkFileServer::cFileTestCases; i++) {
for (size_t i=0; i<Mock
L
inkFileServer::cFileTestCases; i++) {
QString filePath = QDir::temp().absoluteFilePath(Mock
Mavl
inkFileServer::rgFileTestCases[i].filename);
QString filePath = QDir::temp().absoluteFilePath(Mock
L
inkFileServer::rgFileTestCases[i].filename);
if (QFile::exists(filePath)) {
if (QFile::exists(filePath)) {
Q_ASSERT(QFile::remove(filePath));
Q_ASSERT(QFile::remove(filePath));
}
}
}
}
// We setup a spy on the Terminate command signal of the mock file server so that we can determine that a
// Terminate command was correctly sent after the Open/Read commands complete.
QSignalSpy terminateSpy(&_mockFileServer, SIGNAL(terminateCommandReceived()));
// Run through the set of file test cases
// Run through the set of file test cases
for (size_t i=0; i<Mock
Mavl
inkFileServer::cFileTestCases; i++) {
for (size_t i=0; i<Mock
L
inkFileServer::cFileTestCases; i++) {
const Mock
MavlinkFileServer::FileTestCase* testCase = &MockMavl
inkFileServer::rgFileTestCases[i];
const Mock
LinkFileServer::FileTestCase* testCase = &MockL
inkFileServer::rgFileTestCases[i];
// Run through the various failure modes for this test case
// Run through the various failure modes for this test case
for (size_t j=0; j<MockMavlinkFileServer::cFailureModes; j++) {
for (size_t j=0; j<MockLinkFileServer::cFailureModes; j++) {
qDebug() << "Testing successful download";
// Run what should be a successful file download test case. No servers errors are being simulated.
_fileServer->setErrorMode(MockLinkFileServer::errModeNone);
_fileManager->downloadPath(testCase->filename, QDir::temp());
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
// This should be a succesful download
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandCompleteSignalMask), true);
_multiSpy->clearAllSignals();
// We should get a single Reset command to close the session
QCOMPARE(resetSpy.count(), 1);
resetSpy.clear();
// Validate file contents
QString filePath = QDir::temp().absoluteFilePath(MockLinkFileServer::rgFileTestCases[i].filename);
_validateFileContents(filePath, MockLinkFileServer::rgFileTestCases[i].length);
MockLinkFileServer::ErrorMode_t errMode = MockLinkFileServer::rgFailureModes[j];
MockMavlinkFileServer::ErrorMode_t errMode = MockMavlinkFileServer::rgFailureModes[j];
qDebug() << "Testing failure mode:" << errMode;
qDebug() << "Testing failure mode:" << errMode;
_
mockFileServer.
setErrorMode(errMode);
_
fileServer->
setErrorMode(errMode);
_fileManager->downloadPath(testCase->filename, QDir::temp());
_fileManager->downloadPath(testCase->filename, QDir::temp());
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
if (errMode == MockMavlinkFileServer::errModeNoSecondResponse || errMode == MockMavlinkFileServer::errModeNakSecondResponse) {
if (errMode == MockLinkFileServer::errModeNakResponse) {
// For simulated server errors on subsequent Acks, the first Ack will go through. We must handle things differently depending
// This will Nak the Open call which will fail the download, but not cause a Reset
// on whether the downloaded file requires multiple packets to complete the download.
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandErrorSignalMask), true);
if (testCase->fMultiPacketResponse) {
QCOMPARE(resetSpy.count(), 0);
// The downloaded file requires multiple Acks to complete. Hence first Read should have succeeded and sent one downloadFileComplete.
// Second Read should have failed.
QCOMPARE(_multiSpy->checkOnlySignalByMask(signalMaskReadFailure), true);
// Open command succeeded, so we should get a Terminate for the open
QCOMPARE(terminateSpy.count(), 1);
} else {
} else {
if (testCase->packetCount == 1 && (errMode == MockLinkFileServer::errModeNoSecondResponse || errMode == MockLinkFileServer::errModeNakSecondResponse)) {
// The downloaded file fits within a single Ack response, hence there is no second Read issued.
// The downloaded file fits within a single Ack response, hence there is no second Read issued.
// This should result in a successful download.
// This should result in a successful download, followed by a Reset
QCOMPARE(_multiSpy->checkOnlySignalByMask(signalMaskDownloadSuccess), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandCompleteSignalMask), true);
QCOMPARE(resetSpy.count(), 1);
// We should get a single Terminate command to close the Open session
QCOMPARE(terminateSpy.count(), 1);
// Validate file contents
// Validate file contents
QString filePath = QDir::temp().absoluteFilePath(testCase->filename);
QString filePath = QDir::temp().absoluteFilePath(testCase->filename);
_validateFileContents(filePath, testCase->length);
_validateFileContents(filePath, testCase->length);
}
} else {
} else {
// For all the other simulated server errors the Open command should have failed. Since the Open failed
// Download should have failed, followed by a aReset
// there is no session to terminate, hence no Terminate in this case.
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandErrorSignalMask), true);
QCOMPARE(_multiSpy->checkOnlySignalByMask(signalMaskOpenFailure), true
);
QCOMPARE(resetSpy.count(), 1
);
QCOMPARE(terminateSpy.count(), 0);
}
}
}
// Cleanup for next iteration
// Cleanup for next iteration
_multiSpy->clearAllSignals();
_multiSpy->clearAllSignals();
terminate
Spy.clear();
reset
Spy.clear();
_
mockFileServer.setErrorMode(MockMavl
inkFileServer::errModeNone);
_
fileServer->setErrorMode(MockL
inkFileServer::errModeNone);
}
}
// Run what should be a successful file download test case. No servers errors are being simulated.
_mockFileServer.setErrorMode(MockMavlinkFileServer::errModeNone);
_fileManager->downloadPath(testCase->filename, QDir::temp());
// This should be a succesful download
QCOMPARE(_multiSpy->checkOnlySignalByMask(signalMaskDownloadSuccess), true);
// Make sure the file length coming back through the openFileLength signal is correct
QVERIFY(_multiSpy->getSpyByIndex(downloadFileLengthSignalIndex)->takeFirst().at(0).toInt() == testCase->length);
_multiSpy->clearAllSignals();
// We should get a single Terminate command to close the session
QCOMPARE(terminateSpy.count(), 1);
terminateSpy.clear();
// Validate file contents
QString filePath = QDir::temp().absoluteFilePath(MockMavlinkFileServer::rgFileTestCases[i].filename);
_validateFileContents(filePath, MockMavlinkFileServer::rgFileTestCases[i].length);
}
}
}
}
#endif
void FileManagerTest::_streamDownloadTest(void)
void FileManagerTest::_streamDownloadTest(void)
{
{
...
@@ -351,115 +314,83 @@ void FileManagerTest::_streamDownloadTest(void)
...
@@ -351,115 +314,83 @@ void FileManagerTest::_streamDownloadTest(void)
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
// FileManager::streamPath works as follows:
// We setup a spy on the Reset command signal of the mock file server so that we can determine that a
// Sends an Open Command to the server
// Reset command was correctly sent after the Open/Read commands complete.
// Expects an Ack Response back from the server with the correct sequence numner
QSignalSpy resetSpy(_fileServer, SIGNAL(resetCommandReceived()));
// Emits an errorMessage signal if it gets a Nak back
// Emits an downloadFileLength signal with the file length if it gets back a good Ack
// Sends a single Stream command to the server
// Expects continuous Ack responses back with file contents
// Emits a downloadFileProgress for each ack it gets back
// Sends Terminate command to server when download is complete to close Open command
// Mock file server will signal terminateCommandReceived when it gets a Terminate command
// Sends downloadFileComplete signal to indicate the download is complete
// Emits an errorMessage signal if sequence number is incorrrect on any response
// Emits an errorMessage signal if CRC is incorrect on any responses
// Expected signals if the Open command fails for any reason
quint16
signalMaskOpenFailure
=
errorMessageSignalMask
;
// Expected signals if the Read command fails for any reason
quint16
signalMaskReadFailure
=
downloadFileLengthSignalMask
|
errorMessageSignalMask
;
// Expected signals if the downloadPath command succeeds
quint16
signalMaskDownloadSuccess
=
downloadFileLengthSignalMask
|
downloadFileCompleteSignalMask
;
// Send a bogus path
// Send a bogus path
// We should get a single resetStatusMessages signal
// We should get a single errorMessage signal
_fileManager->streamPath("bogus", QDir::temp());
_fileManager->streamPath("bogus", QDir::temp());
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskOpenFailure
),
true
);
_multiSpy->waitForSignalByIndex(commandErrorSignalIndex, _ackTimerTimeoutMsecs);
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandErrorSignalMask), true);
_multiSpy->clearAllSignals();
_multiSpy->clearAllSignals();
QCOMPARE(resetSpy.count(), 0);
// Clean previous downloads
// Clean previous downloads
for
(
size_t
i
=
0
;
i
<
MockMavl
inkFileServer
::
cFileTestCases
;
i
++
)
{
for (size_t i=0; i<MockL
inkFileServer::cFileTestCases; i++) {
QString
filePath
=
QDir
::
temp
().
absoluteFilePath
(
MockMavl
inkFileServer
::
rgFileTestCases
[
i
].
filename
);
QString filePath = QDir::temp().absoluteFilePath(MockL
inkFileServer::rgFileTestCases[i].filename);
if (QFile::exists(filePath)) {
if (QFile::exists(filePath)) {
Q_ASSERT(QFile::remove(filePath));
Q_ASSERT(QFile::remove(filePath));
}
}
}
}
// We setup a spy on the Terminate command signal of the mock file server so that we can determine that a
// Terminate command was correctly sent after the Open/Read commands complete.
QSignalSpy
terminateSpy
(
&
_mockFileServer
,
SIGNAL
(
terminateCommandReceived
()));
// Run through the set of file test cases
// Run through the set of file test cases
for
(
size_t
i
=
0
;
i
<
MockMavl
inkFileServer
::
cFileTestCases
;
i
++
)
{
for (size_t i=0; i<MockL
inkFileServer::cFileTestCases; i++) {
const
MockMavlinkFileServer
::
FileTestCase
*
testCase
=
&
MockMavl
inkFileServer
::
rgFileTestCases
[
i
];
const MockLinkFileServer::FileTestCase* testCase = &MockL
inkFileServer::rgFileTestCases[i];
// Run through the various failure modes for this test case
// Run through the various failure modes for this test case
for
(
size_t
j
=
0
;
j
<
MockMavlinkFileServer
::
cFailureModes
;
j
++
)
{
for (size_t j=0; j<MockLinkFileServer::cFailureModes; j++) {
qDebug() << "Testing successful download";
MockMavlinkFileServer
::
ErrorMode_t
errMode
=
MockMavlinkFileServer
::
rgFailureModes
[
j
];
qDebug
()
<<
"Testing failure mode:"
<<
errMode
;
_mockFileServer
.
setErrorMode
(
errMode
);
// Run what should be a successful file download test case. No servers errors are being simulated.
_fileServer->setErrorMode(MockLinkFileServer::errModeNone);
_fileManager->streamPath(testCase->filename, QDir::temp());
_fileManager->streamPath(testCase->filename, QDir::temp());
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
if
(
errMode
==
MockMavlinkFileServer
::
errModeNoSecondResponse
||
errMode
==
MockMavlinkFileServer
::
errModeNakSecondResponse
)
{
// This should be a succesful download
// For simulated server errors on subsequent Acks, the first Ack will go through. We must handle things differently depending
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandCompleteSignalMask), true);
// on whether the downloaded file requires multiple packets to complete the download.
_multiSpy->clearAllSignals();
if
(
testCase
->
packetCount
!=
1
)
{
// The downloaded file requires multiple Acks to complete. Second Ack should have failed.
// We should get a single Reset command to close the session
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskReadFailure
),
true
);
QCOMPARE(resetSpy.count(), 1);
resetSpy.clear();
// Open command succeeded, so we should get a Terminate for the open
// Validate file contents
QCOMPARE
(
terminateSpy
.
count
(),
1
);
QString filePath = QDir::temp().absoluteFilePath(MockLinkFileServer::rgFileTestCases[i].filename);
_validateFileContents(filePath, MockLinkFileServer::rgFileTestCases[i].length);
MockLinkFileServer::ErrorMode_t errMode = MockLinkFileServer::rgFailureModes[j];
qDebug() << "Testing failure mode:" << errMode;
_fileServer->setErrorMode(errMode);
_fileManager->downloadPath(testCase->filename, QDir::temp());
QTest::qWait(_ackTimerTimeoutMsecs); // Let the file manager timeout
if (errMode == MockLinkFileServer::errModeNakResponse) {
// This will Nak the Open call which will fail the download, but not cause a Reset
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandErrorSignalMask), true);
QCOMPARE(resetSpy.count(), 0);
} else {
} else {
if (testCase->packetCount == 1 && (errMode == MockLinkFileServer::errModeNoSecondResponse || errMode == MockLinkFileServer::errModeNakSecondResponse)) {
// The downloaded file fits within a single Ack response, hence there is no second Read issued.
// The downloaded file fits within a single Ack response, hence there is no second Read issued.
// This should result in a successful download.
// This should result in a successful download, followed by a Reset
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskDownloadSuccess
),
true
);
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandCompleteSignalMask), true);
QCOMPARE(resetSpy.count(), 1);
// We should get a single Terminate command to close the Open session
QCOMPARE
(
terminateSpy
.
count
(),
1
);
// Validate file contents
// Validate file contents
QString filePath = QDir::temp().absoluteFilePath(testCase->filename);
QString filePath = QDir::temp().absoluteFilePath(testCase->filename);
_validateFileContents(filePath, testCase->length);
_validateFileContents(filePath, testCase->length);
}
} else {
} else {
// For all the other simulated server errors the Open command should have failed. Since the Open failed
// Download should have failed, followed by a aReset
// there is no session to terminate, hence no Terminate in this case.
QCOMPARE(_multiSpy->checkOnlySignalByMask(commandErrorSignalMask), true);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskOpenFailure
),
true
);
QCOMPARE(resetSpy.count(), 1
);
QCOMPARE
(
terminateSpy
.
count
(),
0
);
}
}
}
// Cleanup for next iteration
// Cleanup for next iteration
_multiSpy->clearAllSignals();
_multiSpy->clearAllSignals();
terminate
Spy
.
clear
();
reset
Spy.clear();
_mockFileServer
.
setErrorMode
(
MockMavl
inkFileServer
::
errModeNone
);
_fileServer->setErrorMode(MockL
inkFileServer::errModeNone);
}
}
// Run what should be a successful file download test case. No servers errors are being simulated.
_mockFileServer
.
setErrorMode
(
MockMavlinkFileServer
::
errModeNone
);
_fileManager
->
streamPath
(
testCase
->
filename
,
QDir
::
temp
());
// This should be a succesful download
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskDownloadSuccess
),
true
);
// Make sure the file length coming back through the openFileLength signal is correct
QVERIFY
(
_multiSpy
->
getSpyByIndex
(
downloadFileLengthSignalIndex
)
->
takeFirst
().
at
(
0
).
toInt
()
==
testCase
->
length
);
_multiSpy
->
clearAllSignals
();
// We should get a single Terminate command to close the session
QCOMPARE
(
terminateSpy
.
count
(),
1
);
terminateSpy
.
clear
();
// Validate file contents
QString
filePath
=
QDir
::
temp
().
absoluteFilePath
(
MockMavlinkFileServer
::
rgFileTestCases
[
i
].
filename
);
_validateFileContents
(
filePath
,
MockMavlinkFileServer
::
rgFileTestCases
[
i
].
length
);
}
}
}
}
...
@@ -481,3 +412,4 @@ void FileManagerTest::_validateFileContents(const QString& filePath, uint8_t len
...
@@ -481,3 +412,4 @@ void FileManagerTest::_validateFileContents(const QString& filePath, uint8_t len
QCOMPARE((uint8_t)bytes[i], (uint8_t)(i & 0xFF));
QCOMPARE((uint8_t)bytes[i], (uint8_t)(i & 0xFF));
}
}
}
}
#endif
src/qgcunittest/FileManagerTest.h
View file @
bc71d49d
...
@@ -28,9 +28,8 @@
...
@@ -28,9 +28,8 @@
#include <QtTest/QtTest>
#include <QtTest/QtTest>
#include "UnitTest.h"
#include "UnitTest.h"
#include "MockUAS.h"
#include "MockMavlinkFileServer.h"
#include "FileManager.h"
#include "FileManager.h"
#include "MockLink.h"
#include "MultiSignalSpy.h"
#include "MultiSignalSpy.h"
/// @file
/// @file
...
@@ -47,18 +46,13 @@ public:
...
@@ -47,18 +46,13 @@ public:
private
slots
:
private
slots
:
// Test case initialization
// Test case initialization
void
initTestCase
(
void
);
void
cleanupTestCase
(
void
);
void
init
(
void
);
void
init
(
void
);
void
cleanup
(
void
);
void
cleanup
(
void
);
// Test cases
// Test cases
void
_ackTest
(
void
);
void
_ackTest
(
void
);
void
_noAckTest
(
void
);
void
_noAckTest
(
void
);
void
_resetTest
(
void
);
void
_listTest
(
void
);
void
_listTest
(
void
);
void
_readDownloadTest
(
void
);
void
_streamDownloadTest
(
void
);
// Connected to FileManager listEntry signal
// Connected to FileManager listEntry signal
void
listEntry
(
const
QString
&
entry
);
void
listEntry
(
const
QString
&
entry
);
...
@@ -76,15 +70,14 @@ private:
...
@@ -76,15 +70,14 @@ private:
enum
{
enum
{
listEntrySignalMask
=
1
<<
listEntrySignalIndex
,
listEntrySignalMask
=
1
<<
listEntrySignalIndex
,
commandCompleteSignalMask
=
1
<<
commandCompleteSignalIndex
,
commandCompleteSignalMask
=
1
<<
commandCompleteSignalIndex
,
commandErrorSignalMask
=
1
<<
errorMessage
SignalIndex
,
commandErrorSignalMask
=
1
<<
commandError
SignalIndex
,
};
};
static
const
uint8_t
_systemIdQGC
=
255
;
static
const
uint8_t
_systemIdQGC
=
255
;
static
const
uint8_t
_systemIdServer
=
128
;
static
const
uint8_t
_systemIdServer
=
128
;
MockUAS
*
_mockUAS
;
MockLink
*
_mockLink
;
MockMavlinkFileServer
_mockFileServer
;
MockLinkFileServer
*
_fileServer
;
FileManager
*
_fileManager
;
FileManager
*
_fileManager
;
MultiSignalSpy
*
_multiSpy
;
MultiSignalSpy
*
_multiSpy
;
...
...
src/qgcunittest/MockMavlinkInterface.cc
deleted
100644 → 0
View file @
886b40b5
//
// MockMavlinkInterface.cc
// QGroundControl
//
// Created by Donald Gagne on 6/19/14.
// Copyright (c) 2014 Donald Gagne. All rights reserved.
//
#include "MockMavlinkInterface.h"
src/qgcunittest/MockMavlinkInterface.h
deleted
100644 → 0
View file @
886b40b5
/*=====================================================================
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 <QObject>
#include "QGCMAVLink.h"
#include "LinkInterface.h"
#ifndef MOCKMAVLINKINTERFACE_H
#define MOCKMAVLINKINTERFACE_H
class
MockMavlinkInterface
:
public
QObject
{
Q_OBJECT
public:
virtual
void
sendMessage
(
mavlink_message_t
message
)
=
0
;
signals:
// link argument will always be NULL
void
messageReceived
(
LinkInterface
*
link
,
mavlink_message_t
message
);
};
#endif
src/uas/FileManager.cc
View file @
bc71d49d
...
@@ -32,13 +32,13 @@
...
@@ -32,13 +32,13 @@
QGC_LOGGING_CATEGORY
(
FileManagerLog
,
"FileManagerLog"
)
QGC_LOGGING_CATEGORY
(
FileManagerLog
,
"FileManagerLog"
)
FileManager
::
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
,
uint8_t
unitTestSystemIdQGC
)
:
FileManager
::
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
)
:
QObject
(
parent
),
QObject
(
parent
),
_currentOperation
(
kCOIdle
),
_currentOperation
(
kCOIdle
),
_mav
(
uas
),
_mav
(
uas
),
_lastOutgoingSeqNumber
(
0
),
_lastOutgoingSeqNumber
(
0
),
_activeSession
(
0
),
_activeSession
(
0
),
_systemIdQGC
(
unitTestSystemIdQGC
)
_systemIdQGC
(
0
)
{
{
connect
(
&
_ackTimer
,
&
QTimer
::
timeout
,
this
,
&
FileManager
::
_ackTimeout
);
connect
(
&
_ackTimer
,
&
QTimer
::
timeout
,
this
,
&
FileManager
::
_ackTimeout
);
...
@@ -104,7 +104,7 @@ void FileManager::_closeDownloadSession(bool success)
...
@@ -104,7 +104,7 @@ void FileManager::_closeDownloadSession(bool success)
emit
commandComplete
();
emit
commandComplete
();
}
}
// If !success error is emitted elsewhere
_readFileAccumulator
.
clear
();
// Close the open session
// Close the open session
_sendResetCommand
();
_sendResetCommand
();
...
@@ -153,7 +153,6 @@ void FileManager::_downloadAckResponse(Request* readAck, bool readFile)
...
@@ -153,7 +153,6 @@ void FileManager::_downloadAckResponse(Request* readAck, bool readFile)
emit
commandProgress
(
100
*
((
float
)
_readFileAccumulator
.
length
()
/
(
float
)
_downloadFileSize
));
emit
commandProgress
(
100
*
((
float
)
_readFileAccumulator
.
length
()
/
(
float
)
_downloadFileSize
));
}
}
if
(
readAck
->
hdr
.
size
==
sizeof
(
readAck
->
data
))
{
if
(
readFile
||
readAck
->
hdr
.
burstComplete
)
{
if
(
readFile
||
readAck
->
hdr
.
burstComplete
)
{
// Possibly still more data to read, send next read request
// Possibly still more data to read, send next read request
...
@@ -164,14 +163,10 @@ void FileManager::_downloadAckResponse(Request* readAck, bool readFile)
...
@@ -164,14 +163,10 @@ void FileManager::_downloadAckResponse(Request* readAck, bool readFile)
request
.
hdr
.
size
=
0
;
request
.
hdr
.
size
=
0
;
_sendRequest
(
&
request
);
_sendRequest
(
&
request
);
}
else
{
}
else
if
(
!
readFile
)
{
// Streaming, so next ack should come automatically
// Streaming, so next ack should come automatically
_setupAckTimeout
();
_setupAckTimeout
();
}
}
}
else
if
(
readFile
)
{
// We only receieved a partial buffer back. These means we are at EOF
_closeDownloadSession
(
true
/* success */
);
}
}
}
/// @brief Respond to the Ack associated with the List command.
/// @brief Respond to the Ack associated with the List command.
...
@@ -340,7 +335,30 @@ void FileManager::receiveMessage(LinkInterface* link, mavlink_message_t message)
...
@@ -340,7 +335,30 @@ void FileManager::receiveMessage(LinkInterface* link, mavlink_message_t message)
// Make sure we have a good sequence number
// Make sure we have a good sequence number
uint16_t
expectedSeqNumber
=
_lastOutgoingSeqNumber
+
1
;
uint16_t
expectedSeqNumber
=
_lastOutgoingSeqNumber
+
1
;
if
(
incomingSeqNumber
!=
expectedSeqNumber
)
{
if
(
incomingSeqNumber
!=
expectedSeqNumber
)
{
switch
(
_currentOperation
)
{
case
kCOBurst
:
case
kCORead
:
_closeDownloadSession
(
false
/* failure */
);
break
;
case
kCOWrite
:
_closeUploadSession
(
false
/* failure */
);
break
;
case
kCOOpenRead
:
case
kCOOpenBurst
:
case
kCOCreate
:
// We could have an open session hanging around
_currentOperation
=
kCOIdle
;
_currentOperation
=
kCOIdle
;
_sendResetCommand
();
break
;
default:
// Don't need to do anything special
_currentOperation
=
kCOIdle
;
break
;
}
_emitErrorMessage
(
tr
(
"Bad sequence number on received message: expected(%1) received(%2)"
).
arg
(
expectedSeqNumber
).
arg
(
incomingSeqNumber
));
_emitErrorMessage
(
tr
(
"Bad sequence number on received message: expected(%1) received(%2)"
).
arg
(
expectedSeqNumber
).
arg
(
incomingSeqNumber
));
return
;
return
;
}
}
...
@@ -457,12 +475,22 @@ void FileManager::_sendListCommand(void)
...
@@ -457,12 +475,22 @@ void FileManager::_sendListCommand(void)
void
FileManager
::
downloadPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
)
void
FileManager
::
downloadPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
)
{
{
if
(
_currentOperation
!=
kCOIdle
)
{
_emitErrorMessage
(
tr
(
"Command not sent. Waiting for previous command to complete."
));
return
;
}
qCDebug
(
FileManagerLog
)
<<
"downloadPath from:"
<<
from
<<
"to:"
<<
downloadDir
;
qCDebug
(
FileManagerLog
)
<<
"downloadPath from:"
<<
from
<<
"to:"
<<
downloadDir
;
_downloadWorker
(
from
,
downloadDir
,
true
/* read file */
);
_downloadWorker
(
from
,
downloadDir
,
true
/* read file */
);
}
}
void
FileManager
::
streamPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
)
void
FileManager
::
streamPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
)
{
{
if
(
_currentOperation
!=
kCOIdle
)
{
_emitErrorMessage
(
tr
(
"Command not sent. Waiting for previous command to complete."
));
return
;
}
qCDebug
(
FileManagerLog
)
<<
"streamPath from:"
<<
from
<<
"to:"
<<
downloadDir
;
qCDebug
(
FileManagerLog
)
<<
"streamPath from:"
<<
from
<<
"to:"
<<
downloadDir
;
_downloadWorker
(
from
,
downloadDir
,
false
/* stream file */
);
_downloadWorker
(
from
,
downloadDir
,
false
/* stream file */
);
}
}
...
@@ -677,7 +705,6 @@ void FileManager::_emitListEntry(const QString& entry)
...
@@ -677,7 +705,6 @@ void FileManager::_emitListEntry(const QString& entry)
/// @brief Sends the specified Request out to the UAS.
/// @brief Sends the specified Request out to the UAS.
void
FileManager
::
_sendRequest
(
Request
*
request
)
void
FileManager
::
_sendRequest
(
Request
*
request
)
{
{
qCDebug
(
FileManagerLog
)
<<
"_sendRequest opcode:"
<<
request
->
hdr
.
opcode
;
mavlink_message_t
message
;
mavlink_message_t
message
;
...
@@ -687,6 +714,8 @@ void FileManager::_sendRequest(Request* request)
...
@@ -687,6 +714,8 @@ void FileManager::_sendRequest(Request* request)
request
->
hdr
.
seqNumber
=
_lastOutgoingSeqNumber
;
request
->
hdr
.
seqNumber
=
_lastOutgoingSeqNumber
;
qCDebug
(
FileManagerLog
)
<<
"_sendRequest opcode:"
<<
request
->
hdr
.
opcode
<<
"seqNumber:"
<<
request
->
hdr
.
seqNumber
;
if
(
_systemIdQGC
==
0
)
{
if
(
_systemIdQGC
==
0
)
{
_systemIdQGC
=
MAVLinkProtocol
::
instance
()
->
getSystemId
();
_systemIdQGC
=
MAVLinkProtocol
::
instance
()
->
getSystemId
();
}
}
...
...
src/uas/FileManager.h
View file @
bc71d49d
...
@@ -37,12 +37,11 @@ class FileManager : public QObject
...
@@ -37,12 +37,11 @@ class FileManager : public QObject
Q_OBJECT
Q_OBJECT
public:
public:
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
,
uint8_t
unitTestSystemIdQGC
=
0
);
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
);
/// These methods are only used for testing purposes.
/// These methods are only used for testing purposes.
bool
_sendCmdTestAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdNone
,
kCOAck
);
};
bool
_sendCmdTestAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdNone
,
kCOAck
);
};
bool
_sendCmdTestNoAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdTestNoAck
,
kCOAck
);
};
bool
_sendCmdTestNoAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdTestNoAck
,
kCOAck
);
};
bool
_sendCmdReset
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdResetSessions
,
kCOAck
);
};
/// Timeout in msecs to wait for an Ack time come back. This is public so we can write unit tests which wait long enough
/// Timeout in msecs to wait for an Ack time come back. This is public so we can write unit tests which wait long enough
/// for the FileManager to timeout.
/// for the FileManager to timeout.
...
@@ -226,9 +225,9 @@ private:
...
@@ -226,9 +225,9 @@ private:
uint8_t
_systemIdQGC
;
///< System ID for QGC
uint8_t
_systemIdQGC
;
///< System ID for QGC
uint8_t
_systemIdServer
;
///< System ID for server
uint8_t
_systemIdServer
;
///< System ID for server
// We give Mock
Mavl
inkFileServer friend access so that it can use the data structures and opcodes
// We give Mock
L
inkFileServer friend access so that it can use the data structures and opcodes
// to build a mock mavlink file server for testing.
// to build a mock mavlink file server for testing.
friend
class
Mock
Mavl
inkFileServer
;
friend
class
Mock
L
inkFileServer
;
};
};
#endif // FileManager_H
#endif // FileManager_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment