mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-04-20 11:18:16 +00:00
35
tests/unit_tests/socket_can_com_tests/CMakeLists.txt
Normal file
35
tests/unit_tests/socket_can_com_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,35 @@
|
||||
# Only valid for Linux
|
||||
if(UNIX)
|
||||
|
||||
project(UnitTestCanComSocket)
|
||||
|
||||
# Include directories
|
||||
include_directories(../../export)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/../sdv_services/can_communication_socket_can)
|
||||
|
||||
# Add the executable
|
||||
add_executable(UnitTest_CANComSocket
|
||||
src/can_com_test_socket.cpp
|
||||
${CMAKE_SOURCE_DIR}/sdv_services/can_communication_socket_can/can_com_sockets.cpp
|
||||
)
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(UnitTest_CANComSocket ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT} rt GTest::GTest)
|
||||
|
||||
# Add test
|
||||
add_test(NAME UnitTest_CANComSocket COMMAND UnitTest_CANComSocket)
|
||||
|
||||
# Execute the test
|
||||
add_custom_command(TARGET UnitTest_CANComSocket POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_CANComSocket>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unitTest_CANComSocket.xml
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Copy the config files
|
||||
file (COPY ${PROJECT_SOURCE_DIR}/config/test_can_socket.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config)
|
||||
|
||||
# Build dependencies
|
||||
add_dependencies(UnitTest_CANComSocket dependency_sdv_components)
|
||||
add_dependencies(UnitTest_CANComSocket can_com_sockets)
|
||||
|
||||
endif()
|
||||
77
tests/unit_tests/socket_can_com_tests/README.md
Normal file
77
tests/unit_tests/socket_can_com_tests/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Virtual CAN Interface Setup and Testing
|
||||
|
||||
This guide explains how to set up virtual CAN interfaces (`vcan0` and `vcan1`) on a Linux system and how to run tests using these interfaces.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A Linux system with `iproute2` and `can-utils` installed.
|
||||
- Root or sudo privileges.
|
||||
|
||||
## Setup Virtual CAN Interfaces
|
||||
|
||||
1. **Load the `vcan` kernel module:**
|
||||
|
||||
```bash
|
||||
sudo modprobe vcan
|
||||
```
|
||||
|
||||
2. **Create the virtual CAN interfaces:**
|
||||
|
||||
```bash
|
||||
sudo ip link add dev vcan0 type vcan
|
||||
sudo ip link add dev vcan1 type vcan
|
||||
sudo ip link add dev vcan2 type vcan
|
||||
sudo ip link add dev vcan3 type vcan
|
||||
sudo ip link add dev vcan4 type vcan
|
||||
```
|
||||
|
||||
3. **Bring the virtual CAN interfaces online:**
|
||||
|
||||
```bash
|
||||
sudo ip link set up vcan0
|
||||
sudo ip link set up vcan1
|
||||
sudo ip link set up vcan2
|
||||
sudo ip link set up vcan3
|
||||
sudo ip link set up vcan4
|
||||
```
|
||||
|
||||
4. **Verify the virtual CAN interfaces:**
|
||||
|
||||
```bash
|
||||
ip addr | grep "vcan"
|
||||
```
|
||||
|
||||
You should see `vcan0` and `vcan1` listed as available interfaces.
|
||||
|
||||
5. **Remove the virtual CAN interfaces:**
|
||||
|
||||
```bash
|
||||
sudo ip link set down vcan0
|
||||
sudo ip link delete vcan0
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
1. **Listen for CAN messages on `vcan0`:**
|
||||
|
||||
```bash
|
||||
candump vcan0
|
||||
```
|
||||
|
||||
2. **Send a CAN message on `vcan0` (from another terminal):**
|
||||
|
||||
```bash
|
||||
cansend vcan0 123#DEADBEEF
|
||||
```
|
||||
You should see the message `123#DEADBEEF` appear on `vcan0`.
|
||||
|
||||
## Explanation
|
||||
|
||||
This setup uses virtual CAN interfaces (`vcan0` and `vcan1`) to simulate a CAN bus environment. This is useful for testing CAN applications without the need for physical CAN hardware.
|
||||
|
||||
**After virtual can is ready uncomment this line `#add_subdirectory(manual_tests/socket_can_com_tests)` from `vapi-cpp-vehicle-api-platform/tests/CMakeLists.txt` and then reconfigure and build the project to run the tests.**
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- SocketCAN Documentation
|
||||
- [can-utils GitHub Repository](https://github.com/linux-can/can-utils)
|
||||
@@ -0,0 +1,7 @@
|
||||
[Configuration]
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "can_com_sockets.sdv"
|
||||
Class = "CAN_Com_Sockets"
|
||||
canSockets=["vcan3"]
|
||||
@@ -0,0 +1,188 @@
|
||||
#ifndef CAN_TEST_HELPER_H
|
||||
#define CAN_TEST_SOCKET_H
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#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_socket_can/can_com_sockets.h"
|
||||
|
||||
class CComTestHelper
|
||||
{
|
||||
public:
|
||||
bool IsVcanInstalled()
|
||||
{
|
||||
std::string result = exec("ip addr | grep can");
|
||||
if(!result.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isInstalled = false;
|
||||
exec("sudo ip link add dev vcan0 type vcan"); // try to create something
|
||||
result = exec("ip addr | grep can");
|
||||
if(!result.empty())
|
||||
{
|
||||
isInstalled = true;
|
||||
}
|
||||
exec("sudo ip link delete vcan0"); // revert it again
|
||||
|
||||
return isInstalled;
|
||||
}
|
||||
|
||||
struct PcloseDeleter
|
||||
{
|
||||
void operator()(FILE* file) const
|
||||
{
|
||||
pclose(file);
|
||||
}
|
||||
};
|
||||
|
||||
std::string exec(const char* cmd)
|
||||
{
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::unique_ptr<FILE, PcloseDeleter> pipe(popen(cmd, "r"));
|
||||
if (!pipe)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
|
||||
{
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ValidateVCanSetup(const std::string& name, bool expected)
|
||||
{
|
||||
bool found = false;
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
if (getifaddrs(&ifaddr) != -1)
|
||||
{
|
||||
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (name.compare(ifa->ifa_name) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddr);
|
||||
|
||||
if (found == expected)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << "VCan setup: Interface " << name << " expected to be = " << std::to_string(expected)
|
||||
<< " but is = " << std::to_string(found) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
sdv::can::SMessage CreateTestData(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;
|
||||
}
|
||||
sdv::can::SMessage CreateTestData2(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;
|
||||
if(i==2)testMsg.seqData[i] = 7;
|
||||
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 CAN_TEST_HELPER_H
|
||||
@@ -0,0 +1,828 @@
|
||||
#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 CANSocketTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
virtual void SetUp() override
|
||||
{
|
||||
if (vcanIsInstalled)
|
||||
{
|
||||
CComTestHelper testhelper;
|
||||
// interfaces required for the test
|
||||
RequiredVCAN(testhelper, true, "vcan0", "sudo ip link add dev vcan0 type vcan", "sudo ip link set up vcan0");
|
||||
RequiredVCAN(testhelper, true, "vcan1", "sudo ip link add dev vcan1 type vcan", "sudo ip link set up vcan1");
|
||||
RequiredVCAN(testhelper, true, "vcan2", "sudo ip link add dev vcan2 type vcan", "sudo ip link set up vcan2");
|
||||
RequiredVCAN(testhelper, true, "vcan3", "sudo ip link add dev vcan3 type vcan", "sudo ip link set up vcan3");
|
||||
RequiredVCAN(testhelper, true, "vcan4", "sudo ip link add dev vcan4 type vcan", "sudo ip link set up vcan4");
|
||||
// "vcan8" & "vcan9" were interfaces that must not exist.
|
||||
RequiredVCAN(testhelper, false, "vcan8", "sudo ip link set down vcan8", "sudo ip link delete vcan8");
|
||||
RequiredVCAN(testhelper, false, "vcan9", "sudo ip link set down vcan9", "sudo ip link delete vcan9");
|
||||
}
|
||||
else
|
||||
{
|
||||
GTEST_SKIP() << "Skipping test because vcan is not installed.";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown() override
|
||||
{
|
||||
}
|
||||
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
CComTestHelper testhelper;
|
||||
vcanIsInstalled = testhelper.IsVcanInstalled();
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {}
|
||||
|
||||
bool RequiredVCAN(CComTestHelper testhelper, bool expected, std::string name,
|
||||
std::string addDevcommand, std::string setupCommand)
|
||||
{
|
||||
if (!testhelper.ValidateVCanSetup(name.c_str(), expected))
|
||||
{
|
||||
testhelper.exec(addDevcommand.c_str());
|
||||
testhelper.exec(setupCommand.c_str());
|
||||
if (!testhelper.ValidateVCanSetup(name.c_str(), expected))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveCanDumpFilesWithPrefix()
|
||||
{
|
||||
std::string directory = "."; // Current directory
|
||||
std::string prefix = "candump_output_vcan";
|
||||
for (const auto& entry : std::filesystem::directory_iterator(directory))
|
||||
{
|
||||
if (entry.is_regular_file() && entry.path().filename().string().find(prefix) == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::filesystem::remove(entry.path());
|
||||
std::cout << "Deleted: " << entry.path() << std::endl;
|
||||
} catch (const std::filesystem::filesystem_error&)
|
||||
{
|
||||
std::cout << "Failed to delete: " << entry.path() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool vcanIsInstalled;
|
||||
};
|
||||
// Define the static member variable
|
||||
bool CANSocketTest::vcanIsInstalled = false;
|
||||
|
||||
class CTestCANSocket : public CCANSockets
|
||||
{
|
||||
public:
|
||||
virtual void Initialize(const sdv::u8string& ssObjectConfig) override
|
||||
{
|
||||
CCANSockets::Initialize(ssObjectConfig);
|
||||
}
|
||||
|
||||
virtual void Shutdown() override
|
||||
{
|
||||
CCANSockets::Shutdown();
|
||||
}
|
||||
|
||||
virtual void Send(const sdv::can::SMessage& sMsg, uint32_t uiIfcIndex) override
|
||||
{
|
||||
CCANSockets::Send(sMsg, uiIfcIndex);
|
||||
m_MessagesSent++;
|
||||
}
|
||||
|
||||
virtual void RegisterReceiver(sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
CCANSockets::RegisterReceiver(pReceiver);
|
||||
}
|
||||
|
||||
virtual void UnregisterReceiver(sdv::can::IReceive* pReceiver) override
|
||||
{
|
||||
CCANSockets::UnregisterReceiver(pReceiver);
|
||||
}
|
||||
|
||||
virtual sdv::sequence<sdv::u8string> GetInterfaces() const override
|
||||
{
|
||||
return CCANSockets::GetInterfaces();
|
||||
}
|
||||
|
||||
sdv::EObjectStatus GetTestStatus() const
|
||||
{
|
||||
return CCANSockets::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(GetInterfaceName(ifIndex), msg));
|
||||
}
|
||||
|
||||
void Error(const sdv::can::SErrorFrame&, uint32_t) override {}
|
||||
|
||||
std::deque<std::pair<std::string, sdv::can::SMessage>>GetReceivedMessages() const
|
||||
{
|
||||
return m_receivedMessages;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string GetInterfaceName (int ifIndex)
|
||||
{
|
||||
std::string name = "UnknownInterface";
|
||||
// Retrieve the list of available interfaces
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
if (getifaddrs(&ifaddr) != -1)
|
||||
{
|
||||
std::vector<std::string> available;
|
||||
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
|
||||
{
|
||||
int indexFromName = if_nametoindex(ifa->ifa_name);
|
||||
if (indexFromName == ifIndex)
|
||||
{
|
||||
name = ifa->ifa_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::deque<std::pair<std::string, sdv::can::SMessage>> m_receivedMessages; ///< Interface name, message
|
||||
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(CTestCANSocket& 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(CTestCANSocket& canComObj, MockCANReceiver& mockRcv)
|
||||
{
|
||||
EXPECT_NO_THROW(canComObj.UnregisterReceiver(&mockRcv));
|
||||
ASSERT_NO_THROW(canComObj.Shutdown());
|
||||
}
|
||||
|
||||
void SendThread(bool& stop, CTestCANSocket& 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(CANSocketTest, ValidConfigString)
|
||||
{
|
||||
sdv::can::SMessage testMsg {1, 0, 0, {0x11, 0x22, 0x33, 0x44}};
|
||||
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig = R"(canSockets = "vcan0")"; // vcan0 interface must exist
|
||||
CTestCANSocket 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::destruction_pending);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, InvalidConfigString)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig = R"(canSockets = "vcan08")";
|
||||
CTestCANSocket 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::destruction_pending);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, ValidConfigArray)
|
||||
{
|
||||
sdv::can::SMessage testMsg {1, 0, 0, {0x11, 0x22, 0x33, 0x44}};
|
||||
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig = R"(canSockets = ["vcan0", "vcan1"])";
|
||||
CTestCANSocket canComObj;
|
||||
ASSERT_NO_THROW(canComObj.Initialize(ssObjectConfig.c_str()));
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
|
||||
ASSERT_NO_THROW(canComObj.Send(testMsg, 0));
|
||||
|
||||
EXPECT_NO_THROW(canComObj.Shutdown());
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::destruction_pending);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, InvalidConfigArray)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig = R"(canSockets = ["vcan08", "vcan09"])";
|
||||
CTestCANSocket 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::destruction_pending);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, ValidConfigArrayButUnknownElement)
|
||||
{
|
||||
sdv::can::SMessage testMsg {1, 0, 0, {0x11, 0x22, 0x33, 0x44}};
|
||||
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig = R"(canSockets = ["vcan0", "vcan08"])";
|
||||
CTestCANSocket canComObj;
|
||||
ASSERT_NO_THROW(canComObj.Initialize(ssObjectConfig.c_str()));
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
|
||||
ASSERT_NO_THROW(canComObj.Send(testMsg, 0));
|
||||
|
||||
ASSERT_NO_THROW(canComObj.Shutdown());
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::destruction_pending);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, InvalidConfigIdentifier)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssObjectConfig = R"(invalidCanSockets = ["vcan0", "vcan1"])"; // Invalid config identifier
|
||||
CTestCANSocket 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::destruction_pending);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, ReceiveTestDifferentDataSizes)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssConfig1 = R"(canSockets = ["vcan1", "vcan2"])";
|
||||
sdv::u8string ssConfig2 = R"(canSockets = ["vcan2", "vcan1"])";
|
||||
|
||||
// Object1 sends to Object2; Object2 sends to Object1
|
||||
CTestCANSocket canComObj1;
|
||||
CTestCANSocket canComObj2;
|
||||
MockCANReceiver mockRcv1;
|
||||
MockCANReceiver mockRcv2;
|
||||
InitializeCanComObject(canComObj1, ssConfig1, mockRcv1);
|
||||
InitializeCanComObject(canComObj2, ssConfig2, mockRcv2);
|
||||
|
||||
uint32_t msgId1 = 102;
|
||||
uint32_t msgId2 = 201;
|
||||
uint32_t dataSize = 1;
|
||||
uint32_t expectToBeSend = 8; // other data sizes are to large
|
||||
uint32_t msgToBeSend = 16;
|
||||
CComTestHelper testHelper;
|
||||
while (dataSize < msgToBeSend)
|
||||
{
|
||||
auto testData1 = testHelper.CreateTestData(msgId1, dataSize);
|
||||
auto testData2 = testHelper.CreateTestData(msgId2, dataSize);
|
||||
EXPECT_NO_THROW(canComObj1.Send(testData1, 1)); // Send to vcan2
|
||||
EXPECT_NO_THROW(canComObj2.Send(testData2, 1)); // Send to vcan1
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
auto receivedMessages1 = mockRcv1.GetReceivedMessages();
|
||||
auto receivedMessages2 = mockRcv2.GetReceivedMessages();
|
||||
|
||||
if ((expectToBeSend != receivedMessages1.size()) || (expectToBeSend != receivedMessages2.size()))
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << " Failed, expected " << std::to_string(expectToBeSend ) << " messages, got from vcan1 to vcan2: "
|
||||
<< std::to_string(receivedMessages1.size()) << " messages, from vcan2 to vcan1: "
|
||||
<< std::to_string(receivedMessages2.size()) << " messages.";
|
||||
FAIL() << sstream.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSize = 1;
|
||||
for(auto receivedMessage : receivedMessages1)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId2, dataSize);
|
||||
EXPECT_EQ(msgId2, receivedMessage.second.uiID);
|
||||
EXPECT_EQ(dataSize++, receivedMessage.second.seqData.size());
|
||||
EXPECT_EQ(testData.seqData, receivedMessage.second.seqData);
|
||||
}
|
||||
dataSize = 1;
|
||||
for(auto receivedMessage : receivedMessages2)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId1, dataSize);
|
||||
EXPECT_EQ(msgId1, receivedMessage.second.uiID);
|
||||
EXPECT_EQ(dataSize++, receivedMessage.second.seqData.size());
|
||||
EXPECT_EQ(testData.seqData, receivedMessage.second.seqData);
|
||||
}
|
||||
}
|
||||
|
||||
ShutDownCanComObject(canComObj1, mockRcv1);
|
||||
ShutDownCanComObject(canComObj2, mockRcv2);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, ReceiveTestDifferentDataSizesAndInvalidConfiguration)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssConfig1 = R"(canSockets = ["vcan1", "vcan8", "vcan9", "vcan2"])";
|
||||
sdv::u8string ssConfig2 = R"(canSockets = ["vcan2", "vcan9", "vcan1"])";
|
||||
|
||||
// Object1 sends to Object2; Object2 sends to Object1
|
||||
CTestCANSocket canComObj1;
|
||||
CTestCANSocket canComObj2;
|
||||
MockCANReceiver mockRcv1;
|
||||
MockCANReceiver mockRcv2;
|
||||
InitializeCanComObject(canComObj1, ssConfig1, mockRcv1);
|
||||
InitializeCanComObject(canComObj2, ssConfig2, mockRcv2);
|
||||
|
||||
CComTestHelper testHelper;
|
||||
uint32_t msgId1 = 102;
|
||||
uint32_t msgId2 = 201;
|
||||
uint32_t dataSize = 1;
|
||||
uint32_t expectToBeSend = 8; // other data sizes are to large
|
||||
uint32_t msgToBeSend = 16;
|
||||
while (dataSize < msgToBeSend)
|
||||
{
|
||||
auto testData1 = testHelper.CreateTestData(msgId1, dataSize);
|
||||
auto testData2 = testHelper.CreateTestData(msgId2, dataSize);
|
||||
EXPECT_NO_THROW(canComObj1.Send(testData1, 3)); // Send to vcan2, index 1 & 2 are invalid in config
|
||||
EXPECT_NO_THROW(canComObj2.Send(testData2, 2)); // Send to vcan1, index 1 in config
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
auto receivedMessages1 = mockRcv1.GetReceivedMessages();
|
||||
auto receivedMessages2 = mockRcv2.GetReceivedMessages();
|
||||
|
||||
if ((expectToBeSend != receivedMessages1.size()) || (expectToBeSend != receivedMessages2.size()))
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << " Failed to send " << std::to_string(expectToBeSend ) << " messages, got from vcan1 to vcan2: "
|
||||
<< std::to_string(receivedMessages1.size()) << " messages, from vcan2 to vcan1: "
|
||||
<< std::to_string(receivedMessages2.size()) << " messages.";
|
||||
FAIL() << sstream.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSize = 1;
|
||||
for(auto receivedMessage : receivedMessages1)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId2, dataSize);
|
||||
EXPECT_EQ(msgId2, receivedMessage.second.uiID);
|
||||
EXPECT_EQ(dataSize++, receivedMessage.second.seqData.size());
|
||||
EXPECT_EQ(testData.seqData, receivedMessage.second.seqData);
|
||||
}
|
||||
dataSize = 1;
|
||||
for(auto receivedMessage : receivedMessages2)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId1, dataSize);
|
||||
EXPECT_EQ(msgId1, receivedMessage.second.uiID);
|
||||
EXPECT_EQ(dataSize++, receivedMessage.second.seqData.size());
|
||||
EXPECT_EQ(testData.seqData, receivedMessage.second.seqData);
|
||||
}
|
||||
}
|
||||
|
||||
ShutDownCanComObject(canComObj1, mockRcv1);
|
||||
ShutDownCanComObject(canComObj2, mockRcv2);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, StressTestWith3Objects)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
sdv::u8string ssConfig1 = R"(canSockets = ["vcan1", "vcan2"])";
|
||||
sdv::u8string ssConfig2 = R"(canSockets = ["vcan2", "vcan3"])";
|
||||
sdv::u8string ssConfig3 = R"(canSockets = ["vcan3", "vcan1"])";
|
||||
|
||||
// Object1 sends to Object2; Object2 sends to Object3; Object3 sends to Object1
|
||||
CTestCANSocket canComObj1;
|
||||
CTestCANSocket canComObj2;
|
||||
CTestCANSocket canComObj3;
|
||||
MockCANReceiver mockRcv1;
|
||||
MockCANReceiver mockRcv2;
|
||||
MockCANReceiver mockRcv3;
|
||||
InitializeCanComObject(canComObj1, ssConfig1, mockRcv1);
|
||||
InitializeCanComObject(canComObj2, ssConfig2, mockRcv2);
|
||||
InitializeCanComObject(canComObj3, ssConfig3, mockRcv3);
|
||||
|
||||
CComTestHelper testHelper;
|
||||
auto testData1 = testHelper.CreateTestData(10, 6); // Testdata to send to vcan2, size = 6
|
||||
auto testData2 = testHelper.CreateTestData(20, 7); // Testdata to send to vcan3, size = 7
|
||||
auto testData3 = testHelper.CreateTestData(30, 8); // Testdata to send to vcan1, size = 8
|
||||
|
||||
bool stopSendThread = false;
|
||||
std::cout << "Start thread sending messages..." << std::endl;
|
||||
std::thread thSendThread1(SendThread, std::ref(stopSendThread), std::ref(canComObj1), std::ref(testData1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::thread thSendThread2(SendThread, std::ref(stopSendThread), std::ref(canComObj2), std::ref(testData2));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::thread thSendThread3(SendThread, std::ref(stopSendThread), std::ref(canComObj3), std::ref(testData3));
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
|
||||
stopSendThread = true;
|
||||
if (thSendThread1.joinable())
|
||||
thSendThread1.join();
|
||||
if (thSendThread2.joinable())
|
||||
thSendThread2.join();
|
||||
if (thSendThread3.joinable())
|
||||
thSendThread3.join();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
|
||||
auto receivedMessages1 = mockRcv1.GetReceivedMessages();
|
||||
auto receivedMessages2 = mockRcv2.GetReceivedMessages();
|
||||
auto receivedMessages3 = mockRcv3.GetReceivedMessages();
|
||||
std::cout << "Number of messages from vcan1 to vcan2: " << std::to_string(canComObj1.GetMessagesSent())
|
||||
<< ", from vcan2 to vcan3: " << std::to_string(canComObj2.GetMessagesSent())
|
||||
<< ", from vcan3 to vcan1: " << std::to_string(canComObj3.GetMessagesSent()) << std::endl;
|
||||
EXPECT_EQ(testHelper.ValidateReceivedMessages(receivedMessages1, testData3, "vcan1", canComObj3.GetMessagesSent()), true);
|
||||
EXPECT_EQ(testHelper.ValidateReceivedMessages(receivedMessages2, testData1, "vcan2", canComObj1.GetMessagesSent()), true);
|
||||
EXPECT_EQ(testHelper.ValidateReceivedMessages(receivedMessages3, testData2, "vcan3", canComObj2.GetMessagesSent()), true);
|
||||
|
||||
ShutDownCanComObject(canComObj1, mockRcv1);
|
||||
ShutDownCanComObject(canComObj2, mockRcv2);
|
||||
ShutDownCanComObject(canComObj3, mockRcv3);
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, SendWithVAPICompTest)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
|
||||
auto bResult = InitializeAppControl(&appControl, "test_can_socket.toml");
|
||||
|
||||
EXPECT_EQ(bResult, true);
|
||||
|
||||
// Load SocketCAN
|
||||
sdv::TInterfaceAccessPtr ptrCanComObj = sdv::core::GetObject("CAN_Communication_Object");
|
||||
EXPECT_NE(&ptrCanComObj, nullptr);
|
||||
|
||||
sdv::can::ISend* pCanSend = ptrCanComObj.GetInterface<sdv::can::ISend>();
|
||||
EXPECT_NE(&pCanSend, nullptr);
|
||||
|
||||
ASSERT_NO_THROW(appControl.SetRunningMode());
|
||||
|
||||
// Clear the candump output file if it exists
|
||||
std::string candumpFile = "candump_vapi_send.txt";
|
||||
try
|
||||
{
|
||||
if (std::filesystem::exists(candumpFile))
|
||||
std::filesystem::remove(candumpFile);
|
||||
} catch (const std::filesystem::filesystem_error&)
|
||||
{}
|
||||
|
||||
// Start candump in the background
|
||||
std::string candumpCommand = "candump vcan3 > " + candumpFile + " &";
|
||||
system(candumpCommand.c_str());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Ensure candump is ready
|
||||
|
||||
CComTestHelper testHelper;
|
||||
uint32_t msgId = 999;
|
||||
uint32_t dataSize = 1;
|
||||
uint32_t msgToBeSend = 8;
|
||||
while (dataSize < msgToBeSend)
|
||||
{
|
||||
auto testData1 = testHelper.CreateTestData(msgId, dataSize);
|
||||
ASSERT_NO_THROW(pCanSend->Send(testData1, 0));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
msgId++;
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
// Wait for messages to be written to the file
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
|
||||
// Compare sent messages with the candump output
|
||||
std::ifstream inputFile(candumpFile);
|
||||
ASSERT_TRUE(inputFile.is_open()) << "Failed to open candump output file.";
|
||||
|
||||
msgId = 999;
|
||||
dataSize = 1;
|
||||
std::string line;
|
||||
while (std::getline(inputFile, line) && dataSize < msgToBeSend)
|
||||
{
|
||||
auto expectedData = testHelper.CreateTestData(msgId, dataSize);
|
||||
std::stringstream expectedLine;
|
||||
|
||||
// Format the CAN interface name ("vcan3") and the message ID (uiID) in hexadecimal,
|
||||
// ensuring it is uppercase, 3 characters wide, and padded with zeros if necessary.
|
||||
expectedLine << "vcan3 " << std::hex << std::uppercase << std::setw(3) << std::setfill('0') << expectedData.uiID
|
||||
<< " [" << expectedData.seqData.size() << "] ";
|
||||
|
||||
// Loop through each byte in the data sequence (seqData) and format it as a
|
||||
// 2-character wide, zero-padded hexadecimal value, appending it to the stringstream.
|
||||
for (auto byte : expectedData.seqData)
|
||||
{
|
||||
expectedLine << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
|
||||
}
|
||||
|
||||
std::string normalizedExpected = testHelper.NormalizeWhitespace(expectedLine.str());
|
||||
std::string normalizedActual = testHelper.NormalizeWhitespace(line);
|
||||
|
||||
if (normalizedActual != normalizedExpected)
|
||||
{
|
||||
FAIL() << "Mismatch in candump output for message ID " << msgId
|
||||
<< "\nExpected: " << normalizedExpected
|
||||
<< "\nActual: " << normalizedActual;
|
||||
}
|
||||
|
||||
msgId++;
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
inputFile.close();
|
||||
ASSERT_NO_THROW(appControl.Shutdown());
|
||||
// Stop candump
|
||||
system("pkill candump");
|
||||
}
|
||||
|
||||
TEST_F(CANSocketTest, ReceiveWithVAPICompTest)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
|
||||
auto bResult = InitializeAppControl(&appControl, "test_can_socket.toml");
|
||||
|
||||
EXPECT_EQ(bResult, true);
|
||||
|
||||
// Load SocketCAN
|
||||
sdv::TInterfaceAccessPtr ptrCanComObj = sdv::core::GetObject("CAN_Communication_Object");
|
||||
EXPECT_NE(&ptrCanComObj, nullptr);
|
||||
|
||||
sdv::can::IRegisterReceiver* pCanRegRcvr = ptrCanComObj.GetInterface<sdv::can::IRegisterReceiver>();
|
||||
EXPECT_NE(&pCanRegRcvr, nullptr);
|
||||
|
||||
MockCANReceiver mockRcv;
|
||||
ASSERT_NO_THROW(pCanRegRcvr->RegisterReceiver(&mockRcv));
|
||||
|
||||
ASSERT_NO_THROW(appControl.SetRunningMode());
|
||||
|
||||
// Send messages from vcan3 using candump
|
||||
CComTestHelper testHelper;
|
||||
uint32_t msgId = 777;
|
||||
uint32_t dataSize = 1;
|
||||
uint32_t msgToBeSend = 5;
|
||||
|
||||
while (dataSize <= msgToBeSend)
|
||||
{
|
||||
auto testData = testHelper.CreateTestData(msgId, dataSize);
|
||||
std::stringstream cansendCommand;
|
||||
cansendCommand << "cansend vcan3 " << std::hex << std::uppercase << std::setw(3) << std::setfill('0') << testData.uiID << "#";
|
||||
for (auto byte : testData.seqData)
|
||||
{
|
||||
cansendCommand << std::setw(2) << std::setfill('0') << std::hex << (int)byte;
|
||||
}
|
||||
system(cansendCommand.str().c_str());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
msgId++;
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
if (dataSize == msgToBeSend)
|
||||
{
|
||||
system("pkill cansend");
|
||||
}
|
||||
|
||||
// Wait for messages to be received
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
auto receivedMessages = mockRcv.GetReceivedMessages();
|
||||
|
||||
dataSize = 1;
|
||||
msgId = 777;
|
||||
for (const auto& receivedMessage : receivedMessages)
|
||||
{
|
||||
auto expectedData = testHelper.CreateTestData(msgId, dataSize);
|
||||
EXPECT_EQ(receivedMessage.second.uiID, expectedData.uiID) << "Mismatch in message ID for data size " << dataSize;
|
||||
EXPECT_EQ(receivedMessage.second.seqData, expectedData.seqData) << "Mismatch in message data for ID " << msgId;
|
||||
msgId++;
|
||||
dataSize++;
|
||||
}
|
||||
|
||||
ASSERT_NO_THROW(pCanRegRcvr->UnregisterReceiver(&mockRcv));
|
||||
ASSERT_NO_THROW(appControl.Shutdown());
|
||||
}
|
||||
|
||||
// Manual / Visual 'Send' & 'Received' test
|
||||
// Configuration ["vcan0", "vcan3", "vcan8", "vcan1", "vcan8", "vcan4", "vcan2"])"
|
||||
// Index 0 = vcan0
|
||||
// Index 1 = vcan3
|
||||
// Index 2 = vcan8 // should not exist, expect to be invalid
|
||||
// Index 3 = vcan1
|
||||
// Index 4 = vcan9 // should not exist, expect to be invalid
|
||||
// Index 5 = vcan4
|
||||
// Index 6 = vcan2
|
||||
// Required: vcan0, vcan1, vcan2, vcan3, vcan4
|
||||
// sudo ip link add dev vcan0 type vcan
|
||||
// sudo ip link set up vcan0
|
||||
// Show all can interfaces: ip addr | grep "vcan"
|
||||
//
|
||||
// Verifiy Send:
|
||||
// On 5 terminals execute command with the correct interface to visualize the sended messages
|
||||
// candump vcan0
|
||||
// Expected: name of interface, MessageId represends interface
|
||||
// vcan1 001 [x] 02 04 06 08 0A 0C 0E 10
|
||||
//
|
||||
// Verifiy Receive:
|
||||
// On another terminal execute
|
||||
// cansend vcan4 100#DEADBEEF
|
||||
// Expected: name of interface, MessageId is +1 than the interface
|
||||
// Got Message from: vcan4, MsgID: 256 '222' '173' '190' '239'
|
||||
TEST_F(CANSocketTest, ManualSendAndReceiveTestOfMulitpleSockets)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
uint32_t vcan0Index = 0; // must fit to the configuration string
|
||||
uint32_t vcan1Index = 3;
|
||||
uint32_t vcan2Index = 6;
|
||||
uint32_t vcan3Index = 1;
|
||||
uint32_t vcan4Index = 5;
|
||||
sdv::u8string ssConfig = R"(canSockets = ["vcan0", "vcan3", "vcan8", "vcan1", "vcan9", "vcan4", "vcan2"])";
|
||||
CTestCANSocket canComObj;
|
||||
ASSERT_NO_THROW(canComObj.Initialize(ssConfig.c_str()));
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
|
||||
// Register a receiver.
|
||||
MockCANReceiver mockRcv;
|
||||
ASSERT_NO_THROW(canComObj.SetOperationMode(sdv::EOperationMode::configuring));
|
||||
ASSERT_NO_THROW(canComObj.RegisterReceiver(&mockRcv));
|
||||
EXPECT_NO_THROW(canComObj.SetOperationMode(sdv::EOperationMode::running));
|
||||
|
||||
CComTestHelper testHelper;
|
||||
sdv::sequence<sdv::u8string> expectedInterfaces{"vcan0", "vcan3", "vcan1", "vcan4", "vcan2"};
|
||||
EXPECT_TRUE(testHelper.ValidateInterfaces(expectedInterfaces, canComObj.GetInterfaces()));
|
||||
|
||||
uint32_t msgId = 0;
|
||||
uint32_t dataSize = 8;
|
||||
auto testData0 = testHelper.CreateTestData(msgId + 0, dataSize); // Testdata for vcan0
|
||||
auto testData1 = testHelper.CreateTestData(msgId + 1, dataSize); // Testdata for vcan1
|
||||
auto testData2 = testHelper.CreateTestData(msgId + 2, dataSize); // Testdata for vcan2
|
||||
auto testData3 = testHelper.CreateTestData(msgId + 3, dataSize); // Testdata for vcan3
|
||||
auto testData4 = testHelper.CreateTestData(msgId + 4, dataSize); // Testdata for vcan4
|
||||
EXPECT_NO_THROW(canComObj.Send(testData0, vcan0Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData1, vcan1Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData2, vcan2Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData3, vcan3Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData4, vcan4Index));
|
||||
|
||||
// Wait for messages to be received
|
||||
uint32_t waitForMessagesLoop = 1;
|
||||
while (waitForMessagesLoop > 0)
|
||||
{
|
||||
waitForMessagesLoop--;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
auto receivedMessages = mockRcv.GetReceivedMessages();
|
||||
for(auto receivedMessage : receivedMessages)
|
||||
{
|
||||
std::cout << "Got Message from: " << receivedMessage.first << ", MsgID: " << std::to_string(receivedMessage.second.uiID) ;
|
||||
for (uint8_t i = 0; i < receivedMessage.second.seqData.size(); ++i)
|
||||
{
|
||||
std::cout << " '" << std::to_string(receivedMessage.second.seqData[i]) << "'";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(canComObj.UnregisterReceiver(&mockRcv));
|
||||
ASSERT_NO_THROW(canComObj.Shutdown()); // Shutdown the object after the test
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::destruction_pending);
|
||||
}
|
||||
|
||||
// Test similar to ManualSendAndReceiveTestOfMulitpleSockets
|
||||
// but with different messages size
|
||||
// Result:
|
||||
// vcan0 000 [x] 00 02 04 06
|
||||
// vcan1 001 [x] 01 03 05 07 09
|
||||
// vcan2 002 [x] 02 04 06 08 0A 0C
|
||||
// vcan3 003 [x] 03 05 07 09 0B 0D 0F
|
||||
// vcan4 no message
|
||||
TEST_F(CANSocketTest, ManualSendAndReceiveTestWithDifferentDataSizes)
|
||||
{
|
||||
sdv::app::CAppControl appControl;
|
||||
appControl.Startup("");
|
||||
|
||||
uint32_t vcan0Index = 0; // must fit to the configuration string
|
||||
uint32_t vcan1Index = 3;
|
||||
uint32_t vcan2Index = 6;
|
||||
uint32_t vcan3Index = 1;
|
||||
uint32_t vcan4Index = 5;
|
||||
sdv::u8string ssConfig = R"(canSockets = ["vcan0", "vcan3", "vcan8", "vcan1", "vcan9", "vcan4", "vcan2"])";
|
||||
CTestCANSocket canComObj;
|
||||
ASSERT_NO_THROW(canComObj.Initialize(ssConfig.c_str()));
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::initialized);
|
||||
|
||||
// Register a receiver.
|
||||
MockCANReceiver mockRcv;
|
||||
ASSERT_NO_THROW(canComObj.SetOperationMode(sdv::EOperationMode::configuring));
|
||||
ASSERT_NO_THROW(canComObj.RegisterReceiver(&mockRcv));
|
||||
EXPECT_NO_THROW(canComObj.SetOperationMode(sdv::EOperationMode::running));
|
||||
|
||||
CComTestHelper testHelper;
|
||||
sdv::sequence<sdv::u8string> expectedInterfaces{"vcan0", "vcan3", "vcan1", "vcan4", "vcan2"};
|
||||
EXPECT_TRUE(testHelper.ValidateInterfaces(expectedInterfaces, canComObj.GetInterfaces()));
|
||||
|
||||
uint32_t msgId = 0;
|
||||
uint32_t dataSize = 8;
|
||||
auto testData0 = testHelper.CreateTestData(msgId + 0, dataSize -4); // Testdata for vcan0
|
||||
auto testData1 = testHelper.CreateTestData(msgId + 1, dataSize -3); // Testdata for vcan1
|
||||
auto testData2 = testHelper.CreateTestData(msgId + 2, dataSize -2); // Testdata for vcan2
|
||||
auto testData3 = testHelper.CreateTestData(msgId + 3, dataSize -1); // Testdata for vcan3
|
||||
auto testData4 = testHelper.CreateTestData(msgId + 4, dataSize +1); // Testdata for vcan4, is to large
|
||||
EXPECT_NO_THROW(canComObj.Send(testData0, vcan0Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData1, vcan1Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData2, vcan2Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData3, vcan3Index));
|
||||
EXPECT_NO_THROW(canComObj.Send(testData4, vcan4Index));
|
||||
|
||||
// Wait for messages to be received
|
||||
uint32_t waitForMessagesLoop = 1;
|
||||
while (waitForMessagesLoop > 0)
|
||||
{
|
||||
waitForMessagesLoop--;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
auto receivedMessages = mockRcv.GetReceivedMessages();
|
||||
for(auto receivedMessage : receivedMessages)
|
||||
{
|
||||
std::cout << "Got Message from: " << receivedMessage.first << ", MsgID: " << std::to_string(receivedMessage.second.uiID) ;
|
||||
for (uint8_t i = 0; i < receivedMessage.second.seqData.size(); ++i)
|
||||
{
|
||||
std::cout << " '" << std::to_string(receivedMessage.second.seqData[i]) << "'";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(canComObj.UnregisterReceiver(&mockRcv));
|
||||
ASSERT_NO_THROW(canComObj.Shutdown()); // Shutdown the object after the test
|
||||
EXPECT_EQ(canComObj.GetStatus(), sdv::EObjectStatus::destruction_pending);
|
||||
}
|
||||
|
||||
extern "C" int main(int argc, char* argv[])
|
||||
{
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int result = RUN_ALL_TESTS();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
Reference in New Issue
Block a user