-
Notifications
You must be signed in to change notification settings - Fork 251
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use ctrlmsg parsing function add test Signed-off-by: Viktor Kopp <[email protected]>
- Loading branch information
Showing
6 changed files
with
313 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#include "qdltctrlmsg.h" | ||
|
||
#include "dlt_common.h" | ||
|
||
#include <stdexcept> | ||
#include <cstring> | ||
#include <array> | ||
|
||
#include <QByteArray> | ||
|
||
namespace qdlt::msg::payload { | ||
|
||
namespace { | ||
using IdType = std::array<char, DLT_ID_SIZE>; | ||
|
||
QString asQString(IdType&& id) { | ||
QString str; | ||
for (size_t i = 0; i < id.size() && id[i] != '\0'; i++) { | ||
str.append(id[i]); | ||
} | ||
return str; | ||
} | ||
|
||
template <typename T> | ||
T dltPayloadRead(const char *&dataPtr, int32_t &length, bool isBigEndian) | ||
{ | ||
if (sizeof(T) > static_cast<uint32_t>(length)) { | ||
throw std::runtime_error("Invalid data length"); | ||
} | ||
|
||
T value{}; | ||
std::memcpy(&value, dataPtr, sizeof(T)); | ||
dataPtr += sizeof(T); | ||
length -= sizeof(T); | ||
|
||
if constexpr (sizeof(T) == sizeof(uint32_t)) { | ||
value = DLT_ENDIAN_GET_32((isBigEndian ? DLT_HTYP_MSBF : 0), value); | ||
} | ||
|
||
if constexpr (sizeof(T) == sizeof(uint16_t)) { | ||
value = DLT_ENDIAN_GET_16((isBigEndian ? DLT_HTYP_MSBF : 0), value); | ||
} | ||
|
||
return value; | ||
} | ||
|
||
IdType dltPayloadReadId(const char *&dataPtr, int32_t &length) | ||
{ | ||
if (DLT_ID_SIZE > length) { | ||
throw std::runtime_error("Invalid ID length"); | ||
} | ||
IdType id{}; | ||
std::copy(dataPtr, dataPtr + DLT_ID_SIZE, id.begin()); | ||
dataPtr += DLT_ID_SIZE; | ||
length -= DLT_ID_SIZE; | ||
|
||
return id; | ||
} | ||
|
||
std::string dltPayloadReadString(const char *&dataPtr, int32_t &length, bool isBigEndian) | ||
{ | ||
uint16_t strLength = dltPayloadRead<uint16_t>(dataPtr, length, isBigEndian); | ||
if (strLength > length) { | ||
throw std::runtime_error("Invalid string length"); | ||
} | ||
std::string str; | ||
str.assign(dataPtr, strLength); | ||
dataPtr += strLength; | ||
length -= strLength; | ||
|
||
return str; | ||
} | ||
} | ||
|
||
Type parse(const QByteArray& data, bool isBigEndian) | ||
{ | ||
int32_t length = data.length(); | ||
const char *dataPtr = data.data(); | ||
|
||
auto service_id = dltPayloadRead<uint32_t>(dataPtr, length, isBigEndian); | ||
|
||
switch (service_id) { | ||
case DLT_SERVICE_ID_GET_LOG_INFO: | ||
{ | ||
GetLogInfo msg; | ||
msg.status = dltPayloadRead<uint8_t>(dataPtr, length, isBigEndian); | ||
if ((msg.status != 6) && (msg.status != 7)) { | ||
return msg; | ||
} | ||
|
||
const auto numApps = dltPayloadRead<uint16_t>(dataPtr, length, isBigEndian); | ||
for (uint16_t i = 0; i < numApps; i++) { | ||
GetLogInfo::App app; | ||
app.id = asQString(dltPayloadReadId(dataPtr, length)); | ||
const uint16_t numCtx = dltPayloadRead<uint16_t>(dataPtr, length, isBigEndian); | ||
for (uint16_t j = 0; j < numCtx; j++) { | ||
GetLogInfo::App::Ctx ctx; | ||
ctx.id = asQString(dltPayloadReadId(dataPtr, length)); | ||
ctx.logLevel = dltPayloadRead<int8_t>(dataPtr, length, isBigEndian); | ||
ctx.traceStatus = dltPayloadRead<int8_t>(dataPtr, length, isBigEndian); | ||
ctx.description = QString::fromStdString(dltPayloadReadString(dataPtr, length, isBigEndian)); | ||
app.ctxs.push_back(std::move(ctx)); | ||
} | ||
if (msg.status == 7) { | ||
app.description = QString::fromStdString(dltPayloadReadString(dataPtr, length, isBigEndian)); | ||
} | ||
msg.apps.push_back(std::move(app)); | ||
} | ||
return msg; | ||
} | ||
case DLT_SERVICE_ID_GET_SOFTWARE_VERSION: | ||
{ | ||
GetSoftwareVersion msg; | ||
msg.version = dltPayloadReadString(dataPtr, length, isBigEndian); | ||
return msg; | ||
} | ||
case DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL: | ||
{ | ||
GetDefaultLogLevel msg; | ||
msg.logLevel = dltPayloadRead<int8_t>(dataPtr, length, isBigEndian); | ||
msg.status = dltPayloadRead<uint8_t>(dataPtr, length, isBigEndian); | ||
return msg; | ||
} | ||
case DLT_SERVICE_ID_SET_LOG_LEVEL: | ||
{ | ||
SetLogLevel msg; | ||
msg.status = dltPayloadRead<uint8_t>(dataPtr, length, isBigEndian); | ||
return msg; | ||
} | ||
case DLT_SERVICE_ID_TIMEZONE: | ||
{ | ||
Timezone msg; | ||
msg.status = dltPayloadRead<uint8_t>(dataPtr, length, isBigEndian); | ||
msg.timezone = dltPayloadRead<int32_t>(dataPtr, length, isBigEndian); | ||
msg.isDst = dltPayloadRead<uint8_t>(dataPtr, length, isBigEndian); | ||
return msg; | ||
} | ||
case DLT_SERVICE_ID_UNREGISTER_CONTEXT: | ||
{ | ||
UnregisterContext msg; | ||
msg.status = dltPayloadRead<uint8_t>(dataPtr, length, isBigEndian); | ||
msg.appid = asQString(dltPayloadReadId(dataPtr, length)); | ||
msg.ctxid = asQString(dltPayloadReadId(dataPtr, length)); | ||
return msg; | ||
} | ||
} | ||
|
||
throw std::runtime_error("Unknown service type"); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#ifndef QDLTCTRLMSG_H | ||
#define QDLTCTRLMSG_H | ||
|
||
#include <vector> | ||
#include <variant> | ||
|
||
#include <QByteArray> | ||
#include <QString> | ||
|
||
|
||
namespace qdlt::msg::payload { | ||
|
||
struct GetLogInfo { | ||
struct App { | ||
struct Ctx { | ||
QString id; | ||
int8_t logLevel; | ||
int8_t traceStatus; | ||
QString description; | ||
}; | ||
|
||
QString id; | ||
QString description; | ||
std::vector<Ctx> ctxs; | ||
}; | ||
|
||
uint8_t status; | ||
std::vector<App> apps; | ||
}; | ||
|
||
struct GetSoftwareVersion { | ||
std::string version; | ||
}; | ||
|
||
struct GetDefaultLogLevel | ||
{ | ||
uint8_t logLevel; | ||
uint8_t status; | ||
}; | ||
|
||
struct SetLogLevel { | ||
uint8_t status; | ||
}; | ||
|
||
struct Timezone { | ||
uint8_t status; | ||
int32_t timezone; | ||
uint8_t isDst; | ||
}; | ||
|
||
struct UnregisterContext { | ||
uint8_t status; | ||
QString appid; | ||
QString ctxid; | ||
}; | ||
|
||
using Type = std::variant<GetLogInfo, GetSoftwareVersion, GetDefaultLogLevel, SetLogLevel, Timezone, | ||
UnregisterContext>; | ||
|
||
Type parse(const QByteArray&, bool isBigEndian); | ||
|
||
} // namespace qdlt::msg::payload | ||
|
||
// helper type for the visitor | ||
template<class... Ts> | ||
struct overloaded : Ts... { using Ts::operator()...; }; | ||
// explicit deduction guide (not needed as of C++20) | ||
template<class... Ts> | ||
overloaded(Ts...) -> overloaded<Ts...>; | ||
|
||
#endif // QDLTCTRLMSG_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#include <gtest/gtest.h> | ||
|
||
#include <qdltctrlmsg.h> | ||
|
||
#include <QByteArray> | ||
|
||
TEST(CtrlPayload, parse) { | ||
// this is real payload of a dlt control message which collect from dlt-daemon | ||
const auto data = QByteArray::fromHex("030000000701005359530001004d475200ffff2200436f6e74657874206f66206d61696e20646c742073797374656d206d616e616765721200444c542053797374656d204d616e6167657272656d6f"); | ||
|
||
auto payload = qdlt::msg::payload::parse(data, false); | ||
|
||
ASSERT_TRUE(std::holds_alternative<qdlt::msg::payload::GetLogInfo>(payload)); | ||
auto getLogInfo = std::get<qdlt::msg::payload::GetLogInfo>(payload); | ||
EXPECT_EQ(getLogInfo.status, 7); | ||
ASSERT_EQ(getLogInfo.apps.size(), 1); | ||
|
||
auto app = getLogInfo.apps[0]; | ||
EXPECT_EQ(app.id, "SYS"); | ||
EXPECT_EQ(app.description, "DLT System Manager"); | ||
ASSERT_EQ(app.ctxs.size(), 1); | ||
|
||
auto ctx = app.ctxs[0]; | ||
EXPECT_EQ(ctx.id, "MGR"); | ||
EXPECT_EQ(ctx.logLevel, '\xff'); | ||
EXPECT_EQ(ctx.traceStatus, '\xff'); | ||
EXPECT_EQ(ctx.description, "Context of main dlt system manager"); | ||
} |
Oops, something went wrong.