mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
@@ -0,0 +1,29 @@
|
||||
[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
|
||||
SilKitParticipantName = "CAN1"
|
||||
CanSilKitNetwork = "PrivateCAN"
|
||||
RegistryURI = "silkit://localhost:8500"
|
||||
SilKitConfig = """{
|
||||
"Logging": {
|
||||
"Sinks": [ { "Type": "Stdout", "Level": "Info" } ]
|
||||
},
|
||||
}"""
|
||||
|
||||
[[Component]]
|
||||
Path = "can_datalink.sdv"
|
||||
Class = "CAN_data_link"
|
||||
|
||||
55
tests/manual_tests/silkit_can_com_tests/CMakeLists.txt
Normal file
55
tests/manual_tests/silkit_can_com_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
# Only build on MSVC/Windows or 64-bit Linux (not ARM)
|
||||
if((WIN32 AND NOT MSVC) OR (UNIX AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64"))
|
||||
|
||||
project(ManualTestCanComSilKit)
|
||||
|
||||
FetchContent_MakeAvailable(SilKit)
|
||||
|
||||
set(SilKit_DIR "${silkit_SOURCE_DIR}/SilKit/lib/cmake/SilKit")
|
||||
|
||||
find_package(SilKit REQUIRED CONFIG)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
add_compile_options(-Wno-shadow)
|
||||
endif()
|
||||
|
||||
add_executable(ManualTest_CANComSilKit
|
||||
src/can_com_manual_test_silkit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../sdv_services/can_communication_silkit/can_com_silkit.cpp
|
||||
)
|
||||
|
||||
add_executable(can_writer
|
||||
src/can_writer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../sdv_services/can_communication_silkit/can_com_silkit.cpp
|
||||
)
|
||||
|
||||
add_executable(can_reader
|
||||
src/can_reader.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../sdv_services/can_communication_silkit/can_com_silkit.cpp
|
||||
)
|
||||
|
||||
# Copy the config files
|
||||
if(UNIX)
|
||||
file(COPY ${PROJECT_SOURCE_DIR}/run_silkit_util.sh DESTINATION ${CMAKE_BINARY_DIR}/tests/manual_tests/)
|
||||
elseif(WIN32)
|
||||
file(COPY ${PROJECT_SOURCE_DIR}/run_silkit_util.bat DESTINATION ${CMAKE_BINARY_DIR}/tests/manual_tests/)
|
||||
endif()
|
||||
|
||||
target_link_libraries(ManualTest_CANComSilKit ${CMAKE_DL_LIBS} GTest::GTest SilKit::SilKit)
|
||||
target_link_libraries(can_writer ${CMAKE_DL_LIBS} GTest::GTest SilKit::SilKit )
|
||||
target_link_libraries(can_reader ${CMAKE_DL_LIBS} GTest::GTest SilKit::SilKit)
|
||||
|
||||
add_test(NAME ManualTest_CANComSilKit COMMAND ManualTest_CANComSilKit)
|
||||
|
||||
# add_custom_command(TARGET ManualTest_CANComSilKit POST_BUILD
|
||||
# COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ManualTest_CANComSilKit>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ManualTest_CANComSilKit.xml
|
||||
# VERBATIM
|
||||
# )
|
||||
|
||||
# Build dependencies
|
||||
add_dependencies(ManualTest_CANComSilKit dependency_sdv_components can_com_silkit)
|
||||
add_dependencies(can_reader dependency_sdv_components can_com_silkit)
|
||||
add_dependencies(can_writer dependency_sdv_components can_com_silkit)
|
||||
|
||||
endif() # Only build on MSVC/Windows or 64-bit Linux (not ARM)
|
||||
|
||||
128
tests/manual_tests/silkit_can_com_tests/README.md
Normal file
128
tests/manual_tests/silkit_can_com_tests/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# SilKit CAN Communication Tests
|
||||
This guide provides instructions on how to execute the manual tests for the SilKit CAN communication system, including the `can_reader` and `can_writer` components.
|
||||
|
||||
## Prerequisites
|
||||
Before running the tests, ensure the following:
|
||||
|
||||
- Operating System: Ubuntu (or a Linux distribution with gnome-terminal installed) **or Windows**.
|
||||
- Dependencies:
|
||||
- `sil-kit-registry` and `sil-kit-system-controller` binaries are available in the directory: `<...>/vapi-cpp-vehicle-api-platform/build/<compiler_version>/_deps/silkit-src/SilKit/bin/`
|
||||
- gnome-terminal is installed on your system (Linux only).
|
||||
- Build: The project has been built successfully, and the binaries for can_reader and can_writer are available in the directory: `<...>/vapi-cpp-vehicle-api-platform/build/<compiler_version>/tests/bin/`
|
||||
|
||||
## Test Components
|
||||
The tests involve the following components:
|
||||
|
||||
- `sil-kit-registry`: Manages the SilKit network.
|
||||
- `sil-kit-system-controller`: Controls the lifecycle of SilKit participants.
|
||||
- `can_writer`: Sends CAN messages to the network.
|
||||
- `can_reader`: Receives CAN messages from the network.
|
||||
|
||||
## Instructions
|
||||
|
||||
### Linux
|
||||
1. **Start the SilKit Utilities**
|
||||
- Navigate to the directory containing the `run_silkit_util.sh` script:
|
||||
```bash
|
||||
cd <...>/vapi-cpp-vehicle-api-platform/build/<compiler_version>/tests/manual_tests/
|
||||
```
|
||||
|
||||
- Make the script executable (if not already):
|
||||
```bash
|
||||
chmod +x run_silkit_util.sh
|
||||
```
|
||||
- Run the script to start the SilKit utilities:
|
||||
```bash
|
||||
./run_silkit_util.sh
|
||||
```
|
||||
This will open two new terminal windows:
|
||||
- One running `sil-kit-registry`.
|
||||
- Another running `sil-kit-system-controller` with the arguments `can_reader can_writer`.
|
||||
|
||||
2. **Run the CAN Writer**
|
||||
In a new terminal, navigate to the directory containing the can_writer binary:
|
||||
```bash
|
||||
cd <...>/vapi-cpp-vehicle-api-platform/build/<compiler_version>/tests/bin/
|
||||
```
|
||||
|
||||
- Run the can_writer binary:
|
||||
```bash
|
||||
./can_writer
|
||||
```
|
||||
|
||||
The `can_writer` will send different CAN messages to the network. Each message will be logged in the terminal.
|
||||
|
||||
3. **Run the CAN Reader**
|
||||
In another terminal, navigate to the directory containing the can_reader binary:
|
||||
```bash
|
||||
cd <...>/vapi-cpp-vehicle-api-platform/build/<compiler_version>/tests/bin/
|
||||
```
|
||||
|
||||
- Run the `can_reader` binary:
|
||||
```bash
|
||||
./can_reader
|
||||
```
|
||||
|
||||
The `can_reader` will receive and log the CAN messages sent by the `can_writer`. Each message will be logged in the terminal.
|
||||
|
||||
### Windows
|
||||
1. **Start the SilKit Utilities**
|
||||
- Before running the executables, copy the `SilKit.dll` and `SilKitd.dll` DLLs from the SilKit source directory `<..>\_deps\silkit-src\SilKit\bin` to the `<..>\test\bin` directory.
|
||||
|
||||
- Open PowerShell or Command Prompt and navigate to the directory containing the `run_silkit_util.bat` script (if available):
|
||||
```bat
|
||||
cd <...>\vapi-cpp-vehicle-api-platform\build\<compiler_version>\tests\manual_tests
|
||||
```
|
||||
- Run the script to start the SilKit utilities:
|
||||
```bat
|
||||
run_silkit_util.bat
|
||||
```
|
||||
This will open two new windows:
|
||||
- One running `sil-kit-registry`.
|
||||
- Another running `sil-kit-system-controller` with the arguments `can_reader can_writer`.
|
||||
|
||||
**If the script is not available, you can start the utilities manually:**
|
||||
- Open two Command Prompt or PowerShell windows:
|
||||
- In the first window, navigate to the SilKit bin directory and run:
|
||||
```bat
|
||||
cd <...>\vapi-cpp-vehicle-api-platform\build\<compiler_version>\_deps\silkit-src\SilKit\bin
|
||||
sil-kit-registry.exe
|
||||
```
|
||||
- In the second window, run:
|
||||
```bat
|
||||
sil-kit-system-controller.exe can_reader can_writer
|
||||
```
|
||||
|
||||
1. **Run the CAN Writer**
|
||||
- Open a new Command Prompt or PowerShell window and navigate to the directory containing the can_writer binary:
|
||||
```bat
|
||||
cd <...>\vapi-cpp-vehicle-api-platform\build\<compiler_version>\tests\bin
|
||||
can_writer.exe
|
||||
```
|
||||
|
||||
The `can_writer` will send different CAN messages to the network. Each message will be logged in the terminal.
|
||||
|
||||
3. **Run the CAN Reader**
|
||||
- Open another Command Prompt or PowerShell window and navigate to the directory containing the can_reader binary:
|
||||
```bat
|
||||
cd <...>\vapi-cpp-vehicle-api-platform\build\<compiler_version>\tests\bin
|
||||
can_reader.exe
|
||||
```
|
||||
|
||||
The `can_reader` will receive and log the CAN messages sent by the `can_writer`. Each message will be logged in the terminal.
|
||||
|
||||
## Expected Output
|
||||
- **CAN Writer:** Logs the messages being sent, including the CAN ID, data length, and data content in the terminal.
|
||||
|
||||
- **CAN Reader:** Logs the messages being received, including the CAN ID, data length, and data content in the terminal.
|
||||
|
||||
## Troubleshooting
|
||||
- Binaries Not Found: Ensure the `sil-kit-registry`, `sil-kit-system-controller`, `can_writer`, and `can_reader` binaries are built and located in the correct directories.
|
||||
|
||||
- **Terminal Emulator: The script uses gnome-terminal on Linux. On Windows, PowerShell is used. If you use a different terminal emulator, modify the scripts accordingly.**
|
||||
|
||||
- Network Issues: Ensure the RegistryURI in the configuration matches the address of the sil-kit-registry.
|
||||
|
||||
## Additional Notes
|
||||
- The `can_writer` and `can_reader` configurations are hardcoded in their respective source files. If you need to modify the configurations (e.g., participant names, network names, or registry URI), update the source code and rebuild the binaries.
|
||||
- The tests are designed to run in synchronous mode (SyncMode = true). Ensure this setting is consistent across all components.
|
||||
@@ -0,0 +1,217 @@
|
||||
#ifndef TEST_CAN_SILKIT_HELPER_H
|
||||
#define TEST_CAN_SILKIT_HELPER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#include <thread>
|
||||
#include <gtest/gtest.h>
|
||||
#include <interfaces/can.h>
|
||||
#include <support/app_control.h>
|
||||
#include <support/toml.h>
|
||||
#include <support/component_impl.h>
|
||||
#include "../sdv_services/core/toml_parser/parser_toml.h"
|
||||
#include "../../../../sdv_services/can_communication_silkit/can_com_silkit.h"
|
||||
#include "../../../../export/support/app_control.h"
|
||||
|
||||
class CTestCanSilKit : public CCANSilKit
|
||||
{
|
||||
public:
|
||||
virtual void Initialize(const sdv::u8string& ssObjectConfig) override
|
||||
{
|
||||
return CCANSilKit::Initialize(ssObjectConfig);
|
||||
}
|
||||
|
||||
virtual sdv::EObjectStatus GetStatus() const override
|
||||
{
|
||||
return CCANSilKit::GetStatus();
|
||||
}
|
||||
|
||||
virtual void Shutdown() override
|
||||
{
|
||||
return CCANSilKit::Shutdown();
|
||||
}
|
||||
|
||||
virtual void RegisterReceiver(/*in*/ sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
return CCANSilKit::RegisterReceiver(pReceiver);
|
||||
}
|
||||
|
||||
virtual void UnregisterReceiver(/*in*/ sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
return CCANSilKit::UnregisterReceiver(pReceiver);
|
||||
}
|
||||
|
||||
virtual void Send(/*in*/ const sdv::can::SMessage& sMsg, /*in*/ uint32_t uiIfcIndex) override
|
||||
{
|
||||
return CCANSilKit::Send(sMsg, uiIfcIndex);
|
||||
}
|
||||
|
||||
virtual sdv::sequence<sdv::u8string> GetInterfaces() const override
|
||||
{
|
||||
return CCANSilKit::GetInterfaces();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
sdv::can::SMessage CreateCanMsgData(uint8_t init, uint8_t dataSize)
|
||||
{
|
||||
uint8_t value = init;
|
||||
sdv::can::SMessage testMsg;
|
||||
testMsg.uiID = value;
|
||||
testMsg.bCanFd = false;
|
||||
testMsg.bExtended = false;
|
||||
testMsg.seqData.resize(dataSize);
|
||||
for (uint8_t i = 0; i < dataSize; i++)
|
||||
{
|
||||
testMsg.seqData[i] = value;
|
||||
value += 2;
|
||||
}
|
||||
return testMsg;
|
||||
}
|
||||
|
||||
|
||||
class CanReceiver : public sdv::can::IReceive
|
||||
{
|
||||
public:
|
||||
|
||||
void Receive(const sdv::can::SMessage& sMessage, uint32_t) override
|
||||
{
|
||||
vecReceivedMessages.push_back(sMessage);
|
||||
}
|
||||
void Error(const sdv::can::SErrorFrame&, uint32_t) override {}
|
||||
|
||||
std::vector<sdv::can::SMessage> GetReceivedMessages()
|
||||
{
|
||||
return vecReceivedMessages;
|
||||
}
|
||||
|
||||
void ClearReceivedMessages()
|
||||
{
|
||||
vecReceivedMessages.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<sdv::can::SMessage> vecReceivedMessages;
|
||||
};
|
||||
|
||||
class CComTestHelper
|
||||
{
|
||||
public:
|
||||
struct PcloseDeleter
|
||||
{
|
||||
void operator()(FILE* file) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_pclose(file);
|
||||
#else
|
||||
pclose(file);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
std::string exec(const char* cmd)
|
||||
{
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
#ifdef _WIN32
|
||||
std::unique_ptr<FILE, PcloseDeleter> pipe(_popen(cmd, "r"));
|
||||
#else
|
||||
std::unique_ptr<FILE, PcloseDeleter> pipe(popen(cmd, "r"));
|
||||
#endif
|
||||
if (!pipe)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
while (fgets(buffer.data(), static_cast<int>(buffer.size()), pipe.get()) != nullptr)
|
||||
{
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
sdv::can::SMessage CreateTestData(uint8_t init, uint8_t dataSize)
|
||||
{
|
||||
uint8_t value = 65;
|
||||
// uint8_t value = init;
|
||||
sdv::can::SMessage testMsg;
|
||||
testMsg.uiID = init;
|
||||
testMsg.bCanFd = false;
|
||||
testMsg.bExtended = false;
|
||||
testMsg.seqData.resize(dataSize);
|
||||
for (uint8_t i = 0; i < dataSize; i++)
|
||||
{
|
||||
testMsg.seqData[i] = value;
|
||||
value += 2;
|
||||
}
|
||||
return testMsg;
|
||||
}
|
||||
|
||||
bool ValidateInterfaces(const sdv::sequence<sdv::u8string>& seqExpectedInterfaces, const sdv::sequence<sdv::u8string>& seqInterfaces)
|
||||
{
|
||||
bool success = true;
|
||||
if (seqExpectedInterfaces.size() != seqInterfaces.size())
|
||||
{
|
||||
std::cout << "Interfaces failure, expected: " << std::to_string(seqExpectedInterfaces.size()) << " got: " << std::to_string(seqInterfaces.size()) << std::endl;
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < seqInterfaces.size(); nIndex++)
|
||||
{
|
||||
if (seqExpectedInterfaces[nIndex].compare(seqInterfaces[nIndex]) != 0)
|
||||
{
|
||||
success = false,
|
||||
std::cout << "Interface mismatch, expected: " << seqExpectedInterfaces[nIndex].c_str() << " got: " << seqInterfaces[nIndex].c_str() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ValidateReceivedMessages(const std::deque<std::pair<std::string, sdv::can::SMessage>>& received,
|
||||
const sdv::can::SMessage& testMessage, const std::string& interfaceName, size_t expectedSize)
|
||||
{
|
||||
uint32_t error = 0;
|
||||
if (expectedSize == 0)
|
||||
error++;
|
||||
|
||||
if (received.size() != expectedSize)
|
||||
error++;
|
||||
|
||||
for (auto message : received)
|
||||
{
|
||||
if (interfaceName.compare(message.first) != 0)
|
||||
error++;
|
||||
|
||||
if (message.second.uiID != testMessage.uiID)
|
||||
error++;
|
||||
|
||||
if (message.second.seqData.size() != testMessage.seqData.size())
|
||||
error++;
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
std::cout << "Got " << std::to_string(error) << " errors from validation of "
|
||||
<< interfaceName << ", expect " << std::to_string(expectedSize)
|
||||
<< " messages, got " << std::to_string(received.size()) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string NormalizeWhitespace(const std::string& str)
|
||||
{
|
||||
std::string trimmed = str;
|
||||
trimmed.erase(trimmed.find_last_not_of(" \t\n\r") + 1); // Trim trailing whitespace
|
||||
trimmed.erase(0, trimmed.find_first_not_of(" \t\n\r")); // Trim leading whitespace
|
||||
std::string result;
|
||||
std::unique_copy(trimmed.begin(), trimmed.end(), std::back_inserter(result),
|
||||
[](char a, char b) { return std::isspace(a) && std::isspace(b); });
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ! defined TEST_CAN_SILKIT_HELPER_H
|
||||
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
REM Run sil-kit-registry in a new Command Prompt window
|
||||
start cmd /k "..\..\_deps\silkit-src\SilKit\bin\sil-kit-registry.exe"
|
||||
|
||||
REM Run sil-kit-system-controller with arguments in another new Command Prompt window
|
||||
start cmd /k "..\..\_deps\silkit-src\SilKit\bin\sil-kit-system-controller.exe can_reader can_writer"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Run sil-kit-registry in a new terminal window
|
||||
gnome-terminal -- bash -c "./../../_deps/silkit-src/SilKit/bin/sil-kit-registry; exec bash"
|
||||
|
||||
# Run sil-kit-system-controller with arguments in another new terminal window
|
||||
gnome-terminal -- bash -c "./../../_deps/silkit-src/SilKit/bin/sil-kit-system-controller can_reader can_writer; exec bash"
|
||||
@@ -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