mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-04-18 10:38:16 +00:00
@@ -0,0 +1,270 @@
|
||||
#include "../../../../global/process_watchdog.h"
|
||||
#include "../include/can_com_test_helper.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#endif
|
||||
|
||||
class CANSilkitTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
virtual void SetUp() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void TearDown() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class CTestCANSilkit : public CCANSilKit
|
||||
{
|
||||
public:
|
||||
virtual void Initialize(const sdv::u8string& ssObjectConfig) override
|
||||
{
|
||||
CCANSilKit::Initialize(ssObjectConfig);
|
||||
}
|
||||
|
||||
virtual void Shutdown() override
|
||||
{
|
||||
CCANSilKit::Shutdown();
|
||||
}
|
||||
|
||||
virtual void Send(const sdv::can::SMessage& sMsg, uint32_t uiIfcIndex) override
|
||||
{
|
||||
CCANSilKit::Send(sMsg, uiIfcIndex);
|
||||
m_MessagesSent++;
|
||||
}
|
||||
|
||||
virtual void RegisterReceiver(sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
CCANSilKit::RegisterReceiver(pReceiver);
|
||||
}
|
||||
|
||||
virtual void UnregisterReceiver(sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
CCANSilKit::UnregisterReceiver(pReceiver);
|
||||
}
|
||||
|
||||
virtual sdv::sequence<sdv::u8string> GetInterfaces() const override
|
||||
{
|
||||
return CCANSilKit::GetInterfaces();
|
||||
}
|
||||
|
||||
sdv::EObjectStatus GetTestStatus() const
|
||||
{
|
||||
return CCANSilKit::GetStatus();
|
||||
}
|
||||
|
||||
uint64_t GetMessagesSent() const
|
||||
{
|
||||
return m_MessagesSent;
|
||||
}
|
||||
|
||||
uint64_t m_MessagesSent = 0;
|
||||
};
|
||||
|
||||
class MockCANReceiver : public sdv::can::IReceive
|
||||
{
|
||||
public:
|
||||
void Receive(const sdv::can::SMessage& msg, uint32_t ifIndex) override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_receivedMessages.push_back(std::make_pair(ifIndex, msg));
|
||||
}
|
||||
|
||||
void Error(const sdv::can::SErrorFrame&, uint32_t) override {}
|
||||
|
||||
std::deque<std::pair<uint32_t, sdv::can::SMessage>>GetReceivedMessages() const
|
||||
{
|
||||
return m_receivedMessages;
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<std::pair<uint32_t, sdv::can::SMessage>> m_receivedMessages; ///< Storing index and received messages
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
bool InitializeAppControl(sdv::app::CAppControl* appcontrol, const std::string& configFileName)
|
||||
{
|
||||
auto bResult = appcontrol->AddModuleSearchDir("../../bin");
|
||||
bResult &= appcontrol->Startup("");
|
||||
appcontrol->SetConfigMode();
|
||||
bResult &= appcontrol->AddConfigSearchDir("../../tests/bin/config");
|
||||
|
||||
if (!configFileName.empty())
|
||||
{
|
||||
bResult &= appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void InitializeCanComObject(CTestCANSilkit& canComObj, const std::string config, MockCANReceiver& mockRcv)
|
||||
{
|
||||
ASSERT_NO_THROW(canComObj.Initialize(config.c_str()));
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
ASSERT_NO_THROW(canComObj.SetOperationMode(sdv::EOperationMode::configuring));
|
||||
ASSERT_NO_THROW(canComObj.RegisterReceiver(&mockRcv));
|
||||
EXPECT_NO_THROW(canComObj.SetOperationMode(sdv::EOperationMode::running));
|
||||
}
|
||||
|
||||
void ShutDownCanComObject(CTestCANSilkit& canComObj, MockCANReceiver& mockRcv)
|
||||
{
|
||||
EXPECT_NO_THROW(canComObj.UnregisterReceiver(&mockRcv));
|
||||
ASSERT_NO_THROW(canComObj.Shutdown());
|
||||
}
|
||||
|
||||
void SendThread(bool& stop, CTestCANSilkit& canComObj, sdv::can::SMessage& testData)
|
||||
{
|
||||
while (!stop)
|
||||
{
|
||||
EXPECT_NO_THROW(canComObj.Send(testData, 1)); // Send to second configuration
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CANSilkitTest, ValidConfigString)
|
||||
{
|
||||
sdv::can::SMessage testMsg {1, 0, 0, {0x11, 0x22, 0x33, 0x44}};
|
||||
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig =
|
||||
R"(
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
SilKitParticipantName = "can_writer"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
)";
|
||||
CTestCANSilkit canComObj;
|
||||
ASSERT_NO_THROW(canComObj.Initialize(ssObjectConfig.c_str()));
|
||||
ASSERT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
|
||||
ASSERT_NO_THROW(canComObj.Send(testMsg, 0));
|
||||
|
||||
ASSERT_NO_THROW(canComObj.Shutdown());
|
||||
ASSERT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::shutdown_in_progress);
|
||||
}
|
||||
|
||||
TEST_F(CANSilkitTest, InvalidConfigIdentifier)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig =
|
||||
R"(
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
InvalidSilKitParticipantName = "can_writer"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
)";
|
||||
|
||||
CTestCANSilkit canComObj;
|
||||
ASSERT_NO_THROW(canComObj.Initialize(ssObjectConfig.c_str()));
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialization_failure);
|
||||
|
||||
ASSERT_NO_THROW(canComObj.Shutdown());
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::shutdown_in_progress);
|
||||
}
|
||||
|
||||
TEST_F(CANSilkitTest, SendReceiveTest)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssConfig1 =
|
||||
R"(
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
SilKitParticipantName = "can_writer"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
)";
|
||||
sdv::u8string ssConfig2 =
|
||||
R"(
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
SilKitParticipantName = "can_reader"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
)";
|
||||
|
||||
CTestCANSilkit canComObj1;
|
||||
CTestCANSilkit canComObj2;
|
||||
MockCANReceiver mockRcv;
|
||||
|
||||
canComObj1.Initialize(ssConfig1.c_str());
|
||||
ASSERT_EQ(canComObj1.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
canComObj2.Initialize(ssConfig2.c_str());
|
||||
ASSERT_EQ(canComObj2.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
|
||||
ASSERT_NO_THROW(canComObj1.SetOperationMode(sdv::EOperationMode::running));
|
||||
ASSERT_NO_THROW(canComObj2.SetOperationMode(sdv::EOperationMode::configuring));
|
||||
ASSERT_NO_THROW(canComObj2.RegisterReceiver(&mockRcv));
|
||||
ASSERT_NO_THROW(canComObj2.SetOperationMode(sdv::EOperationMode::running));
|
||||
|
||||
uint8_t msgId = 102;
|
||||
uint8_t dataSize = 1;
|
||||
uint32_t expectToBeSend = 8;
|
||||
uint32_t msgToBeSend = 8;
|
||||
CComTestHelper testHelper;
|
||||
while (dataSize <= msgToBeSend)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId, dataSize);
|
||||
EXPECT_NO_THROW(canComObj1.Send(testData, 0)); // Send to CAN1
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
auto receivedMessages = mockRcv.GetReceivedMessages();
|
||||
|
||||
if (expectToBeSend != receivedMessages.size())
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << " Failed, expected " << std::to_string(expectToBeSend ) << " messages, got from CAN1 to CAN2: "
|
||||
<< std::to_string(receivedMessages.size());
|
||||
FAIL() << sstream.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSize = 1;
|
||||
for(auto rcvMsg : receivedMessages)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId, dataSize);
|
||||
EXPECT_EQ(msgId, rcvMsg.second.uiID);
|
||||
EXPECT_EQ(dataSize++, rcvMsg.second.seqData.size());
|
||||
EXPECT_EQ(testData.seqData, rcvMsg.second.seqData);
|
||||
std::cout << "Expected " << std::to_string(expectToBeSend ) << " messages, got from CAN1 to CAN2: "
|
||||
<< std::to_string(receivedMessages.size()) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_NO_THROW(canComObj2.UnregisterReceiver(&mockRcv));
|
||||
canComObj1.Shutdown();
|
||||
canComObj2.Shutdown();
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <condition_variable>
|
||||
#include <gtest/gtest.h>
|
||||
#include <interfaces/can.h>
|
||||
#include <support/app_control.h>
|
||||
#include <support/toml.h>
|
||||
#include <support/component_impl.h>
|
||||
#include "../../../global/process_watchdog.h"
|
||||
#include "../sdv_services/core/toml_parser/parser_toml.h"
|
||||
|
||||
/**
|
||||
* @brief Dummy CAN Component to be able to load data link for testing purposes.
|
||||
* Sends and receives CAN messages with multiple signals.
|
||||
*/
|
||||
class CDummyCANSilKit
|
||||
: public sdv::CSdvObject
|
||||
, public sdv::IObjectControl
|
||||
, public sdv::can::IRegisterReceiver
|
||||
, public sdv::can::ISend
|
||||
{
|
||||
public:
|
||||
|
||||
// Interface map
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
|
||||
SDV_INTERFACE_ENTRY(sdv::can::IRegisterReceiver)
|
||||
SDV_INTERFACE_ENTRY(sdv::can::ISend)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
|
||||
DECLARE_OBJECT_CLASS_NAME("Dummy_CAN_Sockets")
|
||||
DECLARE_DEFAULT_OBJECT_NAME("CAN_Communication_Object")
|
||||
DECLARE_OBJECT_SINGLETON()
|
||||
|
||||
virtual void Initialize(const sdv::u8string& ) override
|
||||
{
|
||||
m_StopThread = false;
|
||||
//m_thSend2DatalinkThread = std::thread(&CDummyCANSockets::Send2DatalinkThread, this);
|
||||
m_status = sdv::EObjectStatus::initialized;
|
||||
}
|
||||
|
||||
virtual sdv::EObjectStatus GetStatus() const override
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
void SetOperationMode(sdv::EOperationMode eMode) override
|
||||
{
|
||||
switch (eMode)
|
||||
{
|
||||
case sdv::EOperationMode::configuring:
|
||||
if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
|
||||
m_status = sdv::EObjectStatus::configuring;
|
||||
break;
|
||||
case sdv::EOperationMode::running:
|
||||
if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
|
||||
m_status = sdv::EObjectStatus::running;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Shutdown() override
|
||||
{
|
||||
m_StopThread = true;
|
||||
if (m_thSend2DatalinkThread.joinable())
|
||||
{
|
||||
m_thSend2DatalinkThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void RegisterReceiver(sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
if (!pReceiver)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Registering Dummy CAN communication receiver...\n";
|
||||
std::unique_lock<std::mutex> lock(m_mtxReceivers);
|
||||
m_setReceivers.insert(pReceiver);
|
||||
}
|
||||
|
||||
virtual void UnregisterReceiver(sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
if (!pReceiver)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Unregistering Dummy CAN communication receiver...\n";
|
||||
std::unique_lock<std::mutex> lock(m_mtxReceivers);
|
||||
m_setReceivers.erase(pReceiver);
|
||||
}
|
||||
|
||||
virtual void Send(const sdv::can::SMessage& sMsg, uint32_t uiIfcIndex) override
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lockReceivers(m_mtxReceivers);
|
||||
for (sdv::can::IReceive* pReceiver : m_setReceivers)
|
||||
{
|
||||
pReceiver->Receive(sMsg, uiIfcIndex);
|
||||
}
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx);
|
||||
m_messageSent = true;
|
||||
}
|
||||
m_cv.notify_one();
|
||||
}
|
||||
|
||||
// Synchronization members
|
||||
std::condition_variable m_cv;
|
||||
std::mutex m_mtx;
|
||||
bool m_messageSent = false;
|
||||
|
||||
private:
|
||||
bool m_StopThread = false;
|
||||
std::thread m_thSend2DatalinkThread;
|
||||
mutable std::mutex m_mtxReceivers;
|
||||
std::set<sdv::can::IReceive*> m_setReceivers;
|
||||
std::atomic<sdv::EObjectStatus> m_status = { sdv::EObjectStatus::initialization_pending };
|
||||
};
|
||||
|
||||
class MockCANReceiver : public sdv::can::IReceive
|
||||
{
|
||||
public:
|
||||
std::vector<sdv::can::SMessage> vecReceivedMessages;
|
||||
|
||||
void Receive(const sdv::can::SMessage& sMessage, uint32_t) override
|
||||
{
|
||||
vecReceivedMessages.push_back(sMessage);
|
||||
}
|
||||
|
||||
void Error(const sdv::can::SErrorFrame&, uint32_t) override {}
|
||||
};
|
||||
|
||||
bool InitializeAppControl(sdv::app::CAppControl* appcontrol, const std::string& configFileName)
|
||||
{
|
||||
auto bResult = appcontrol->AddModuleSearchDir("../../bin");
|
||||
bResult &= appcontrol->Startup("");
|
||||
appcontrol->SetConfigMode();
|
||||
bResult &= appcontrol->AddConfigSearchDir("../../tests/bin/config");
|
||||
|
||||
if (!configFileName.empty())
|
||||
{
|
||||
bResult &= appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
std::string ReplaceWhitespaceWithSingleSpaceAndEscapeQuotes(const std::string& input)
|
||||
{
|
||||
std::stringstream result;
|
||||
bool inWhitespace = false;
|
||||
|
||||
for (uint8_t singleChar : input)
|
||||
{
|
||||
if (std::isspace(static_cast<uint8_t>(singleChar)))
|
||||
{
|
||||
if (!inWhitespace)
|
||||
{
|
||||
result << ' '; // Add a single space for whitespace
|
||||
inWhitespace = true;
|
||||
}
|
||||
}
|
||||
else if (singleChar == '"')
|
||||
{
|
||||
// Escape the quote character
|
||||
result << "\\\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
result << singleChar; // Add the character as is
|
||||
inWhitespace = false;
|
||||
}
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
bool StringToBool(const std::string& value) {
|
||||
return value == "true" || value == "1"; // Return true for "true" or "1", false otherwise
|
||||
}
|
||||
|
||||
std::string ExtractValue(const std::string& content, const std::string& key)
|
||||
{
|
||||
std::size_t startPos = content.find(key + " = ");
|
||||
if (startPos == std::string::npos) {
|
||||
return ""; // Key not found
|
||||
}
|
||||
|
||||
startPos += key.length() + 3; // Move past the key and " = "
|
||||
|
||||
// If the value is multi-line (enclosed by triple quotes), find the start and end
|
||||
std::size_t endPos;
|
||||
if (content.substr(startPos, 3) == "\"\"\"") { // Check for starting triple quotes
|
||||
startPos += 3; // Skip over the triple quotes
|
||||
endPos = content.find("\"\"\"", startPos); // Look for the closing triple quotes
|
||||
if (endPos == std::string::npos) {
|
||||
return ""; // End of value not found, invalid format
|
||||
}
|
||||
} else {
|
||||
// Otherwise, find the first newline or end of the string
|
||||
endPos = content.find_first_of("\n", startPos);
|
||||
if (endPos == std::string::npos) {
|
||||
endPos = content.length();
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the value between startPos and endPos
|
||||
std::string value = content.substr(startPos, endPos - startPos);
|
||||
|
||||
// Remove surrounding whitespace and newline characters if present
|
||||
value.erase(std::remove(value.begin(), value.end(), '\"'), value.end());
|
||||
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end());
|
||||
value.erase(std::remove(value.begin(), value.end(), '\r'), value.end());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
class CANCommunicationTest : public ::testing::Test
|
||||
{
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(CANCommunicationTest, BasicSendAndReceiveMessageTest)
|
||||
{
|
||||
// Dummy test message
|
||||
sdv::can::SMessage testMsg;
|
||||
testMsg.uiID = 0x1234;
|
||||
testMsg.bCanFd = false;
|
||||
testMsg.bExtended = false;
|
||||
testMsg.seqData = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x77, 0x88};
|
||||
|
||||
// Configuration content as a string
|
||||
std::string testConfigFileContent = R"(
|
||||
[Configuration]
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "task_timer.sdv"
|
||||
Class = "TaskTimerService"
|
||||
|
||||
[[Component]]
|
||||
Path = "data_dispatch_service.sdv"
|
||||
Class = "DataDispatchService"
|
||||
|
||||
[[Component]]
|
||||
Path = "can_com_silkit.sdv"
|
||||
Class = "CAN_Com_SilKit"
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
CanSilKitChannel = "CAN1"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
|
||||
[[Component]]
|
||||
Path = "can_datalink.sdv"
|
||||
Class = "CAN_data_link"
|
||||
"""
|
||||
)";
|
||||
|
||||
sdv::app::CAppControl appControl;
|
||||
auto bResult = InitializeAppControl(&appControl, "test_manual_can_com_silkit.toml");
|
||||
EXPECT_EQ(bResult, true);
|
||||
|
||||
std::string SilKitChannel = ExtractValue(testConfigFileContent, "CanSilKitChannel");
|
||||
EXPECT_EQ(SilKitChannel, "CAN1");
|
||||
|
||||
// Check RegistryURI
|
||||
std::string SilKitRegistryUri = ExtractValue(testConfigFileContent, "RegistryURI");
|
||||
EXPECT_EQ(SilKitRegistryUri, "silkit://localhost:8500");
|
||||
|
||||
// Check CanSilKitNetwork
|
||||
std::string SilKitNetwork = ExtractValue(testConfigFileContent, "CanSilKitNetwork");
|
||||
EXPECT_EQ(SilKitNetwork, "PrivateCAN");
|
||||
|
||||
// Check SyncMode
|
||||
std::string SyncModeString = ExtractValue(testConfigFileContent, "SyncMode");
|
||||
|
||||
// Convert the extracted value to a bool
|
||||
bool SilKitSyncMode = StringToBool(SyncModeString);
|
||||
EXPECT_EQ(SilKitSyncMode, true);
|
||||
|
||||
// Check SilKitConfig
|
||||
std::string SilKitJSONConfigContent = ExtractValue(testConfigFileContent, "SilKitConfig");
|
||||
std::string ExpectedConfigContent = R"({
|
||||
Logging: {
|
||||
Sinks: [ { Type: Stdout, Level: Info } ]
|
||||
},
|
||||
})";
|
||||
EXPECT_EQ(ReplaceWhitespaceWithSingleSpaceAndEscapeQuotes(SilKitJSONConfigContent), ReplaceWhitespaceWithSingleSpaceAndEscapeQuotes(ExpectedConfigContent));
|
||||
|
||||
|
||||
// Create an object of the CDummyCANSilKit class
|
||||
CDummyCANSilKit canComObj;
|
||||
canComObj.Initialize("");
|
||||
|
||||
sdv::can::ISend* pCanSend = &canComObj;
|
||||
EXPECT_NE(pCanSend, nullptr);
|
||||
|
||||
sdv::can::IRegisterReceiver* pCanRegRcvr = &canComObj;
|
||||
EXPECT_NE(pCanRegRcvr, nullptr);
|
||||
|
||||
MockCANReceiver mockRcv;
|
||||
EXPECT_NO_THROW(pCanRegRcvr->RegisterReceiver(&mockRcv));
|
||||
|
||||
appControl.SetRunningMode();
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
// Send a message
|
||||
EXPECT_NO_THROW(pCanSend->Send(testMsg, 0));
|
||||
|
||||
// Wait for the message to be received
|
||||
std::unique_lock<std::mutex> lock(canComObj.m_mtx);
|
||||
canComObj.m_cv.wait(lock, [&] { return canComObj.m_messageSent; });
|
||||
|
||||
// Verify received messages
|
||||
ASSERT_FALSE(mockRcv.vecReceivedMessages.empty());
|
||||
auto rcvMsg = mockRcv.vecReceivedMessages.front();
|
||||
EXPECT_EQ(rcvMsg.uiID, testMsg.uiID);
|
||||
EXPECT_EQ(rcvMsg.seqData, testMsg.seqData);
|
||||
|
||||
// Reset the flag for the next iteration
|
||||
canComObj.m_messageSent = false;
|
||||
mockRcv.vecReceivedMessages.clear();
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(pCanRegRcvr->UnregisterReceiver(&mockRcv));
|
||||
|
||||
// Ensure proper shutdown
|
||||
canComObj.Shutdown();
|
||||
}
|
||||
|
||||
TEST_F(CANCommunicationTest, ExtractAndCompareSignals)
|
||||
{
|
||||
// Dummy test message
|
||||
sdv::can::SMessage testMsg;
|
||||
testMsg.uiID = 0x1234;
|
||||
testMsg.bCanFd = false;
|
||||
testMsg.bExtended = false;
|
||||
testMsg.seqData = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x77, 0x88};
|
||||
|
||||
sdv::app::CAppControl appControl;
|
||||
auto bResult = InitializeAppControl(&appControl, "test_manual_can_com_silkit.toml");
|
||||
EXPECT_EQ(bResult, true);
|
||||
|
||||
// Create a normal object of the CDummyCANSilKit class
|
||||
CDummyCANSilKit canComObj;
|
||||
canComObj.Initialize("");
|
||||
|
||||
sdv::can::ISend* pCanSend = &canComObj;
|
||||
EXPECT_NE(pCanSend, nullptr);
|
||||
|
||||
sdv::can::IRegisterReceiver* pCanRegRcvr = &canComObj;
|
||||
EXPECT_NE(pCanRegRcvr, nullptr);
|
||||
|
||||
MockCANReceiver mockRcv;
|
||||
EXPECT_NO_THROW(pCanRegRcvr->RegisterReceiver(&mockRcv));
|
||||
|
||||
appControl.SetRunningMode();
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
// Send a message
|
||||
EXPECT_NO_THROW(pCanSend->Send(testMsg, 0));
|
||||
|
||||
// Wait for the message to be received
|
||||
std::unique_lock<std::mutex> lock(canComObj.m_mtx);
|
||||
canComObj.m_cv.wait(lock, [&] { return canComObj.m_messageSent; });
|
||||
|
||||
// Verify received messages
|
||||
ASSERT_FALSE(mockRcv.vecReceivedMessages.empty());
|
||||
auto rcvMsg = mockRcv.vecReceivedMessages.front();
|
||||
EXPECT_EQ(rcvMsg.uiID, testMsg.uiID);
|
||||
EXPECT_EQ(rcvMsg.seqData, testMsg.seqData);
|
||||
|
||||
// Extract and compare signals
|
||||
uint32_t sentSpeed = (testMsg.seqData[6] << 8) | testMsg.seqData[7];
|
||||
uint32_t receivedSpeed = (rcvMsg.seqData[6] << 8) | rcvMsg.seqData[7];
|
||||
EXPECT_EQ(sentSpeed, receivedSpeed);
|
||||
|
||||
int32_t sentSteeringWheel = (testMsg.seqData[4] << 8) | testMsg.seqData[5];
|
||||
int32_t receivedSteeringWheel = (rcvMsg.seqData[4] << 8) | rcvMsg.seqData[5];
|
||||
EXPECT_EQ(sentSteeringWheel, receivedSteeringWheel);
|
||||
|
||||
// Reset the flag for the next iteration
|
||||
canComObj.m_messageSent = false;
|
||||
mockRcv.vecReceivedMessages.clear();
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(pCanRegRcvr->UnregisterReceiver(&mockRcv));
|
||||
|
||||
// Ensure proper shutdown
|
||||
canComObj.Shutdown();
|
||||
}
|
||||
|
||||
extern "C" int main(int argc, char* argv[])
|
||||
{
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
67
tests/manual_tests/silkit_can_com_tests/src/can_reader.cpp
Normal file
67
tests/manual_tests/silkit_can_com_tests/src/can_reader.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "../include/can_com_test_helper.h"
|
||||
|
||||
void ReceiveData()
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string config = R"(
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
SilKitParticipantName = "can_reader"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
)";
|
||||
|
||||
CTestCanSilKit canComObj;
|
||||
canComObj.Initialize(config.c_str());
|
||||
canComObj.SetOperationMode(sdv::EOperationMode::configuring);
|
||||
|
||||
CanReceiver mockRcv;
|
||||
canComObj.RegisterReceiver(&mockRcv);
|
||||
canComObj.SetOperationMode(sdv::EOperationMode::running);
|
||||
|
||||
while(true)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
auto receivedMessages = mockRcv.GetReceivedMessages();
|
||||
if(receivedMessages.size() != 0)
|
||||
{
|
||||
for(auto rcvdMsg : receivedMessages)
|
||||
{
|
||||
std::stringstream buffer;
|
||||
buffer << "\n[RX] CAN message being received [CANID=";
|
||||
buffer << rcvdMsg.uiID; buffer << ", Length=" ;
|
||||
buffer << unsigned(rcvdMsg.seqData.size()); buffer << "]" ;
|
||||
|
||||
buffer << " Data=";
|
||||
for(uint16_t i = 0; i < rcvdMsg.seqData.size(); i++)
|
||||
{
|
||||
buffer << "[" ; buffer << std::hex << unsigned(rcvdMsg.seqData[i]); buffer << "] ";
|
||||
}
|
||||
std::cout << buffer.str().c_str();
|
||||
mockRcv.ClearReceivedMessages();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "[RX] Received Message size is " << receivedMessages.size() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
canComObj.UnregisterReceiver(&mockRcv);
|
||||
std::cout << "CAN has read all messages\n";
|
||||
|
||||
canComObj.Shutdown();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ReceiveData();
|
||||
return 0;
|
||||
}
|
||||
59
tests/manual_tests/silkit_can_com_tests/src/can_writer.cpp
Normal file
59
tests/manual_tests/silkit_can_com_tests/src/can_writer.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "../include/can_com_test_helper.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string config = R"(
|
||||
DebugInfo = true
|
||||
SyncMode = true
|
||||
SilKitParticipantName = "can_writer"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
)";
|
||||
|
||||
CTestCanSilKit canComObj;
|
||||
canComObj.Initialize(config.c_str());
|
||||
canComObj.SetOperationMode(sdv::EOperationMode::running);
|
||||
|
||||
uint8_t msgId = 65;
|
||||
uint8_t dataSize = 1;
|
||||
uint16_t i = 0;
|
||||
std::cout << "Can writes 30 different datas:\n";
|
||||
CComTestHelper testHelper;
|
||||
while(i < 30) //Sending 30 messages
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId, dataSize);
|
||||
canComObj.Send(testData, 0);
|
||||
|
||||
if(testData.seqData.size() != 0)
|
||||
{
|
||||
std::stringstream buffer;
|
||||
buffer << "\n[TX] CAN message being sent [CANID=";
|
||||
buffer << testData.uiID; buffer << ", Length=" ;
|
||||
buffer << unsigned(testData.seqData.size()); buffer << "]" ;
|
||||
|
||||
buffer << " Data=";
|
||||
for(uint16_t j = 0; j < testData.seqData.size(); j++)
|
||||
{
|
||||
buffer << "[" ; buffer << std::hex << unsigned(testData.seqData[j]); buffer << "] ";
|
||||
}
|
||||
std::cout << buffer.str().c_str();
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
msgId++;
|
||||
i++;
|
||||
dataSize++;
|
||||
if(dataSize > 8)
|
||||
dataSize = 1;
|
||||
}
|
||||
|
||||
canComObj.Shutdown();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user