Precommit (#1)

* first commit

* cleanup
This commit is contained in:
tompzf
2025-11-04 13:28:06 +01:00
committed by GitHub
parent dba45dc636
commit 6ed4b1534e
898 changed files with 256340 additions and 0 deletions

84
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,84 @@
# Define project
project(Tests VERSION 1.0 LANGUAGES CXX)
# Enable testing for all subsequent projects
enable_testing()
# Re-set target directories
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $<1:${CMAKE_BINARY_DIR}/tests/lib>)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $<1:${CMAKE_BINARY_DIR}/tests/bin>)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_BINARY_DIR}/tests/bin>)
# Include export into the include directory path
include_directories(../export)
# Get Google Test from github
include(FetchContent)
# Fetch the Google Test library from GitHub.
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.17.0
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # For Windows: Prevent overriding the parent project's compiler/linker settings
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()
FetchContent_MakeAvailable(googletest)
add_library(GTest::GTest INTERFACE IMPORTED)
add_library(GMock::GMock INTERFACE IMPORTED)
target_link_libraries(GTest::GTest INTERFACE gtest_main)
target_link_libraries(GMock::GMock INTERFACE gmock_main)
file (COPY ${PROJECT_SOURCE_DIR}/sdv_core_reloc.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/)
file (COPY ${PROJECT_SOURCE_DIR}/sdv_core_reloc.toml DESTINATION ${CMAKE_BINARY_DIR}/examples/bin/)
file (COPY ${PROJECT_SOURCE_DIR}/sdv_core_reloc.toml DESTINATION ${CMAKE_BINARY_DIR}/framework_tests/bin/)
# Copy shell script to the build directory
if(WIN32)
file (COPY ${PROJECT_SOURCE_DIR}/run_tests_on_windows.ps1 DESTINATION ${CMAKE_BINARY_DIR}/tests/)
else()
file (COPY ${PROJECT_SOURCE_DIR}/run_tests_on_linux.sh DESTINATION ${CMAKE_BINARY_DIR}/tests/)
endif()
# Add test projects
add_subdirectory(unit_tests/concurrency)
add_subdirectory(unit_tests/flags_type)
add_subdirectory(unit_tests/scheduler)
add_subdirectory(unit_tests/idl_compiler)
add_subdirectory(unit_tests/commandline_parser)
add_subdirectory(unit_tests/dbc_parser)
add_subdirectory(unit_tests/asc_format)
add_subdirectory(unit_tests/basic_types)
add_subdirectory(unit_tests/smart_ifc)
add_subdirectory(unit_tests/toml_parser)
add_subdirectory(unit_tests/module_control)
add_subdirectory(unit_tests/repository)
# add_subdirectory(unit_tests/shared_mem)
add_subdirectory(unit_tests/memory_manager)
add_subdirectory(unit_tests/core_loader)
add_subdirectory(unit_tests/named_mutex)
add_subdirectory(unit_tests/trace_fifo)
add_subdirectory(unit_tests/socket_can_com_tests)
add_subdirectory(unit_tests/app_connect)
add_subdirectory(unit_tests/process_control)
add_subdirectory(unit_tests/ipc_com)
add_subdirectory(unit_tests/ipc_connect)
add_subdirectory(unit_tests/sdv_control)
add_subdirectory(unit_tests/sdv_macro_test)
add_subdirectory(unit_tests/install_package_composer)
add_subdirectory(unit_tests/path_match)
add_subdirectory(component_tests/logger)
add_subdirectory(component_tests/data_dispatch_service)
add_subdirectory(component_tests/repository)
add_subdirectory(component_tests/config_install)
add_subdirectory(component_tests/dbc_util)
add_subdirectory(component_tests/vss_util)
add_subdirectory(component_tests/task_timer)
add_subdirectory(component_tests/core_library)
add_subdirectory(component_tests/config)
add_subdirectory(manual_tests/silkit_can_com_tests)

91
tests/README.md Normal file
View File

@@ -0,0 +1,91 @@
# Running tests
When the project is build the tests are executed with warning level.
To run the test without warning level aou have to execute the test locally by executing the script files:
**On Windows PowerShell:** run_tests_on_windows.ps1
or
**On Linux:** run_tests_on_linux.sh
# SDV TEST MACRO
## Overview
There is set of macros in "export/support/sdv_test_macro.h" which are designed to extend the Google Test (GTEST) framework by incorporating a warning level mechanism. These macros allow developers to specify a warning level for each test assertion, providing more control over test outcomes and enabling better handling of test result conditions based on their warning level.
## Purpose
The primary purpose of these macros is to enhance the flexibility and robustness of test assertions in the GTEST framework. By integrating a warning level, developers can decide whether to report failed tests as warning or error and handle them accordingly. This is particularly useful in where different test failures may have varying impacts on the overall build system.
## Macros
### Equality Assertions:
These macros check for equality or inequality between two values. The level parameter specifies the warning level to be handled by the HANDLE_WARNING_LEVEL function.
- SDV_EXPECT_EQ(val1, val2, level)
- SDV_ASSERT_EQ(val1, val2, level)
- SDV_EXPECT_NE(val1, val2, level)
- SDV_ASSERT_NE(val1, val2, level)
### Boolean Assertions:
These macros check if a condition is true or false. The level parameter specifies the warning level to be handled by the HANDLE_WARNING_LEVEL function.
- SDV_EXPECT_TRUE(condition, level)
- SDV_ASSERT_TRUE(condition, level)
- SDV_EXPECT_FALSE(condition, level)
- SDV_ASSERT_FALSE(condition, level)
### Relational Assertions:
These macros check for relational conditions (less than, less than or equal to, greater than, greater than or equal to) between two values. The level parameter specifies the warning level to be handled by the HANDLE_WARNING_LEVEL function.
- SDV_EXPECT_LT(val1, val2, level)
- SDV_ASSERT_LT(val1, val2, level)
- SDV_EXPECT_LE(val1, val2, level)
- SDV_ASSERT_LE(val1, val2, level)
- SDV_EXPECT_GT(val1, val2, level)
- SDV_ASSERT_GT(val1, val2, level)
- SDV_EXPECT_GE(val1, val2, level)
- SDV_ASSERT_GE(val1, val2, level)
### String Assertions:
These macros check for string equality or inequality, both case-sensitive and case-insensitive. The level parameter specifies the warning level to be handled by the HANDLE_WARNING_LEVEL function.
- SDV_EXPECT_STREQ(str1, str2, level)
- SDV_ASSERT_STREQ(str1, str2, level)
- SDV_EXPECT_STRNE(str1, str2, level)
- SDV_ASSERT_STRNE(str1, str2, level)
- SDV_EXPECT_STRCASEEQ(str1, str2, level)
- SDV_ASSERT_STRCASEEQ(str1, str2, level)
- SDV_EXPECT_STRCASENE(str1, str2, level)
- SDV_ASSERT_STRCASENE(str1, str2, level)
## Warning Levels
The WarningLevel enum defines three levels of warnings:
- WARNING_ENABLED: With this warning level, failed tests are reported as errors, as is standard in GTEST.
- WARNING_REDUCED: With warning this level, failed tests are reported as warnings.
- WARNING_DISABLED: With this warning level, no action is implemented at this moment.
Additionally SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD is implemented to check if tests are running with CMake build or any other way. It returns true if they are running with CMake build.
## Usage
To use these macros, include the header file '#include <support/sdv_test_macro.h>" in your test files. When writing test cases, use the SDV macros instead of the standard GTEST macros, and specify the appropriate warning level for each assertion.
```cpp
#include <support/sdv_test_macro.h>
TEST(SDVTestMacros, TestExpectEq)
{
int val1 = 5;
int val2 = 5;
if (SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_EXPECT_EQ(val1, val2, sdv::TEST::WARNING_REDUCED);
else
SDV_EXPECT_EQ(val1, val2, sdv::TEST::WARNING_ENABLED);
}
TEST(SDVTestMacros, TestExpectStreq)
{
std::string str1 = "test";
std::string str2 = "test";
if (SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_EXPECT_STREQ(str1, str2, sdv::TEST::WARNING_REDUCED);
else
SDV_EXPECT_STREQ(str1, str2, sdv::TEST::WARNING_ENABLED);
}
```
In this example, the SDV_EXPECT_EQ macro checks if val1 and val2 are equal, while the SDV_EXPECT_STREQ macro checks if str1 and str2 are equal. In both test cases, it is checked whether it is running
with the Cmake build. If it is running with the CMake build then report test failures as warning, otherwise report normally as GTEST does.

View File

@@ -0,0 +1,19 @@
# Define project
project(ConfigTests VERSION 1.0 LANGUAGES CXX)
# Define target
add_executable(ComponentTest_Config config_tests.cpp)
target_link_libraries(ComponentTest_Config ${CMAKE_DL_LIBS} GTest::GTest)
# Add the test
add_test(NAME ComponentTest_Config COMMAND ComponentTest_Config WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
add_custom_command(TARGET ComponentTest_Config POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_Config>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_Config.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_Config dependency_sdv_components)

View File

@@ -0,0 +1,960 @@
#include <gtest/gtest.h>
#include <support/toml.h>
#include <support/sdv_core.h>
#include <support/app_control.h>
#include "../../../global/process_watchdog.h"
#ifdef _MSC_VER
#pragma warning(disable : 4566)
#endif
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
TEST(Config, Instantiate)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config;
EXPECT_TRUE(config.Process(""));
config.Clear();
appcontrol.Shutdown();
}
TEST(RecognizeTypes, Table)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
[newTable]
[secondTable.nestedTable]
)");
EXPECT_TRUE(config.IsValid());
auto table1 = config.GetDirect("newTable");
EXPECT_TRUE(table1);
EXPECT_EQ(table1.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_EQ(table1.GetName(), "newTable");
EXPECT_EQ(table1.GetValue(), sdv::any_t());
sdv::toml::CNodeCollection collection = table1;
EXPECT_TRUE(collection);
sdv::toml::CNodeCollection table2 = config.GetDirect("secondTable");
EXPECT_TRUE(table2);
EXPECT_EQ(table2.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_EQ(table2.GetName(), "secondTable");
EXPECT_EQ(table2.GetValue(), sdv::any_t());
sdv::toml::CNodeCollection table3 = config.GetDirect("secondTable.nestedTable");
EXPECT_TRUE(table3);
EXPECT_EQ(table3.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_EQ(table3.GetName(), "nestedTable");
EXPECT_EQ(table3.GetValue(), sdv::any_t());
config.Clear();
appcontrol.Shutdown();
}
TEST(RecognizeTypes, Key_Value)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
name = "Hammer"
id = 42
pi = 3.1415926
boolean = true
array = []
table = {}
)");
auto value_name = config.GetDirect("name");
EXPECT_EQ(value_name.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(value_name.GetValue(), sdv::any_t("Hammer"));
auto value_id = config.GetDirect("id");
EXPECT_EQ(value_id.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(value_id.GetValue(), 42);
auto value_pi = config.GetDirect("pi");
EXPECT_EQ(value_pi.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(value_pi.GetValue(), 3.1415926);
auto value_boolean = config.GetDirect("boolean");
EXPECT_EQ(value_boolean.GetType(), sdv::toml::ENodeType::node_boolean);
EXPECT_EQ(value_boolean.GetValue(), true);
auto value_array = config.GetDirect("array");
EXPECT_EQ(value_array.GetType(), sdv::toml::ENodeType::node_array);
EXPECT_EQ(value_array.GetValue(), sdv::any_t());
auto value_table = config.GetDirect("table");
EXPECT_EQ(value_table.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_EQ(value_table.GetValue(), sdv::any_t());
config.Clear();
appcontrol.Shutdown();
}
TEST(RecognizeTypes, TableArray)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
[[newTableArray]]
[[newTableArray]]
[[table.nestedTableArray]]
)");
sdv::toml::CNodeCollection tableArray1 = config.GetDirect("newTableArray");
EXPECT_EQ(tableArray1.GetType(), sdv::toml::ENodeType::node_array);
EXPECT_TRUE(tableArray1);
EXPECT_EQ(tableArray1.GetName(), "newTableArray");
EXPECT_EQ(tableArray1.GetCount(), 2u);
auto tableNode0 = tableArray1[0];
EXPECT_TRUE(tableNode0);
auto tableNode0b = tableArray1.Get(0);
EXPECT_TRUE(tableNode0b);
auto tableNode1 = tableArray1[1];
EXPECT_TRUE(tableNode1);
auto tableNode1b = tableArray1.Get(1);
EXPECT_TRUE(tableNode1b);
EXPECT_FALSE(tableArray1[2]);
EXPECT_FALSE(tableArray1.Get(2));
auto table1 = config.GetDirect("newTableArray[0]");
EXPECT_EQ(table1.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_TRUE(table1.GetName().empty());
auto table2 = config.GetDirect("newTableArray[1]");
EXPECT_EQ(table2.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_TRUE(table2.GetName().empty());
config.Clear();
appcontrol.Shutdown();
}
TEST(NestedContent, Array)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
arr_mixed = [ 1.0, 2, "test string", [ 1, 2, ], { pi = 3.14, e = 2.71828 }, true]
arr_ints = [ 1, 2, 3, 4]
arr_ints_trailing_comma = [ 1, 2, 3, 4, ]
arr_multiline = [
"first line",
"second line",
"third_line",
]
)");
{
sdv::toml::CNodeCollection array_ints = config.GetDirect("arr_ints");
EXPECT_EQ(array_ints.GetType(), sdv::toml::ENodeType::node_array);
ASSERT_TRUE(array_ints);
EXPECT_EQ(array_ints.GetCount(), 4u);
EXPECT_TRUE(array_ints[0]);
EXPECT_TRUE(array_ints[1]);
EXPECT_TRUE(array_ints[2]);
EXPECT_TRUE(array_ints[3]);
EXPECT_FALSE(array_ints[4]);
auto array_ints_0 = config.GetDirect("arr_ints[0]");
ASSERT_TRUE(array_ints_0);
EXPECT_EQ(array_ints_0.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_0.GetValue(), 1);
auto array_ints_1 = config.GetDirect("arr_ints[1]");
ASSERT_TRUE(array_ints_1);
EXPECT_EQ(array_ints_1.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_1.GetValue(), 2);
auto array_ints_2 = config.GetDirect("arr_ints[2]");
ASSERT_TRUE(array_ints_2);
EXPECT_EQ(array_ints_2.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_2.GetValue(), 3);
auto array_ints_3 = config.GetDirect("arr_ints[3]");
ASSERT_TRUE(array_ints_3);
EXPECT_EQ(array_ints_3.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_3.GetValue(), 4);
auto array_ints_4 = config.GetDirect("arr_ints[4]");
EXPECT_FALSE(array_ints_4);
}
{
auto array_ints_trailing_comma = config.GetDirect("arr_ints_trailing_comma");
auto array_ints_trailing_comma_0 = config.GetDirect("arr_ints_trailing_comma[0]");
auto array_ints_trailing_comma_1 = config.GetDirect("arr_ints_trailing_comma[1]");
auto array_ints_trailing_comma_2 = config.GetDirect("arr_ints_trailing_comma[2]");
auto array_ints_trailing_comma_3 = config.GetDirect("arr_ints_trailing_comma[3]");
auto array_ints_trailing_comma_4 = config.GetDirect("arr_ints_trailing_comma[4]");
EXPECT_EQ(array_ints_trailing_comma.GetType(), sdv::toml::ENodeType::node_array);
ASSERT_TRUE(array_ints_trailing_comma_0);
EXPECT_EQ(array_ints_trailing_comma_0.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_trailing_comma_0.GetValue(), 1);
ASSERT_TRUE(array_ints_trailing_comma_1);
EXPECT_EQ(array_ints_trailing_comma_1.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_trailing_comma_1.GetValue(), 2);
ASSERT_TRUE(array_ints_trailing_comma_2);
EXPECT_EQ(array_ints_trailing_comma_2.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_trailing_comma_2.GetValue(), 3);
ASSERT_TRUE(array_ints_trailing_comma_3);
EXPECT_EQ(array_ints_trailing_comma_3.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_ints_trailing_comma_3.GetValue(), 4);
EXPECT_FALSE(array_ints_trailing_comma_4);
}
{
auto array_mixed = config.GetDirect("arr_mixed");
auto array_mixed_0 = config.GetDirect("arr_mixed[0]");
auto array_mixed_1 = config.GetDirect("arr_mixed[1]");
auto array_mixed_2 = config.GetDirect("arr_mixed[2]");
auto array_mixed_3 = config.GetDirect("arr_mixed[3]");
auto array_mixed_3_2 = config.GetDirect("arr_mixed[3][1]");
auto array_mixed_4 = config.GetDirect("arr_mixed[4]");
auto array_mixed_4_pi = config.GetDirect("arr_mixed[4].pi");
auto array_mixed_5 = config.GetDirect("arr_mixed[5]");
auto array_mixed_6 = config.GetDirect("arr_mixed[6]");
EXPECT_EQ(array_mixed.GetType(), sdv::toml::ENodeType::node_array);
ASSERT_TRUE(array_mixed_0);
EXPECT_EQ(array_mixed_0.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(array_mixed_0.GetValue(), 1.0);
ASSERT_TRUE(array_mixed_1);
EXPECT_EQ(array_mixed_1.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_mixed_1.GetValue(), 2);
ASSERT_TRUE(array_mixed_2);
EXPECT_EQ(array_mixed_2.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(array_mixed_2.GetValue()), "test string");
ASSERT_TRUE(array_mixed_3);
EXPECT_EQ(array_mixed_3.GetType(), sdv::toml::ENodeType::node_array);
EXPECT_EQ(array_mixed_3_2.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(array_mixed_3_2.GetValue(), 2);
ASSERT_TRUE(array_mixed_4);
EXPECT_EQ(array_mixed_4.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_EQ(array_mixed_4_pi.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(array_mixed_4_pi.GetValue(), 3.14);
ASSERT_TRUE(array_mixed_5);
EXPECT_EQ(array_mixed_5.GetType(), sdv::toml::ENodeType::node_boolean);
EXPECT_EQ(array_mixed_5.GetValue(), true);
EXPECT_EQ(array_mixed_5.GetValue(), sdv::any_t());
EXPECT_FALSE(array_mixed_6);
}
{
auto array_multiline = config.GetDirect("arr_multiline");
auto array_multiline_0 = config.GetDirect("arr_multiline[0]");
auto array_multiline_1 = config.GetDirect("arr_multiline[1]");
auto array_multiline_2 = config.GetDirect("arr_multiline[2]");
auto array_multiline_3 = config.GetDirect("arr_multiline[3]");
EXPECT_EQ(array_multiline.GetType(), sdv::toml::ENodeType::node_array);
ASSERT_TRUE(array_multiline_0);
EXPECT_EQ(array_multiline_0.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(array_multiline_0.GetValue()), "first line");
ASSERT_TRUE(array_multiline_1);
EXPECT_EQ(array_multiline_1.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(array_multiline_1.GetValue()), "second line");
ASSERT_TRUE(array_multiline_2);
EXPECT_EQ(array_multiline_2.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(array_multiline_2.GetValue()), "third_line");
EXPECT_FALSE(array_multiline_3);
}
config.Clear();
appcontrol.Shutdown();
}
TEST(NestedContent, Table)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
[table]
a = 2
b = 1.2
[anotherTable]
a = 4
c = false
[thirdTable.fourthTable]
a = "five"
d = []
)");
auto table_a = config.GetDirect("table.a");
auto table_b = config.GetDirect("table.b");
auto anotherTable_a = config.GetDirect("anotherTable.a");
auto anotherTable_c = config.GetDirect("anotherTable.c");
auto fourthTable_a = config.GetDirect("thirdTable.fourthTable.a");
auto fourthTable_d = config.GetDirect("thirdTable.fourthTable.d");
ASSERT_TRUE(table_a);
EXPECT_EQ(table_a.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(table_a.GetValue(), 2);
ASSERT_TRUE(table_b);
EXPECT_EQ(table_b.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(table_b.GetValue(), 1.2);
ASSERT_TRUE(anotherTable_a);
EXPECT_EQ(anotherTable_a.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(anotherTable_a.GetValue(), 4);
ASSERT_TRUE(anotherTable_c);
EXPECT_EQ(anotherTable_c.GetType(), sdv::toml::ENodeType::node_boolean);
EXPECT_EQ(anotherTable_c.GetValue(), false);
ASSERT_TRUE(fourthTable_a);
EXPECT_EQ(fourthTable_a.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(fourthTable_a.GetValue()), "five");
ASSERT_TRUE(fourthTable_d);
EXPECT_EQ(fourthTable_d.GetType(), sdv::toml::ENodeType::node_array);
config.Clear();
appcontrol.Shutdown();
}
TEST(NestedContent, TableArray)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
[[table.test]]
a = 2
b = 1.2
[[table.test]]
a = 4
c = false
[[table.test]]
a = "five"
d = []
)");
auto table_test_1_a = config.GetDirect("table.test[0].a");
auto table_test_1_b = config.GetDirect("table.test[0].b");
auto table_test_2_a = config.GetDirect("table.test[1].a");
auto table_test_2_c = config.GetDirect("table.test[1].c");
auto table_test_3_a = config.GetDirect("table.test[2].a");
auto table_test_3_d = config.GetDirect("table.test[2].d");
ASSERT_TRUE(table_test_1_a);
EXPECT_EQ(table_test_1_a.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(table_test_1_a.GetValue(), 2);
ASSERT_TRUE(table_test_1_b);
EXPECT_EQ(table_test_1_b.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(table_test_1_b.GetValue(), 1.2);
ASSERT_TRUE(table_test_2_a);
EXPECT_EQ(table_test_2_a.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(table_test_2_a.GetValue(), 4);
ASSERT_TRUE(table_test_2_c);
EXPECT_EQ(table_test_2_c.GetType(), sdv::toml::ENodeType::node_boolean);
EXPECT_EQ(table_test_2_c.GetValue(), false);
ASSERT_TRUE(table_test_3_a);
EXPECT_EQ(table_test_3_a.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table_test_3_a.GetValue()), "five");
ASSERT_TRUE(table_test_3_d);
EXPECT_EQ(table_test_3_d.GetType(), sdv::toml::ENodeType::node_array);
config.Clear();
appcontrol.Shutdown();
}
TEST(NestedContent, InlineTable)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
table1 = { a = 0, b = 1.2, c = "string" }
table2 = { a = [], b = true, e = 2.71828 }
table3 = { a = { a = "a", b = "A" }, b = {a = "b", b = "B"}, e = {a = "e", b = "E"} }
)");
auto table1_a = config.GetDirect("table1.a");
auto table1_b = config.GetDirect("table1.b");
auto table1_c = config.GetDirect("table1.c");
auto table2_a = config.GetDirect("table2.a");
auto table2_b = config.GetDirect("table2.b");
auto table2_e = config.GetDirect("table2.e");
auto table3_a_a = config.GetDirect("table3.a.a");
auto table3_a_b = config.GetDirect("table3.a.b");
auto table3_b_a = config.GetDirect("table3.b.a");
auto table3_b_b = config.GetDirect("table3.b.b");
auto table3_e_a = config.GetDirect("table3.e.a");
auto table3_e_b = config.GetDirect("table3.e.b");
ASSERT_TRUE(table1_a);
EXPECT_EQ(table1_a.GetType(), sdv::toml::ENodeType::node_integer);
EXPECT_EQ(table1_a.GetValue(), 0);
ASSERT_TRUE(table1_b);
EXPECT_EQ(table1_b.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(table1_b.GetValue(), 1.2);
ASSERT_TRUE(table1_c);
EXPECT_EQ(table1_c.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table1_c.GetValue()), "string");
ASSERT_TRUE(table2_a);
EXPECT_EQ(table2_a.GetType(), sdv::toml::ENodeType::node_array);
ASSERT_TRUE(table2_b);
EXPECT_EQ(table2_b.GetType(), sdv::toml::ENodeType::node_boolean);
EXPECT_EQ(table2_b.GetValue(), true);
ASSERT_TRUE(table2_e);
EXPECT_EQ(table2_e.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(table2_e.GetValue(), 2.71828);
ASSERT_TRUE(table3_a_a);
EXPECT_EQ(table3_a_a.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table3_a_a.GetValue()), "a");
ASSERT_TRUE(table3_a_b);
EXPECT_EQ(table3_a_b.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table3_a_b.GetValue()), "A");
ASSERT_TRUE(table3_b_a);
EXPECT_EQ(table3_b_a.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table3_b_a.GetValue()), "b");
ASSERT_TRUE(table3_b_b);
EXPECT_EQ(table3_b_b.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table3_b_b.GetValue()), "B");
ASSERT_TRUE(table3_e_a);
EXPECT_EQ(table3_e_a.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table3_e_a.GetValue()), "e");
ASSERT_TRUE(table3_e_b);
EXPECT_EQ(table3_e_b.GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(static_cast<std::string>(table3_e_b.GetValue()), "E");
config.Clear();
appcontrol.Shutdown();
}
TEST(SpecialCases, Keys)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_TRUE(sdv::toml::CTOMLParser(u8R"(
"127.0.0.1" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"
'key2' = "value"
'quoted "value"' = "value"
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
key = "value"
bare_key = "value"
bare-key = "value"
1234 = "value"
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
"" = "blank" # VALID but discouraged
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
'' = 'blank' # VALID but discouraged
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
name = "Orange"
physical.color = "orange"
physical.shape = "round"
site."google.com" = true
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
fruit.name = "banana" # this is best practice
fruit. color = "yellow" # same as fruit.color
fruit . flavor = "banana" # same as fruit.flavor
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
# This makes the key "fruit" into a table.
fruit.apple.smooth = true
# So then you can add to the table "fruit" like so:
fruit.orange = 2
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
# VALID BUT DISCOURAGED
apple.type = "fruit"
orange.type = "fruit"
apple.skin = "thin"
orange.skin = "thick"
apple.color = "red"
orange.color = "orange"
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
3.1415 = 3.1415
)"));
{
sdv::toml::CTOMLParser config(R"(
3.1415 = 3.1415
)");
auto table = config.GetDirect("3");
auto pi = config.GetDirect("3.1415");
ASSERT_TRUE(table);
EXPECT_EQ(table.GetType(), sdv::toml::ENodeType::node_table);
ASSERT_TRUE(pi);
EXPECT_EQ(pi.GetType(), sdv::toml::ENodeType::node_floating_point);
EXPECT_EQ(pi.GetValue(), 3.1415);
}
appcontrol.Shutdown();
}
TEST(SpecialCases, Arrays)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested_arrays_of_ints = [ [ 1, 2 ], [3, 4, 5] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "all", 'strings', """are the same""", '''type''' ]
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
"Foo Bar <foo@example.com>",
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
integers3 = [
1,
2, # this is ok
]
)"));
appcontrol.Shutdown();
}
TEST(SpecialCases, Tables)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
[table-1]
key1 = "some string"
key2 = 123
[table-2]
key1 = "another string"
key2 = 456
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
[dog."tater.man"]
type.name = "pug"
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(u8R"(
[a.b.c] # this is best practice
[ d.e.f ] # same as [d.e.f]
[ g . h . i ] # same as [g.h.i]
[ j . "ʞ" . 'l' ] # same as [j."ʞ".'l']
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
# [x] you
# [x.y] don't
# [x.y.z] need these
[x.y.z.w] # for this to work
[x] # defining a super-table afterward is ok
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
# VALID BUT DISCOURAGED
[fruit.apple]
[animal]
[fruit.orange]
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
[fruit]
apple.color = "red"
apple.taste.sweet = true
[fruit.apple.texture] # you can add sub-tables
)"));
appcontrol.Shutdown();
}
TEST(SpecialCases, TableArrays)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
[[products]]
name = "Hammer"
sku = 738594937
[[products]] # empty table within the array
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
[[fruits]]
name = "apple"
[fruits.physical] # subtable
color = "red"
shape = "round"
[[fruits.varieties]] # nested array of tables
name = "red delicious"
[[fruits.varieties]]
name = "granny smith"
[[fruits]]
name = "banana"
[[fruits.varieties]]
name = "plantain"
)"));
EXPECT_TRUE(sdv::toml::CTOMLParser(R"(
points = [ { x = 1, y = 2, z = 3 },
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]
)"));
appcontrol.Shutdown();
}
TEST(ErrorCases, KeyValue)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(key = # node_invalid)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(first = "Tom" last = "Preston-Werner" # node_invalid)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(= "no key name" # node_invalid)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
name = "Tom"
name = "Pradyun"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
fruit . flavor = "banana" # same as fruit.flavor
fruit.flavor = "banana"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
spelling = "favorite"
"spelling" = "favourite"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
# This defines the value of fruit.apple to be an integer.
fruit.apple = 1
# But then this treats fruit.apple like it's a table.
# You can't turn an integer into a table.
fruit.apple.smooth = true
)"));
appcontrol.Shutdown();
}
TEST(ErrorCases, Tables)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_FALSE(sdv::toml::CTOMLParser(u8R"(
[ j . "ʞ" . 'l' ]
[j."ʞ".'l']
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[fruit]
apple = "red"
[fruit]
orange = "orange"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[fruit]
apple = "red"
[fruit.apple]
texture = "smooth"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[fruit]
apple.color = "red"
apple.taste.sweet = true
[fruit.apple] # INVALID
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[fruit]
apple.color = "red"
apple.taste.sweet = true
[fruit.apple.taste] # INVALID
)"));
appcontrol.Shutdown();
}
TEST(ErrorCases, InlineTables)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
type = { name = "Nail" }
type.edible = false # INVALID
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[product]
type.name = "Nail"
type = { edible = false } # INVALID
)"));
appcontrol.Shutdown();
}
TEST(ErrorCases, TableArrays)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[fruit.physical] # subtable, but to which parent element should it belong?
color = "red"
shape = "round"
[[fruit]] # parser must throw an error upon discovering that "fruit" is
# an array rather than a table
name = "apple"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
fruits = []
[[fruits]] # Not allowed
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[[fruits]]
name = "apple"
[[fruits.varieties]]
name = "red delicious"
# INVALID: This table conflicts with the previous array of tables
[fruits.varieties]
name = "granny smith"
)"));
EXPECT_FALSE(sdv::toml::CTOMLParser(R"(
[[fruits]]
name = "apple"
[fruits.physical]
color = "red"
shape = "round"
# INVALID: This array of tables conflicts with the previous table
[[fruits.physical]]
color = "green"
)"));
appcontrol.Shutdown();
}
TEST(Ordering, Array)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
)");
auto two = config.GetDirect("array[2]");
auto eleven = config.GetDirect("array[11]");
const sdv::toml::CNodeCollection arr = config.GetDirect("array");
// with direct access
ASSERT_TRUE(two);
EXPECT_EQ(two.GetValue(), 2);
ASSERT_TRUE(eleven);
EXPECT_EQ(eleven.GetValue(), 11);
// with indirect access through iterating
ASSERT_TRUE(arr);
for (std::size_t i = 0; i < arr.GetCount(); ++i)
{
EXPECT_EQ(arr[i].GetValue(), (int64_t)i);
}
config.Clear();
appcontrol.Shutdown();
}
TEST(Ordering, TableAray)
{
sdv::app::CAppControl appcontrol(R"config(
[Application]
Mode = "Essential"
[LogHandler]
ViewFilter = "Fatal"
)config");
ASSERT_TRUE(appcontrol.IsRunning());
sdv::toml::CTOMLParser config(R"(
[[tableArray]]
a = 0
[[tableArray]]
a = 1
[[tableArray]]
a = 2
[[tableArray]]
a = 3
[[tableArray]]
a = 4
[[tableArray]]
a = 5
[[tableArray]]
a = 6
[[tableArray]]
a = 7
[[tableArray]]
a = 8
[[tableArray]]
a = 9
[[tableArray]]
a = 10
[[tableArray]]
a = 11
)");
sdv::toml::CNodeCollection tableArray = config.GetDirect("tableArray");
ASSERT_TRUE(tableArray);
for (std::size_t i = 0; i < tableArray.GetCount(); ++i)
{
EXPECT_EQ(sdv::toml::CNodeCollection(tableArray[i])[0].GetValue(), (int64_t) i);
}
config.Clear();
appcontrol.Shutdown();
}

View File

@@ -0,0 +1,69 @@
# Define project
project (ModuleControlTests VERSION 1.0 LANGUAGES CXX)
# Get CRC++ from github
include(FetchContent)
FetchContent_Declare(
CRCpp
GIT_REPOSITORY https://github.com/d-bahr/CRCpp
GIT_TAG release-1.2.0.0
)
FetchContent_MakeAvailable(CRCpp)
# Add include directories
include_directories(../export ${CRCpp_SOURCE_DIR})
# build module example for the test
add_library(ComponentTest_ConfigInstall_Module SHARED
"test_component.cpp"
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_options(ComponentTest_ConfigInstall_Module PUBLIC -fPIC)
target_link_libraries(ComponentTest_ConfigInstall_Module GTest::GTest)
if (WIN32)
target_link_libraries(ComponentTest_ConfigInstall_Module Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_ConfigInstall_Module ${CMAKE_DL_LIBS} rt)
endif()
else()
target_link_libraries(ComponentTest_ConfigInstall_Module GTest::GTest Rpcrt4.lib)
endif()
set_target_properties(ComponentTest_ConfigInstall_Module PROPERTIES PREFIX "")
set_target_properties(ComponentTest_ConfigInstall_Module PROPERTIES SUFFIX ".sdv")
# Execute the sdv_packager utility to install the component in instance #2006.
add_custom_target(ComponentTest_ConfigInstall_install_manifest
# TODO EVE
# COMMAND "$<TARGET_FILE:sdv_packager>" -O. --instance2006 -NComponentTest_ConfigInstall "$<TARGET_FILE:ComponentTest_ConfigInstall_Module>" "-I$<TARGET_FILE_DIR:ComponentTest_ConfigInstall_Module>" --settings --create_configtest.toml
COMMAND "$<TARGET_FILE:sdv_packager>" DIRECT_INSTALL ComponentTest_ConfigInstall --instance2006 "$<TARGET_FILE:ComponentTest_ConfigInstall_Module>" "-I$<TARGET_FILE_DIR:ComponentTest_ConfigInstall_Module>" --overwrite --user_config
DEPENDS ComponentTest_ConfigInstall_Module
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
# Module control test executable
add_executable(ComponentTest_ConfigInstall
"main.cpp"
"module_install_test.cpp"
"manifest_helper_util_test.cpp"
)
target_link_libraries(ComponentTest_ConfigInstall ${CMAKE_DL_LIBS} GTest::GTest)
# Add the Data Dispatch Service unittest
add_test(NAME ComponentTest_ConfigInstall COMMAND ComponentTest_ConfigInstall WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
add_custom_command(TARGET ComponentTest_ConfigInstall POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_ConfigInstall>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_ConfigInstall.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_ConfigInstall_Module sdv_packager)
add_dependencies(ComponentTest_ConfigInstall_Module dependency_sdv_components)
add_dependencies(ComponentTest_ConfigInstall dependency_sdv_components)
add_dependencies(ComponentTest_ConfigInstall ComponentTest_ConfigInstall_Module)
add_dependencies(ComponentTest_ConfigInstall ComponentTest_ConfigInstall_install_manifest)

View File

@@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,81 @@
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>
#include <support/mem_access.h>
#include <support/app_control.h>
#include <filesystem>
#include "../../../global/exec_dir_helper.h"
TEST(ManifestHelperUtil, Instantiate)
{
sdv::app::CAppControl control;
bool bResult = control.Startup("");
EXPECT_TRUE(bResult);
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
sdv::core::TModuleID tManifestModule = pModuleControl->Load("manifest_util.sdv");
ASSERT_NE(tManifestModule, 0);
sdv::TObjectPtr ptrManifestUtil = sdv::core::CreateUtility("ManifestHelperUtility");
EXPECT_TRUE(ptrManifestUtil);
sdv::helper::IModuleManifestHelper* pManifestHelper = ptrManifestUtil.GetInterface<sdv::helper::IModuleManifestHelper>();
EXPECT_NE(pManifestHelper, nullptr);
ptrManifestUtil.Clear();
pModuleControl->Unload(tManifestModule);
control.Shutdown();
}
TEST(ManifestHelperUtil, NonExistingComponent)
{
sdv::app::CAppControl control;
bool bResult = control.Startup("");
EXPECT_TRUE(bResult);
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
sdv::core::TModuleID tManifestModule = pModuleControl->Load("manifest_util.sdv");
ASSERT_NE(tManifestModule, 0);
sdv::TObjectPtr ptrManifestUtil = sdv::core::CreateUtility("ManifestHelperUtility");
EXPECT_TRUE(ptrManifestUtil);
sdv::helper::IModuleManifestHelper* pManifestHelper = ptrManifestUtil.GetInterface<sdv::helper::IModuleManifestHelper>();
EXPECT_NE(pManifestHelper, nullptr);
sdv::u8string ssManifest = pManifestHelper->ReadModuleManifest("non_existing_component");
EXPECT_TRUE(ssManifest.empty());
ptrManifestUtil.Clear();
pModuleControl->Unload(tManifestModule);
control.Shutdown();
}
TEST(ManifestHelperUtil, ExistingComponent)
{
sdv::app::CAppControl control;
bool bResult = control.Startup("");
EXPECT_TRUE(bResult);
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
sdv::core::TModuleID tManifestModule = pModuleControl->Load("manifest_util.sdv");
ASSERT_NE(tManifestModule, 0);
sdv::TObjectPtr ptrManifestUtil = sdv::core::CreateUtility("ManifestHelperUtility");
EXPECT_TRUE(ptrManifestUtil);
sdv::helper::IModuleManifestHelper* pManifestHelper = ptrManifestUtil.GetInterface<sdv::helper::IModuleManifestHelper>();
EXPECT_NE(pManifestHelper, nullptr);
sdv::u8string ssManifest = pManifestHelper->ReadModuleManifest((GetExecDirectory() /
"ComponentTest_ConfigInstall_Module.sdv").generic_u8string());
EXPECT_FALSE(ssManifest.empty());
ptrManifestUtil.Clear();
pModuleControl->Unload(tManifestModule);
control.Shutdown();
}

View File

@@ -0,0 +1,277 @@
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>
#include <support/mem_access.h>
#include <support/app_control.h>
#include <filesystem>
#include "../../../global/exec_dir_helper.h"
#include "../../../global/base64.h"
#ifdef _WIN32
#include <Shlobj.h>
#endif
class CModuleControl_Install : public ::testing::Test
{
public:
virtual void SetUp()
{
DeleteTestDirs();
}
virtual void TearDown()
{
DeleteTestDirs();
}
static void SetUpTestCase() {}
static void TearDownTestSuite() {}
void DeleteTestDirs()
{
try
{
std::filesystem::remove_all(GetExecDirectory() / "module_test1");
}
catch (const std::filesystem::filesystem_error&)
{}
try
{
std::filesystem::remove_all(GetExecDirectory() / "module_test2");
}
catch (const std::filesystem::filesystem_error&)
{}
try
{
std::filesystem::remove_all(GetDefaultInstallDir());
}
catch (const std::filesystem::filesystem_error&)
{}
}
/**
* @brief Default installation directory.
* @return The default installation directory.
*/
std::filesystem::path GetDefaultInstallDir();
};
inline std::filesystem::path CModuleControl_Install::GetDefaultInstallDir()
{
// // The default directory for Windows is located at $ProgramData/ and for Posix at the executable.
std::filesystem::path pathInstallDir;
//#ifdef _WIN32
// wchar_t* szPath = nullptr;
// HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, 0, &szPath);
// if (SUCCEEDED(hr) && szPath)
// pathInstallDir = szPath;
// if (szPath) CoTaskMemFree(szPath);
//#elif defined __unix__
pathInstallDir = GetExecDirectory();
//#else
//#error OS is not supported!
//#endif
// Append the installation directory with /<instance_ID>/.
pathInstallDir /= "2006";
return pathInstallDir;
}
TEST_F(CModuleControl_Install, MainApp_DefaultInstallDir)
{
sdv::app::CAppControl control;
bool bResult = control.Startup("[Application]\nMode=\"Main\"\nInstance=2006");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetDefaultInstallDir()));
control.Shutdown();
}
TEST_F(CModuleControl_Install, IsolatedApp_DefaultInstallDir)
{
sdv::app::CAppControl control;
std::string ssConnectionString = Base64EncodePlainText("");
std::string ssConfig = R"code([Application]
Mode = "Isolated"
Instance = 2006
Connection = ")code";
ssConfig += Base64EncodePlainText("test") + "\"";
bool bResult = control.Startup(ssConfig);
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetDefaultInstallDir()));
control.Shutdown();
}
TEST_F(CModuleControl_Install, OtherApp_DefaultInstallDir)
{
sdv::app::CAppControl control;
bool bResult = control.Startup("");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_FALSE(std::filesystem::exists(GetDefaultInstallDir()));
control.Shutdown();
}
TEST_F(CModuleControl_Install, MainApp_BlockDefaultInstallDir)
{
// Prevent error reporting on std::cerr - they will influence test outcome.
auto* pCErr = std::cerr.rdbuf();
std::ostringstream sstreamCErr;
std::cerr.rdbuf(sstreamCErr.rdbuf());
// Create a blocking file... cannot create directory!
std::ofstream fstream(GetDefaultInstallDir());
ASSERT_TRUE(fstream.is_open());
fstream << "Dummy string...";
fstream.close();
sdv::app::CAppControl control;
bool bResult = control.Startup("[Application]\nMode=\"Main\"\nInstance=2006");
EXPECT_FALSE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetDefaultInstallDir()));
std::cerr.rdbuf(pCErr);
}
TEST_F(CModuleControl_Install, IsolatedApp_BlockDefaultInstallDir)
{
// Prevent error reporting on std::cerr - they will influence test outcome.
auto* pCErr = std::cerr.rdbuf();
std::ostringstream sstreamCErr;
std::cerr.rdbuf(sstreamCErr.rdbuf());
std::ofstream fstream(GetDefaultInstallDir());
ASSERT_TRUE(fstream.is_open());
fstream << "Dummy string...";
fstream.close();
sdv::app::CAppControl control;
bool bResult = control.Startup("[Application]\nMode=\"Isolated\"\nInstance=2006");
EXPECT_FALSE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetDefaultInstallDir()));
std::cerr.rdbuf(pCErr);
}
TEST_F(CModuleControl_Install, OtherApp_BlockDefaultInstallDir)
{
std::ofstream fstream(GetDefaultInstallDir());
ASSERT_TRUE(fstream.is_open());
fstream << "Dummy string...";
fstream.close();
sdv::app::CAppControl control;
bool bResult = control.Startup("");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetDefaultInstallDir()));
control.Shutdown();
}
TEST_F(CModuleControl_Install, MainApp_CustomInstallDirRelative)
{
sdv::app::CAppControl control;
bool bResult = control.Startup(R"code(
[Application]
Mode="Main"
Instance=2006
InstallDir = "module_test1"
)code");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetExecDirectory() / "module_test1"));
control.Shutdown();
}
TEST_F(CModuleControl_Install, IsolatedApp_CustomInstallDirRelative)
{
sdv::app::CAppControl control;
bool bResult = control.Startup(std::string(R"code(
[Application]
Mode="Isolated"
Instance=2006
InstallDir = "module_test1"
Connection = ")code") + Base64EncodePlainText("test") + "\"");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetExecDirectory() / "module_test1"));
control.Shutdown();
}
TEST_F(CModuleControl_Install, OtherApp_CustomInstallDirRelative)
{
sdv::app::CAppControl control;
bool bResult = control.Startup(R"code([Application]
Install.Dir = "module_test1"
)code");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_FALSE(std::filesystem::exists(GetExecDirectory() / "module_test1"));
control.Shutdown();
}
TEST_F(CModuleControl_Install, MainApp_CustomInstallDirAbsolute)
{
sdv::app::CAppControl control;
bool bResult = control.Startup(std::string(R"code(
[Application]
Mode="Main"
Instance=2006
InstallDir = ")code") + (GetExecDirectory() / "module_test2").generic_u8string() + "\"");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetExecDirectory() / "module_test2"));
control.Shutdown();
}
TEST_F(CModuleControl_Install, IsolatedApp_CustomInstallDirAbsolute)
{
sdv::app::CAppControl control;
bool bResult = control.Startup(std::string(R"code(
[Application]
Mode="Isolated"
Instance=2006
InstallDir = ")code") + (GetExecDirectory() / "module_test2").generic_u8string() + "\"" + R"code(
Connection = ")code" + Base64EncodePlainText("test") + "\"");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_TRUE(std::filesystem::exists(GetExecDirectory() / "module_test2"));
control.Shutdown();
}
TEST_F(CModuleControl_Install, OtherApp_CustomInstallDirAbsolute)
{
sdv::app::CAppControl control;
bool bResult = control.Startup(std::string(R"code([Application]
InstallDir = ")code") + (GetExecDirectory() / "module_test2").generic_u8string() + "\"");
EXPECT_TRUE(bResult);
// The default installation directory should be created.
EXPECT_FALSE(std::filesystem::exists(GetExecDirectory() / "module_test2"));
control.Shutdown();
}

View File

@@ -0,0 +1,28 @@
#include <support/component_impl.h>
class CModuleTestComponent1 : public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Utility)
DECLARE_OBJECT_CLASS_NAME("ModuleTestComponent1")
private:
};
DEFINE_SDV_OBJECT(CModuleTestComponent1)
class CModuleTestComponent2 : public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Utility)
DECLARE_OBJECT_CLASS_NAME("ModuleTestComponent2")
private:
};
DEFINE_SDV_OBJECT(CModuleTestComponent2)

View File

@@ -0,0 +1,31 @@
# Define project
project (ComponentTest_CoreLibrary VERSION 1.0 LANGUAGES CXX)
# Data maneger executable
add_executable(ComponentTest_CoreLibrary
"main.cpp"
"app_control_test.cpp"
"app_control_test_no_event_handler.cpp"
"app_control_test_event_handler.cpp"
"app_control_test_mgnt_class.cpp"
"app_config.cpp")
target_link_libraries(ComponentTest_CoreLibrary ${CMAKE_DL_LIBS} GTest::GTest)
# Add the Data Dispatch Service unittest
add_test(NAME ComponentTest_CoreLibrary COMMAND ComponentTest_CoreLibrary WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
# Currently disabled due to issues with MINGW causing the application to sporadically crash. A bug ticket has been filed:
# https://dev.azure.com/SW4ZF/AZP-074_DivDI_SofDCarResearch/_workitems/edit/608132
#add_custom_command(TARGET ComponentTest_CoreLibrary POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_CoreLibrary>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_CoreLibrary.xml
# VERBATIM
#)
# Build dependencies
add_dependencies(ComponentTest_CoreLibrary install_manifest)
add_dependencies(ComponentTest_CoreLibrary dependency_sdv_components)
add_dependencies(ComponentTest_CoreLibrary data_dispatch_service)
add_dependencies(ComponentTest_CoreLibrary ComponentTest_Repository) # Use the repository components for this test

View File

@@ -0,0 +1,29 @@
// Application config tests
// Load config file - Save config file - identical?
// Load config file - add module - save config file - module added?
// Load config file - add and delete module - identical?
// Load config file - add component - save config file - module added?
// Load config file - add and delete component - identical?
// Load config file - load another config file - Save config file - identical to last config file?
// Load config file - reset baseline - add module - save config file - only module in config?
// Load config file - reset baseline - add component - save config file - only component in config?
// Add module - save config - only module in config?
// Add component - save config - only component in config?
// Add config file in Startup - config loaded?
// For main app: add system config file in settings - config loaded?
// For main app: add multiple system config file in settings - config loaded?
// For main app: add application config file in settings - config loaded?
// For main app: add multiple system config files and an application config in settings - configs loaded?
// For main app: add application config file in settings - config loaded? - add component - auto save config - config updated with additional compoment?
// For main app: add multiple system config files and an application config file in settings - config loaded? - add component - auto save config - config updated with additional compoment?
// For main app: add system config file in settings - add config in application startup - configs loaded?
// For main app: add multiple system config file in settings - add config in application startup - configs loaded?
// For main app: add application config file in settings - add config in application startup - startup config loaded (and otherone not)?
// For main app: add application config file in settings - add config in application startup - add service - startup config not updated? Settings config also not?
// Test search algorithm with multiple modules with similar name in different location for standalone and essential
// Test search algorithm with multiple modules with similar name in different location for main and isolated
// Test configuration saving of module path shoudl not change when module is found somewhere else.
// Test not existing config
// Test partially existing config (some modules/components do not exist)
// Test multiple manifest for loading components

View File

@@ -0,0 +1,33 @@
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>
#include <support/mem_access.h>
#include <support/app_control.h>
#include "../../../global/exec_dir_helper.h"
TEST(CoreLibrary_AppControl, SetModuleSearchPath)
{
sdv::core::IModuleControlConfig* pModuleConfig = sdv::core::GetCore<sdv::core::IModuleControlConfig>();
ASSERT_NE(pModuleConfig, nullptr);
bool bResult = pModuleConfig->AddModuleSearchDir("../../bin");
EXPECT_TRUE(bResult);
sdv::sequence<sdv::u8string> seqSearchDirs = pModuleConfig->GetModuleSearchDirs();
std::filesystem::path pathModuleDir = (GetExecDirectory() / "../../bin").lexically_normal();
auto itDir = std::find_if(seqSearchDirs.begin(), seqSearchDirs.end(),
[&](const sdv::u8string& rssDir)
{
std::filesystem::path pathDir = static_cast<std::string>(rssDir);
if (pathDir.is_relative())
pathDir = (GetExecDirectory() / pathDir).lexically_normal();
return pathDir == pathModuleDir;
});
EXPECT_NE(itDir, seqSearchDirs.end());
}
TEST(CoreLibrary_AppControl, SetModuleSearchPathMgntClass)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.AddModuleSearchDir("../../bin");
EXPECT_TRUE(bResult);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,510 @@
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>
#include <support/mem_access.h>
#include <support/app_control.h>
#include "../../../sdv_services/core/local_shutdown_request.h"
#include "../../../global/base64.h"
TEST(CoreLibrary_AppControl_MgntClass, Startup_Invalid_ApplicationMode)
{
// Prevent error reporting on std::cerr - they will influence test outcome.
auto* pCErr = std::cerr.rdbuf();
std::ostringstream sstreamCErr;
std::cerr.rdbuf(sstreamCErr.rdbuf());
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Invalid\"");
EXPECT_FALSE(bResult);
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
std::cerr.rdbuf(pCErr);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Default_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::standalone);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Standalone_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Standalone\"");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::standalone);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_External_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"External\"");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::external);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Isolated_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup(R"code(
[Application]
Mode = "Isolated"
[Console]
Report = "Silent"
)code");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::isolated);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Main_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Main\"");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::main);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Essential_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Essential\"");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::essential);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Maintenance_NoConfig)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Maintenance\"");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::maintenance);
EXPECT_EQ(control.GetInstanceID(), 1000u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Default_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nInstance=2005");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::standalone);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Standalone_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Standalone\"\nInstance=2005");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::standalone);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_External_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"External\"\nInstance=2005");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::external);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Isolated_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
std::string ssConfig = R"code([Application]
Mode = "Isolated"
Instance = 2005
Connection = ")code";
ssConfig += Base64EncodePlainText("test") + "\"";
bool bResult = control.Startup(ssConfig);
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::isolated);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Main_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Main\"\nInstance=2005");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::main);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Essential_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Essential\"\nInstance=2005");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::essential);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, Startup_Maintenance_DefineInstance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Maintenance\"\nInstance=2005");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::maintenance);
EXPECT_EQ(control.GetInstanceID(), 2005u);
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_Default)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nInstance=2007");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::standalone);
EXPECT_EQ(control.GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
EXPECT_TRUE(control.RunLoop());
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_Standalone)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Standalone\"\nInstance=2007");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::standalone);
EXPECT_EQ(control.GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
EXPECT_TRUE(control.RunLoop());
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_External)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"External\"\nInstance=2007");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::external);
EXPECT_EQ(control.GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
EXPECT_TRUE(control.RunLoop());
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_Isolated)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
std::string ssConfig = R"code([Application]
Mode = "Isolated"
Instance = 2007
Connection = ")code";
ssConfig += Base64EncodePlainText("test") + "\"";
bool bResult = control.Startup(ssConfig);
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::isolated);
EXPECT_EQ(control.GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
sdv::app::IAppShutdownRequest* pShutdownRequest = sdv::core::GetObject<sdv::app::IAppShutdownRequest>("AppControlService");
ASSERT_NE(pShutdownRequest, nullptr);
pShutdownRequest->RequestShutdown();
});
EXPECT_TRUE(control.RunLoop());
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_Main)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Main\"\nInstance=2007");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::main);
EXPECT_EQ(control.GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
sdv::app::IAppShutdownRequest* pShutdownRequest = sdv::core::GetObject<sdv::app::IAppShutdownRequest>("AppControlService");
ASSERT_NE(pShutdownRequest, nullptr);
pShutdownRequest->RequestShutdown();
});
EXPECT_TRUE(control.RunLoop());
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_Essential)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Essential\"\nInstance=2007");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::essential);
EXPECT_EQ(control.GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
EXPECT_TRUE(control.RunLoop());
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_MgntClass, RunLoop_Maintenance)
{
sdv::app::CAppControl control;
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
bool bResult = control.Startup("[Application]\nMode=\"Maintenance\"\nInstance=2007");
EXPECT_TRUE(bResult);
EXPECT_TRUE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::maintenance);
EXPECT_EQ(control.GetInstanceID(), 2007u);
// Loop not allowed...
EXPECT_FALSE(control.RunLoop());
control.Shutdown();
EXPECT_FALSE(control.IsRunning());
EXPECT_EQ(control.GetAppContext(), sdv::app::EAppContext::no_context);
EXPECT_EQ(control.GetInstanceID(), 0u);
}

View File

@@ -0,0 +1,643 @@
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>
#include <support/mem_access.h>
#include <support/app_control.h>
#include "../../../sdv_services/core/local_shutdown_request.h"
#include "../../../global/base64.h"
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Invalid_ApplicationMode)
{
// Prevent error reporting on std::cerr - they will influence test outcome.
auto* pCErr = std::cerr.rdbuf();
std::ostringstream sstreamCErr;
std::cerr.rdbuf(sstreamCErr.rdbuf());
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Invalid\"", nullptr);
EXPECT_FALSE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
std::cerr.rdbuf(pCErr);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Default_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::standalone);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Standalone_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Standalone\"", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::standalone);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_External_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"External\"", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::external);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Isolated_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup(R"code(
[Application]
Mode = "Isolated"
[Console]
Report = "Silent"
)code", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::isolated);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Main_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Main\"", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::main);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Essential_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Essential\"", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::essential);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Maintenance_NoConfig)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Maintenance\"", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::maintenance);
EXPECT_EQ(pContext->GetInstanceID(), 1000u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Default_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nInstance=2005", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::standalone);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Standalone_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Standalone\"\nInstance=2005", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::standalone);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_External_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"External\"\nInstance=2005", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::external);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Isolated_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
std::string ssConfig = R"code([Application]
Mode = "Isolated"
Instance = 2005
Connection = ")code";
ssConfig += Base64EncodePlainText("test") + "\"";
bool bResult = pControl->Startup(ssConfig, nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::isolated);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Main_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Main\"\nInstance=2005", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::main);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Essential_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Essential\"\nInstance=2005", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::essential);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, Startup_Maintenance_DefineInstance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Maintenance\"\nInstance=2005", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::maintenance);
EXPECT_EQ(pContext->GetInstanceID(), 2005u);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_Default)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nInstance=2007", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::standalone);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
pControl->RunLoop();
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_Standalone)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Standalone\"\nInstance=2007", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::standalone);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
pControl->RunLoop();
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_External)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"External\"\nInstance=2007", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::external);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
pControl->RunLoop();
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_Isolated)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
std::string ssConfig = R"code([Application]
Mode = "Isolated"
Instance = 2007
Connection = ")code";
ssConfig += Base64EncodePlainText("test") + "\"";
bool bResult = pControl->Startup(ssConfig, nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::isolated);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
sdv::app::IAppShutdownRequest* pShutdownRequest = sdv::core::GetObject<sdv::app::IAppShutdownRequest>("AppControlService");
ASSERT_NE(pShutdownRequest, nullptr);
pShutdownRequest->RequestShutdown();
});
pControl->RunLoop();
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_Main)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Main\"\nInstance=2007", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::main);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
sdv::app::IAppShutdownRequest* pShutdownRequest = sdv::core::GetObject<sdv::app::IAppShutdownRequest>("AppControlService");
ASSERT_NE(pShutdownRequest, nullptr);
pShutdownRequest->RequestShutdown();
});
pControl->RunLoop();
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_Essential)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Essential\"\nInstance=2007", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::essential);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
auto tpStart = std::chrono::high_resolution_clock::now();
std::thread threadShutdownRequest([]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(250));
RequestShutdown(2007u);
});
pControl->RunLoop();
EXPECT_GT(std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tpStart).count(), 0.100);
threadShutdownRequest.join();
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}
TEST(CoreLibrary_AppControl_NoEventHandler, RunLoop_Maintenance)
{
sdv::app::IAppControl* pControl = sdv::core::GetCore<sdv::app::IAppControl>();
ASSERT_NE(pControl, nullptr);
sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
ASSERT_NE(pContext, nullptr);
sdv::app::IAppOperation* pOperation = sdv::core::GetCore<sdv::app::IAppOperation>();
ASSERT_NE(pOperation, nullptr);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
bool bResult = pControl->Startup("[Application]\nMode=\"Maintenance\"\nInstance=2007", nullptr);
EXPECT_TRUE(bResult);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::running);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::maintenance);
EXPECT_EQ(pContext->GetInstanceID(), 2007u);
// Loop not allowed...
EXPECT_THROW(pControl->RunLoop(), sdv::XAccessDenied);
pControl->Shutdown(true);
EXPECT_EQ(pOperation->GetOperationState(), sdv::app::EAppOperationState::not_started);
EXPECT_EQ(pContext->GetContextType(), sdv::app::EAppContext::no_context);
EXPECT_EQ(pContext->GetInstanceID(), 0u);
}

View File

@@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,32 @@
# Define project
project (DataDispatchServiceTests VERSION 1.0 LANGUAGES CXX)
# Data maneger executable
add_executable(ComponentTest_DataDispatchService data_dispatch_service_test.cpp "transaction_test.cpp" "main.cpp" "trigger_test.cpp")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(THREADS_PREFER_PTHREAD_FLAG ON)
target_link_libraries(ComponentTest_DataDispatchService ${CMAKE_THREAD_LIBS_INIT} GTest::GTest)
if (WIN32)
target_link_libraries(ComponentTest_DataDispatchService Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_DataDispatchService ${CMAKE_DL_LIBS} rt)
endif()
else()
target_link_libraries(ComponentTest_DataDispatchService GTest::GTest Rpcrt4.lib)
endif()
# Add the Data Dispatch Service unittest
add_test(NAME ComponentTest_DataDispatchService COMMAND ComponentTest_DataDispatchService WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
add_custom_command(TARGET ComponentTest_DataDispatchService POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_DataDispatchService>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_DataDispatchService.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_DataDispatchService dependency_sdv_components)
add_dependencies(ComponentTest_DataDispatchService data_dispatch_service)
add_dependencies(ComponentTest_DataDispatchService task_timer)
file (COPY ${PROJECT_SOURCE_DIR}/test_dds_config.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,814 @@
#include <gtest/gtest.h>
#include <iostream>
#include <mutex>
#include <thread>
#include <utility>
#include <atomic>
#include <chrono>
#include <support/signal_support.h>
#include <interfaces/dispatch.h>
#include <support/app_control.h>
TEST(DataDispatchServiceTest, SingleSpontaneousTrigger)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; });
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, 7);
// Send data through the publisher
signal8.Write(101);
signal9.Write(111);
signal10.Write(121);
signal11.Write(131);
signal12.Write(141);
signal13.Write(151);
signal14.Write(161);
EXPECT_EQ(nTriggerCnt, 14);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, MultipleSpontaneousTrigger)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTrigger1Cnt = 0;
sdv::core::CTrigger trigger1 = dispatch.CreateTxTrigger([&] { nTrigger1Cnt++; });
EXPECT_TRUE(trigger1);
trigger1.AddSignal(signal1);
trigger1.AddSignal(signal2);
trigger1.AddSignal(signal3);
size_t nTrigger2Cnt = 0;
sdv::core::CTrigger trigger2 = dispatch.CreateTxTrigger([&] { nTrigger2Cnt++; });
EXPECT_TRUE(trigger2);
trigger2.AddSignal(signal4);
trigger2.AddSignal(signal5);
trigger2.AddSignal(signal6);
trigger2.AddSignal(signal7);
EXPECT_EQ(nTrigger2Cnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTrigger1Cnt, 3);
EXPECT_EQ(nTrigger2Cnt, 4);
trigger1.Reset();
trigger2.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, TriggerRemoveSignals)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; });
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, 7);
// Remove signals from trigger
trigger.RemoveSignal(signal4);
trigger.RemoveSignal(signal4); // Check double removal
trigger.RemoveSignal(signal5);
// Send data through the publisher
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, 12);
// Reset signal
signal6.Reset();
signal7.Reset();
// Send data through the publisher
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, 15);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, SpontaneousTransactionalTrigger)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Start read transaction
sdv::core::CTransaction transaction = dispatch.CreateTransaction();
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; });
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
signal8.Write(100, transaction);
signal9.Write(110, transaction);
signal10.Write(120, transaction);
signal11.Write(130, transaction);
signal12.Write(140, transaction);
signal13.Write(150, transaction);
signal14.Write(160, transaction);
EXPECT_EQ(nTriggerCnt, 0);
// Send data through the publisher
signal8.Write(200, transaction);
signal9.Write(210, transaction);
signal10.Write(220, transaction);
signal11.Write(230, transaction);
signal12.Write(240, transaction);
signal13.Write(250, transaction);
signal14.Write(260, transaction);
EXPECT_EQ(nTriggerCnt, 0);
// Finalize the transaction
transaction.Finish();
EXPECT_EQ(nTriggerCnt, 1);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, PeriodicTrigger)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; }, false, 0, 100);
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
size_t nTriggerCntTemp = nTriggerCnt;
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp);
// Sleep for 750 ms
std::this_thread::sleep_for(std::chrono::milliseconds(750));
// Check trigger count.
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp + 7);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, PeriodicTriggerOnlyActive)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; }, false, 0, 100, true);
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
size_t nTriggerCntTemp = nTriggerCnt;
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp);
// Sleep for 220 ms
std::this_thread::sleep_for(std::chrono::milliseconds(220));
// Back to default value
nTriggerCntTemp = nTriggerCnt;
signal8.Write(10);
signal9.Write(20);
signal10.Write(30);
signal11.Write(40);
signal12.Write(50);
signal13.Write(60);
signal14.Write(70);
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp);
// Sleep for 700 ms
std::this_thread::sleep_for(std::chrono::milliseconds(700));
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp + 1);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, SpontaneousAndPeriodicTrigger)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; }, true, 0, 100);
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
size_t nTriggerCntTemp = nTriggerCnt;
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp + 7);
// Sleep for 750 ms
std::this_thread::sleep_for(std::chrono::milliseconds(750));
// Check trigger count.
EXPECT_EQ(nTriggerCnt, nTriggerCntTemp + 14);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}
TEST(DataDispatchServiceTest, SingleSpontaneousTriggerWithDelay)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
// Register the signals
sdv::core::CDispatchService dispatch;
sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10);
EXPECT_TRUE(signal1);
sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20);
EXPECT_TRUE(signal2);
sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30);
EXPECT_TRUE(signal3);
sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40);
EXPECT_TRUE(signal4);
sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50);
EXPECT_TRUE(signal5);
sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60);
EXPECT_TRUE(signal6);
sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70);
EXPECT_TRUE(signal7);
// Add publisher for the signals
sdv::core::CSignal signal8 = dispatch.AddPublisher("abc");
EXPECT_TRUE(signal8);
sdv::core::CSignal signal9 = dispatch.AddPublisher("def");
EXPECT_TRUE(signal9);
sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi");
EXPECT_TRUE(signal10);
sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl");
EXPECT_TRUE(signal11);
sdv::core::CSignal signal12 = dispatch.AddPublisher("mno");
EXPECT_TRUE(signal12);
sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr");
EXPECT_TRUE(signal13);
sdv::core::CSignal signal14 = dispatch.AddPublisher("stu");
EXPECT_TRUE(signal14);
// Create a trigger
size_t nTriggerCnt = 0;
sdv::core::CTrigger trigger = dispatch.CreateTxTrigger([&] { nTriggerCnt++; }, true, 100);
EXPECT_TRUE(trigger);
trigger.AddSignal(signal1);
trigger.AddSignal(signal2);
trigger.AddSignal(signal3);
trigger.AddSignal(signal4);
trigger.AddSignal(signal5);
trigger.AddSignal(signal6);
trigger.AddSignal(signal7);
EXPECT_EQ(nTriggerCnt, 0);
appcontrol.SetRunningMode();
// Send data through the publisher
signal8.Write(100);
signal9.Write(110);
signal10.Write(120);
signal11.Write(130);
signal12.Write(140);
signal13.Write(150);
signal14.Write(160);
EXPECT_EQ(nTriggerCnt, 1);
// Send data through the publisher
signal8.Write(101);
signal9.Write(111);
signal10.Write(121);
signal11.Write(131);
signal12.Write(141);
signal13.Write(151);
signal14.Write(161);
EXPECT_EQ(nTriggerCnt, 1);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
EXPECT_EQ(nTriggerCnt, 2);
appcontrol.SetConfigMode();
trigger.Reset();
signal1.Reset();
signal2.Reset();
signal3.Reset();
signal4.Reset();
signal5.Reset();
signal6.Reset();
signal7.Reset();
signal8.Reset();
signal9.Reset();
signal10.Reset();
signal11.Reset();
signal12.Reset();
signal13.Reset();
signal14.Reset();
appcontrol.Shutdown();
}

View File

@@ -0,0 +1,74 @@
# Define project
project (DbcUtilTests VERSION 1.0 LANGUAGES CXX)
# Find the DBC utility
# REMARKS The utility can only be found after it has build. Having both the utility and the unittest project build, causes an
# error during the scanning phase of CMake.
#find_program(DBCUTIL NAMES "sdv_dbc_util" PATHS "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../../bin/" NO_CACHE)
set (DBCUTIL "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../../bin/sdv_dbc_util")
message("Use DBC utility: ${DBCUTIL}")
# Generate the datalink
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/generated/dbc_struct_test/can_dl/datalink.h ${PROJECT_SOURCE_DIR}/generated/dbc_struct_test/can_dl/datalink.cpp
DEPENDS sdv_dbc_util
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/dbc_struct_test.dbc
COMMENT "Build dbc_struct_test.dbc"
COMMAND ${DBCUTIL} ${PROJECT_SOURCE_DIR}/dbc_struct_test.dbc -O${PROJECT_SOURCE_DIR}/generated/dbc_struct_test/ --nodesTestECU_Tx,TestECU_Rx
VERBATIM
)
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/generated/example_can_test/can_dl/datalink.h ${PROJECT_SOURCE_DIR}/generated/example_can_test/can_dl/datalink.cpp
DEPENDS sdv_dbc_util
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/example_can.dbc
COMMENT "Build example_can.dbc"
COMMAND ${DBCUTIL} ${PROJECT_SOURCE_DIR}/example_can.dbc -O${PROJECT_SOURCE_DIR}/generated/example_can_test/ --nodesDSC_ASC_ABS
VERBATIM
)
add_custom_target(PrecompileDBCUtilTest
DEPENDS
${PROJECT_SOURCE_DIR}/generated/dbc_struct_test/can_dl/datalink.cpp
${PROJECT_SOURCE_DIR}/generated/example_can_test/can_dl/datalink.cpp
${PROJECT_SOURCE_DIR}/generated/dbc_struct_test/can_dl/datalink.h
${PROJECT_SOURCE_DIR}/generated/example_can_test/can_dl/datalink.h
)
# DBC util component test executable
add_executable(ComponentTest_DbcUtil dbc_util_test.cpp)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(THREADS_PREFER_PTHREAD_FLAG ON)
target_link_libraries(ComponentTest_DbcUtil ${CMAKE_THREAD_LIBS_INIT} GTest::GTest)
if (WIN32)
target_link_libraries(ComponentTest_DbcUtil Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_DbcUtil ${CMAKE_DL_LIBS} rt)
endif()
else()
target_link_libraries(ComponentTest_DbcUtil GTest::GTest Rpcrt4.lib)
endif()
# Add the DBC utility component test
add_test(NAME ComponentTest_DbcUtil COMMAND ComponentTest_DbcUtil WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# copy the folder 'test_dbc_util_config.toml' to output folder 'config'
file (COPY ${PROJECT_SOURCE_DIR}/test_dbc_util_config_asc.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)
file (COPY ${PROJECT_SOURCE_DIR}/test_dbc_util_config_rx.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)
file (COPY ${PROJECT_SOURCE_DIR}/test_dbc_util_config_tx.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)
# Execute the test
add_custom_command(TARGET ComponentTest_DbcUtil POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_DbcUtil>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_DbcUtil.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_DbcUtil sdv_dbc_util)
add_dependencies(ComponentTest_DbcUtil PrecompileDBCUtilTest)
add_dependencies(ComponentTest_DbcUtil dependency_sdv_components)
add_dependencies(ComponentTest_DbcUtil task_timer)
add_dependencies(ComponentTest_DbcUtil data_dispatch_service)
add_dependencies(ComponentTest_DbcUtil can_com_sim)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,233 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: TestECU_Rx TestECU_Tx
BO_ 39 TestLE_MinMax: 8 TestECU_Tx
SG_ SignalLE6 : 32|32@1+ (-1.5,5000) [-5000|5000] "" TestECU_Rx
SG_ SignalLE5 : 24|8@1- (12.34567,0) [-1000|1000] "" TestECU_Rx
SG_ SignalLE4 : 18|6@1+ (0.5,-16) [-15|15] "" TestECU_Rx
SG_ SignalLE3 : 12|6@1- (1,25) [0|50] "" TestECU_Rx
SG_ SignalLE2 : 4|8@1+ (2,-100) [-100|300] "" TestECU_Rx
SG_ SignalLE1 : 0|4@1- (1,0) [-6|6] "" TestECU_Rx
BO_ 38 TestBE_MinMax: 8 TestECU_Tx
SG_ SignalBE1 : 7|4@0- (1,0) [-6|6] "" TestECU_Rx
SG_ SignalBE2 : 3|8@0+ (2,-100) [-100|300] "" TestECU_Rx
SG_ SignalBE3 : 11|6@0- (1,25) [0|50] "" TestECU_Rx
SG_ SignalBE4 : 21|6@0+ (0.5,-16) [-15|15] "" TestECU_Rx
SG_ SignalBE5 : 31|8@0- (12.34567,0) [-1000|1000] "" TestECU_Rx
SG_ SignalBE6 : 39|32@0+ (-1.5,5000) [-5000|5000] "" TestECU_Rx
BO_ 8 TestCyclic: 1 TestECU_Tx
SG_ Counter : 7|3@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 9 TestCyclicAndSpontaneous: 1 TestECU_Tx
SG_ Counter : 7|3@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 10 TestCyclicIfActive: 1 TestECU_Tx
SG_ Counter : 7|3@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 11 TestCyclicIfActiveAndSpontaneous: 1 TestECU_Tx
SG_ Counter : 7|3@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 12 TestSpontaneousDelay: 1 TestECU_Tx
SG_ Counter : 7|3@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 13 TestCyclicAndSpontaneousDelay: 1 TestECU_Tx
SG_ Counter : 7|3@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 100 TestUintLE: 8 TestECU_Tx
SG_ SignalUintLE6 : 34|30@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintLE5 : 16|18@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintLE4 : 9|7@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintLE3 : 3|6@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintLE2 : 1|2@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintLE1 : 0|1@1+ (1,0) [0|0] "" TestECU_Rx
BO_ 101 TestUintBE: 8 TestECU_Tx
SG_ SignalUintBE1 : 7|1@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintBE2 : 6|2@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintBE3 : 4|6@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintBE4 : 14|7@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintBE5 : 23|18@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalUintBE6 : 37|30@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 102 TestUint64LE: 8 TestECU_Tx
SG_ SignalUint64LE : 0|64@1+ (1,0) [0|0] "" TestECU_Rx
BO_ 103 TestUint64BE: 8 TestECU_Tx
SG_ SignalUint64BE : 7|64@0+ (1,0) [0|0] "" TestECU_Rx
BO_ 200 TestIntLE: 8 TestECU_Tx
SG_ SignalIntLE6 : 34|30@1- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntLE5 : 16|18@1- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntLE4 : 13|3@1- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntLE3 : 7|6@1- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntLE2 : 2|5@1- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntLE1 : 0|2@1- (1,0) [0|0] "" TestECU_Rx
BO_ 201 TestIntBE: 8 TestECU_Tx
SG_ SignalIntBE1 : 7|2@0- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntBE2 : 5|5@0- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntBE3 : 0|6@0- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntBE4 : 10|3@0- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntBE5 : 23|18@0- (1,0) [0|0] "" TestECU_Rx
SG_ SignalIntBE6 : 37|30@0- (1,0) [0|0] "" TestECU_Rx
BO_ 202 TestInt64LE: 8 TestECU_Tx
SG_ SignalInt64LE : 0|64@1- (1,0) [0|0] "" TestECU_Rx
BO_ 203 TestInt64BE: 8 TestECU_Tx
SG_ SignalInt64BE : 7|64@0- (1,0) [0|0] "" TestECU_Rx
BO_ 300 TestFloatLE: 8 TestECU_Tx
SG_ SignalFloatLE2 : 32|32@1- (1,0) [0|0] "" TestECU_Rx
SG_ SignalFloatLE1 : 0|32@1- (1,0) [0|0] "" TestECU_Rx
BO_ 301 TestFloatBE: 8 TestECU_Tx
SG_ SignalFloatBE1 : 7|32@0- (1,0) [0|0] "" TestECU_Rx
SG_ SignalFloatBE2 : 39|32@0- (1,0) [0|0] "" TestECU_Rx
BO_ 400 TestDoubleLE: 8 TestECU_Tx
SG_ SignalDoubleLE1 : 0|64@1- (1,0) [0|0] "" TestECU_Rx
BO_ 401 TestDoubleBE: 8 TestECU_Tx
SG_ SignalDoubleBE1 : 7|64@0- (1,0) [0|0] "" TestECU_Rx
BO_ 500 TestScaleLE: 7 TestECU_Tx
SG_ SignalScaleFloatLE7 : 24|32@1- (0.001,100) [-1000|1000] "" TestECU_Rx
SG_ SignalScaleIntLE6 : 20|4@1- (1,-3.5) [-14|15] "" TestECU_Rx
SG_ SignalScaleIntLE5 : 16|4@1- (0.001,0.008) [0.002|0.012] "" TestECU_Rx
SG_ SignalScaleUintLE4 : 12|4@1+ (1,-2) [-1|10.5] "" TestECU_Rx
SG_ SignalScaleUintLE3 : 8|4@1+ (-1,0) [-14|-2] "" TestECU_Rx
SG_ SignalScaleUintLE2 : 4|4@1+ (1,-3.5) [-2|11.5] "" TestECU_Rx
SG_ SignalScaleUintLE1 : 0|4@1+ (0.001,0) [0.002|0.012] "" TestECU_Rx
BO_ 501 TestScaleBE: 7 TestECU_Tx
SG_ SignalScaleUintBE1 : 7|4@0+ (0.001,0) [0.002|0.012] "" TestECU_Rx
SG_ SignalScaleUintBE2 : 3|4@0+ (1,-3.5) [-2|11.5] "" TestECU_Rx
SG_ SignalScaleUintBE3 : 15|4@0+ (-1,0) [-14|-2] "" TestECU_Rx
SG_ SignalScaleUintBE4 : 11|4@0+ (1,-2) [-1|10.5] "" TestECU_Rx
SG_ SignalScaleIntBE5 : 23|4@0- (0.001,0.008) [0.002|0.012] "" TestECU_Rx
SG_ SignalScaleIntBE6 : 19|4@0- (1,-3.5) [-14|15] "" TestECU_Rx
SG_ SignalScaleFloatBE7 : 31|32@0- (0.001,100) [-1000|1000] "" TestECU_Rx
BO_ 502 TestScale64LE: 8 TestECU_Tx
SG_ SignalScaleInt64LE : 0|64@1- (1e-9,0) [-1000|1000] "" TestECU_Rx
BO_ 503 TestScale64BE: 8 TestECU_Tx
SG_ SignalScaleInt64BE : 7|64@0- (1e-9,0) [-1000|1000] "" TestECU_Rx
BO_ 7 TestLE: 8 TestECU_Tx
SG_ SignalLE6 : 32|32@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalLE5 : 24|8@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalLE4 : 18|6@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalLE3 : 12|6@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalLE2 : 4|8@1+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalLE1 : 0|4@1+ (1,0) [0|0] "" TestECU_Rx
BO_ 6 TestBE: 8 TestECU_Tx
SG_ SignalBE1 : 7|4@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalBE2 : 3|8@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalBE3 : 11|6@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalBE4 : 21|6@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalBE5 : 31|8@0+ (1,0) [0|0] "" TestECU_Rx
SG_ SignalBE6 : 39|32@0+ (1,0) [0|0] "" TestECU_Rx
BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 0;
BA_DEF_ BO_ "GenMsgSendType" ENUM "cyclic","triggered","cyclicIfActive","cyclicAndTriggered","cyclicIfActiveAndTriggered","none";
BA_DEF_ BO_ "GenMsgRequestable" INT 0 0;
BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 0;
BA_DEF_ BO_ "GenMsgLSupport" INT 0 0;
BA_DEF_ BO_ "GenMsgFastOnStart" INT 0 0;
BA_DEF_ BO_ "GenMsgDelayTime" INT 0 0;
BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 1000;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 1000;
BA_DEF_ SG_ "GenSigStartValue" FLOAT 0 0;
BA_DEF_ "BusType" STRING ;
BA_DEF_DEF_ "GenMsgStartDelayTime" 0;
BA_DEF_DEF_ "GenMsgSendType" "triggered";
BA_DEF_DEF_ "GenMsgRequestable" 0;
BA_DEF_DEF_ "GenMsgNrOfRepetition" 0;
BA_DEF_DEF_ "GenMsgLSupport" 0;
BA_DEF_DEF_ "GenMsgFastOnStart" 0;
BA_DEF_DEF_ "GenMsgDelayTime" 0;
BA_DEF_DEF_ "GenMsgCycleTimeFast" 100;
BA_DEF_DEF_ "GenMsgCycleTime" 100;
BA_DEF_DEF_ "GenSigStartValue" 0;
BA_DEF_DEF_ "BusType" "";
BA_ "BusType" "CAN";
BA_ "GenMsgCycleTime" BO_ 8 10;
BA_ "GenMsgSendType" BO_ 8 0;
BA_ "GenMsgCycleTime" BO_ 9 50;
BA_ "GenMsgSendType" BO_ 9 3;
BA_ "GenMsgCycleTime" BO_ 10 10;
BA_ "GenMsgSendType" BO_ 10 2;
BA_ "GenMsgCycleTime" BO_ 11 50;
BA_ "GenMsgSendType" BO_ 11 4;
BA_ "GenMsgDelayTime" BO_ 12 20;
BA_ "GenMsgSendType" BO_ 12 1;
BA_ "GenMsgDelayTime" BO_ 13 25;
BA_ "GenMsgCycleTime" BO_ 13 50;
BA_ "GenMsgSendType" BO_ 13 3;
BA_ "GenSigStartValue" SG_ 10 Counter 2;
BA_ "GenSigStartValue" SG_ 11 Counter 2;
BA_ "GenSigStartValue" SG_ 500 SignalScaleFloatLE7 100;
BA_ "GenSigStartValue" SG_ 500 SignalScaleIntLE6 10;
BA_ "GenSigStartValue" SG_ 500 SignalScaleIntLE5 10;
BA_ "GenSigStartValue" SG_ 500 SignalScaleUintLE4 10;
BA_ "GenSigStartValue" SG_ 500 SignalScaleUintLE3 10;
BA_ "GenSigStartValue" SG_ 500 SignalScaleUintLE2 10;
BA_ "GenSigStartValue" SG_ 500 SignalScaleUintLE1 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleUintBE1 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleUintBE2 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleUintBE3 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleUintBE4 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleIntBE5 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleIntBE6 10;
BA_ "GenSigStartValue" SG_ 501 SignalScaleFloatBE7 100;
SIG_VALTYPE_ 300 SignalFloatLE2 : 1;
SIG_VALTYPE_ 300 SignalFloatLE1 : 1;
SIG_VALTYPE_ 301 SignalFloatBE1 : 1;
SIG_VALTYPE_ 301 SignalFloatBE2 : 1;
SIG_VALTYPE_ 400 SignalDoubleLE1 : 2;
SIG_VALTYPE_ 401 SignalDoubleBE1 : 2;
SIG_VALTYPE_ 500 SignalScaleFloatLE7 : 1;
SIG_VALTYPE_ 501 SignalScaleFloatBE7 : 1;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,375 @@
VERSION "PrivateCAN"
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: ExampleNode
VAL_TABLE_ Fault_Codes 27 "UKWN" 26 "VEHSPDMAX_EXDD" 25 "STS_ALIVE" 24 "STEER_NOT_E2E_MODE" 23 "OTA_SPD" 22 "OTA_TIMER_DOWNLOAD_FAILED" 21 "OTA_MAX_TIME" 20 "CUBIXAD_STEERSTREQ_NOTACTV" 19 "CUBIXAD_DRVSTREQ_NOTACTV" 18 "SFTYDRV_INTV" 17 "LSDC_ALIVE" 16 "CUBIXAD_ALIVE" 15 "IBC_MAB_NO_PRIO" 14 "IBC_NOT_RDY" 13 "IBC_ALIVE" 12 "LSDC_GEAR" 11 "LSDC_SPD" 10 "LSDC_ACCL" 9 "IBC_NOT_MAB_MOD" 8 "GOLDBOX_ALIVE" 7 "CUBIXAD_GEAR" 6 "CUBIXAD_SPD_TESTTRACK" 5 "DRVREQCHG" 4 "RDY_TIMER" 3 "SFTY_CDN_FAILED" 2 "ACTVNCHK_SPD" 1 "ACTVNCHK_TIMR" 0 "NONE" ;
VAL_TABLE_ TestMapID 6 "E_TESTMAPID_UNDEFINED" 5 "E_TESTMAPID_TEST_DRIVE" 4 "E_TESTMAPID_AD_AREA" 3 "E_TESTMAPID_STUTT_ARENA" 2 "E_TESTMAPID_ZF_LASTMILE" 1 "E_TESTMAPID_ZF_TESTTRACK_2" 0 "E_TESTMAPID_NONE" ;
VAL_TABLE_ CtrlReqStates 7 "CtrlSts3b_RESERVED_4" 6 "CtrlSts3b_RESERVED_3" 5 "CtrlSts3b_RESERVED_2" 4 "CtrlSts3b_RESERVED_1" 3 "CtrlSts3b_ERROR" 2 "CtrlSts3b_CONTROL_REQUESTED" 1 "CtrlSts3b_CONTROL_NOT_REQUESTED" 0 "CtrlSts3b_INIT" ;
VAL_TABLE_ SteerActrReSts 7 "Diag" 6 "Inactive" 5 "Ramping" 4 "Yellow" 3 "Red" 2 "Normal" 1 "Pending" 0 "Initialisation" ;
VAL_TABLE_ SwtPark1 1 "SwtParkActv" 0 "SwtParkNotActv" ;
VAL_TABLE_ PE_State 2 "ERROR" 1 "INIT" 0 "NO_ERROR" ;
VAL_TABLE_ SSM_Req 7 "HMS_TAKEOVER" 6 "RESERVED" 5 "RELESE_VIA_RAMP" 4 "DRIVEOFF" 3 "HOLD_STANDBY" 2 "PARK" 1 "HOLD" 0 "NO_REQUEST" ;
VAL_TABLE_ IBC_StandStillMode 12 "SSM_ERROR" 11 "SSM_INIT" 10 "SSM_DRIVEOFF_STANDBY_ACTIVE" 9 "SSM_HOLD_STANDBY_ACTIVE" 8 "SSM_HILL_SLIPPOFF_DETECTED" 7 "SSM_RELEASE_REQ_FROM_DRIVER" 6 "SSM_RELEASE_REQ_ACTIVE" 5 "SSM_DRIVEOFF_ACTIVE" 4 "SSM_PARK_RETAINED_ACTIVE" 3 "SSM_PARK_ACTIVE" 2 "SSM_PARK_REQUESTED" 1 "SSM_HOLD_ACTIVE" 0 "SSM_NO_ACTIVE_FUNCTION" ;
VAL_TABLE_ AppTgtStDrv 3 "ACTIVE" 2 "READY" 1 "RESERVED" 0 "NOT_ACTIVE" ;
VAL_TABLE_ IBC_Status 4 "IBC_MAB_ERR_COMM" 3 "IBC_MAB_NO_PRIO" 2 "IBC_IN_MAB_MODE" 1 "IBC_READY" 0 "IBC_NOT_READY_FAILED" ;
VAL_TABLE_ GearLvrIndcn 7 "GearLvrIndcn2_Undefd" 6 "GearLvrIndcn2_Resd2" 5 "GearLvrIndcn2_Resd1" 4 "GearLvrIndcn2_ManModeIndcn" 3 "GearLvrIndcn2_DrvIndcn" 2 "GearLvrIndcn2_NeutIndcn" 1 "GearLvrIndcn2_RvsIndcn" 0 "GearLvrIndcn2_ParkIndcn" ;
VAL_TABLE_ LvlgAdjReq 7 "LvlgAdjReq_Resd2" 6 "LvlgAdjReq_Resd1" 5 "LvlgAdjReq_Ll2" 4 "LvlgAdjReq_Ll1" 3 "LvlgAdjReq_Nrh" 2 "LvlgAdjReq_Hl1" 1 "LvlgAdjReq_Hl2" 0 "LvlgAdjReq_Ukwn" ;
VAL_TABLE_ DrvModReq 15 "Err" 14 "Rock" 13 "Mud" 12 "Sand" 11 "Snow" 10 "Power" 9 "Hybrid" 8 "Pure_EV" 7 "Race" 6 "Adaptive" 5 "Offroad_CrossTerrain" 4 "Individual" 3 "Dynamic_Sport" 2 "Comfort_Normal" 1 "ECO" 0 "Undefd" ;
VAL_TABLE_ MAB_Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_TABLE_ MAB_OvrdTool_Sts 11 "HACKATHON" 10 "OTA" 9 "INIT" 8 "FINSHD" 7 "FLT" 6 "CUBIX_AD" 5 "SAVE_THE_SPOILER" 4 "LSDC" 3 "RDY" 2 "ACTVN_CHK" 1 "NO_MANIPULATION" 0 "NONE" ;
VAL_TABLE_ HMI_Drvr_Req 9 "FCT_DEACTVN_REQ" 8 "FCT_ACTVN_OTA_CFMD" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_CUBIXAD_CFMD" 1 "FCT_ACTVN_CUBIXAD_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_TABLE_ Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_TABLE_ HMI_Fct_Req 8 "FCT_DEACTVN_REQ" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_AI4MTN_CFMD" 1 "FCT_ACTVN_AI4MTN_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_TABLE_ SOVD_states 2 "SOVD_SHOWCASE_ACTIVE" 1 "SOVD_SHOWCASE_DEACTIVE" 0 "SOVD_NONE" ;
VAL_TABLE_ OTA_states 7 "OTA_DOWNLOAD_FAILED" 6 "OTA_INSTALL_FAILED" 5 "OTA_INSTALL_FINISHED" 4 "OTA_INSTALL_START" 3 "OTA_DOWNLOAD_START" 2 "OTA_SCHEDULED" 1 "OTA_STANDBY" 0 "OTA_NONE" ;
BO_ 21 Goldbox_Common: 1 ExampleNode
SG_ Goldbox_RollgCntr : 7|4@0+ (1,0) [0|15] "" Vector__XXX
BO_ 20 MAB_Internal_Info: 1 Vector__XXX
SG_ MAB_GPS_Map_ID : 7|4@0+ (1,0) [0|15] "" Vector__XXX
BO_ 257 MAB_Diagnosics_Response: 8 Vector__XXX
SG_ MAB_Diag_IBC_Response : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" Vector__XXX
BO_ 256 ProConnect_Diagnostics_Request: 8 Vector__XXX
SG_ ProConnect_Diag_IBC_Req : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" Vector__XXX
BO_ 19 ProConnect_GPS_Lat_Long: 8 Vector__XXX
SG_ ProConnect_GPS_PE_Long_LowAccry : 39|32@0+ (8.3819E-008,-180) [-180|179.999863699605] "deg" ExampleNode
SG_ ProConnect_GPS_PE_Lat_LowAccry : 7|32@0+ (4.19095E-008,-90) [-90|89.9999318498025] "deg" ExampleNode
BO_ 18 ProConnect_GPS_IMU_Status: 5 Vector__XXX
SG_ ProConnect_GPS_TimeStamp : 15|32@0+ (1,0) [0|4294967295] "" Vector__XXX
SG_ ProConnect_IMU_PE_State : 7|3@0+ (1,0) [0|7] "" ExampleNode
SG_ ProConnect_GPS_PE_State : 4|3@0+ (1,0) [0|7] "" ExampleNode
BO_ 17 Goldbox_Cubix_Ctrl_2: 3 ExampleNode
SG_ Goldbox_TestMapId : 23|8@0+ (1,0) [0|255] "" Vector__XXX
SG_ Goldbox_Freigabe_Radbremsmom : 8|1@0+ (1,0) [0|1] "bool" Vector__XXX
SG_ Goldbox_AccrPedlRatAccrPedlRat : 7|15@0+ (0.00390625,0) [0|127.99609375] "%" Vector__XXX
BO_ 16 MAB_CubixAD_Ctrl_2: 6 Vector__XXX
SG_ MAB_IBC_Status : 15|3@0+ (1,0) [0|7] "" ExampleNode
SG_ MAB_GearLvrIndc : 3|3@0+ (1,0) [0|7] "" ExampleNode
SG_ MAB_BrakeStandStillMode : 7|4@0+ (1,0) [0|15] "" ExampleNode
SG_ MAB_VehMNom : 39|14@0+ (1,0) [0|10000] "Kg" ExampleNode
SG_ MAB_DrvrGearShiftParkReq1 : 0|1@0+ (1,0) [0|1] "" ExampleNode
SG_ MAB_PinionSteerAgAct : 23|15@0- (0.0009765625,0) [-14.5|14.5] "rad" ExampleNode
BO_ 15 MAB_CubixAD_Ctrl_1: 6 Vector__XXX
SG_ MAB_f_cubiX_AD_Actvn : 24|1@0+ (1,0) [0|1] "bool" ExampleNode
SG_ MAB_SteerActReGroupAgAct : 39|10@0- (0.01,0) [-5.12|5.11] "Deg" ExampleNode
SG_ MAB_ADataRawSafeALat : 23|15@0- (0.0085,0) [-139.264|139.2555] "m/s^2" ExampleNode
SG_ MAB_AgDataRawSafeYawRate : 7|16@0- (0.000244140625,0) [-8|7.999755859375] "rad/s" ExampleNode
BO_ 14 ProConnect_PE_Angle: 8 Vector__XXX
SG_ ProConnect_GPS_PE_Yaw_Angle : 39|32@0+ (8.3819E-008,0) [0|359.999863699605] "deg" ExampleNode
SG_ ProConnect_GPS_PE_Course_Angle : 7|32@0+ (8.3819E-008,0) [0|359.999863699605] "deg" ExampleNode
BO_ 13 ProConnect_GPS_Long: 5 Vector__XXX
SG_ ProConnect_GPS_PE_Longitude : 7|40@0+ (3.27419E-010,-180) [-180|180.000997654463] "deg" ExampleNode
BO_ 12 ProConnect_GPS_Lat: 5 Vector__XXX
SG_ ProConnect_GPS_PE_Latitude : 7|40@0+ (1.6371E-010,-90) [-90|90.0010485830452] "deg" ExampleNode
BO_ 11 ProConnect_STS_Ctrl: 1 Vector__XXX
SG_ ProConnect_VehHeiTarReq : 2|3@0+ (1,0) [0|7] "Enum" Vector__XXX
SG_ ProConnect_STS_AliveCounter : 6|4@0+ (1,0) [0|15] "Unitless" Vector__XXX
SG_ ProConnect_f_VehInGeofence : 7|1@0+ (1,0) [0|1] "bool" Vector__XXX
BO_ 5 ProConnect_OTA_STS_Status: 1 Vector__XXX
SG_ ProConnect_OTA_Sts : 7|8@0+ (1,0) [0|255] "enum" Vector__XXX
BO_ 10 MAB_STS_Input: 6 Vector__XXX
SG_ MAB_WhlRotToothCntrReRi : 47|8@0+ (1,0) [0|255] "Unitless" Vector__XXX
SG_ MAB_WhlRotToothCntrReLe : 39|8@0+ (1,0) [0|255] "Unitless" Vector__XXX
SG_ MAB_WhlRotToothCntrFrntRi : 31|8@0+ (1,0) [0|255] "Unitless" Vector__XXX
SG_ MAB_WhlRotToothCntrFrntLe : 23|8@0+ (1,0) [0|255] "Unitless" Vector__XXX
SG_ MAB_VehBodyHei : 7|15@0- (6.2E-005,0) [-1.015808|1.015746] "m" Vector__XXX
SG_ MAB_f_STS_Actvn : 8|1@0+ (1,0) [0|1] "bool" Vector__XXX
BO_ 6 MAB_LSDC_PROP_Input: 8 Vector__XXX
SG_ MAB_BrkFricTqWhlReRiAct : 55|13@0+ (1,0) [0|8191] "Nm" ExampleNode
SG_ MAB_BrkFricTqWhlReLeAct : 39|13@0+ (1,0) [0|8191] "Nm" ExampleNode
SG_ MAB_BrkFricTqWhlFrntRiAct : 23|13@0+ (1,0) [0|8191] "Nm" ExampleNode
SG_ MAB_BrkFricTqWhlFrntLeAct : 7|13@0+ (1,0) [0|8191] "Nm" ExampleNode
BO_ 2 MAB_LSDC_Ctrl: 1 Vector__XXX
SG_ MAB_f_LSDC_Actvn : 7|1@0+ (1,0) [0|1] "bool" ExampleNode
BO_ 0 MAB_LSDC_CAN_Input: 8 Vector__XXX
SG_ MAB_VehSpdLgtA : 55|15@0+ (0.00391,0) [0|128.11897] "m/s" ExampleNode
SG_ MAB_SteerWhlSnsrAg : 39|15@0- (0.0009765625,0) [-16|15.9990234375] "rad" ExampleNode
SG_ MAB_f_VehSpd_RvsDetd : 24|1@0+ (1,0) [0|1] "bool" ExampleNode
SG_ MAB_DrvModReq : 15|8@0+ (1,0) [0|255] "" ExampleNode
SG_ MAB_ADataRawSafeALgt : 23|15@0- (0.0085,0) [-139.264|139.2555] "m/s^2" ExampleNode
SG_ MAB_act_wheel_angle_front : 7|8@0- (0.00781,0) [-0.99968|0.99187] "rad" ExampleNode
BO_ 7 MAB_HMI_Feedback_2: 8 Vector__XXX
SG_ MAB_FourCornrReq_Act : 45|3@0+ (1,0) [0|7] "Enum" Vector__XXX
SG_ MAB_Veh_A : 15|8@0- (0.2,0) [-25.6|25.4] "m/s^2" Vector__XXX
SG_ MAB_SteerWhlAg_Deg : 23|11@0- (1,0) [-1024|1023] "deg" Vector__XXX
SG_ MAB_ReSteerAgAct : 55|10@0- (0.01,0) [-5.12|5.11] "deg" Vector__XXX
SG_ MAB_Goldbox_Alive : 25|1@0+ (1,0) [0|1] "bool" Vector__XXX
SG_ MAB_CurSpd_kmph : 7|8@0+ (1,0) [0|255] "kmph" Vector__XXX
SG_ MAB_AliveCounter : 28|3@0+ (1,0) [0|7] "" Vector__XXX
SG_ MAB_act_wheel_angle_front_deg : 39|10@0- (0.2,0) [-102.4|102.2] "deg" Vector__XXX
BO_ 4 MAB_HMI_Feedback_1: 4 Vector__XXX
SG_ voltage_AccrPedl_Out : 31|8@0+ (1,0) [0|255] "" Vector__XXX
SG_ MAB_OvrdTool_Sts : 3|4@0+ (1,0) [0|15] "" Vector__XXX
SG_ MAB_Info_Message : 7|4@0+ (1,0) [0|15] "" Vector__XXX
SG_ MAB_Global_activation_status : 15|6@0+ (1,0) [0|63] "bit coded" Vector__XXX
SG_ MAB_Fault_codes : 23|5@0+ (1,0) [0|31] "" Vector__XXX
BO_ 9 MAB_CubixAD_Ctrl_3: 6 Vector__XXX
SG_ MAB_SteerActReGroupSts : 43|3@0+ (1,0) [0|7] "" Vector__XXX
SG_ MAB_IsgTqAct800ActuTq : 39|12@0+ (5,-10235) [-10235|10240] "Nm" ExampleNode
SG_ MAB_WhlMotSysTqEst800Tq2Act : 23|14@0+ (1,-8191) [-8191|8192] "Nm" ExampleNode
SG_ MAB_VehMtnSt : 8|1@0+ (1,0) [0|1] "bool" ExampleNode
SG_ MAB_BrkFricTqTotAtWhlsAct : 7|15@0+ (1,0) [0|20000] "Nm" ExampleNode
BO_ 1 HMI_Requests: 2 Vector__XXX
SG_ HMI_f_ReSteerCtrlActvnReq : 15|1@0+ (1,0) [0|1] "bool" Vector__XXX
SG_ HMI_Drvr_Req : 7|8@0+ (1,0) [0|255] "enum" Vector__XXX
BO_ 3 Goldbox_LSDC_Ctrl: 3 ExampleNode
SG_ Goldbox_SteerReCtrlReqSts : 23|3@0+ (1,0) [0|7] "" Vector__XXX
SG_ Goldbox_SteerReCtrlReqAgReq : 7|10@0- (0.01,0) [-5.12|5.11] "deg" Vector__XXX
SG_ Goldbox_LSDC_RollgCntr : 13|4@0+ (1,0) [0|15] "" Vector__XXX
BO_ 8 Goldbox_Cubix_Ctrl_1: 7 ExampleNode
SG_ Goldbox_DriveStateReq : 55|2@0+ (1,0) [0|3] "" Vector__XXX
SG_ Goldbox_SteerStateReq : 42|3@0+ (1,0) [0|7] "" Vector__XXX
SG_ Goldbox_SSM_Req : 45|3@0+ (1,0) [0|7] "" Vector__XXX
SG_ Goldbox_Verz_Anf : 39|10@0+ (0.024,-20.016) [-20.016|4.536] "m/s^2" Vector__XXX
SG_ Goldbox_Radbremsmom : 23|12@0+ (8,0) [0|32760] "Nm" Vector__XXX
SG_ Goldbox_Verz_freigabe : 8|1@0+ (1,0) [0|1] "" Vector__XXX
SG_ Goldbox_SteerWhlAgReq : 7|15@0- (0.0009765625,0) [-14.5|14.5] "rad" Vector__XXX
SG_ Goldbox_Cubix_RollgCntr : 27|4@0+ (1,0) [0|15] "" Vector__XXX
CM_ SG_ 21 Goldbox_RollgCntr "A similar counter will be existing in MAB, Each cycle will the counter number be compared with the value from Goldbox. When these numbers have a deviation of more than 3, the MAB will switch to the series mode.";
CM_ BO_ 20 "Internal signals for measurement and debugging";
CM_ SG_ 257 MAB_Diag_IBC_Response "Response of IBC regarding diagnosis request read from Chassis can 1 ";
CM_ SG_ 256 ProConnect_Diag_IBC_Req "Diagnosis request sent by ProConnect to MAB. MAB forwards it to IBC on chassis Can 1";
CM_ SG_ 19 ProConnect_GPS_PE_Long_LowAccry "ProConnect GPS longitude signal with less accuracy. Instead of 40 bit is 32 bit. The accuracy will be in the 1-2 cm range.";
CM_ SG_ 19 ProConnect_GPS_PE_Lat_LowAccry "ProConnect GPS lateral signal with less accuracy. Instead of 40 bit is 32 bit. The accuracy will be in the 1-2 cm range.";
CM_ SG_ 17 Goldbox_TestMapId "Identifier CubixAD test map. ";
CM_ SG_ 16 MAB_VehMNom "Estimated vehicle mass including trailer. Vehicle mass including trailer mass (if connected).";
CM_ SG_ 16 MAB_DrvrGearShiftParkReq1 "Driver park request from gear shifter. Valid for Shift-By-Wire system.";
CM_ SG_ 15 MAB_SteerActReGroupAgAct "AgAct (Actual angle at Rear axle)";
CM_ SG_ 11 ProConnect_STS_AliveCounter "Save the spoiler alive rolling counter (0 -14 )";
CM_ SG_ 11 ProConnect_f_VehInGeofence "Is vehicle in geofence area";
CM_ SG_ 5 ProConnect_OTA_Sts "Current status of the ProConnect. ";
CM_ SG_ 10 MAB_WhlRotToothCntrReRi "Wheel rotation ticks for each individual wheel. Wheel rotation impuls counter rear right. For one complete wheel revolution the counter will increase by 96 (with 48 magnetic pole-pairs).";
CM_ SG_ 10 MAB_WhlRotToothCntrReLe "Wheel rotation ticks for each individual wheel. Wheel rotation impuls counter rear left. For one complete wheel revolution the counter will increase by 96 (with 48 magnetic pole-pairs).";
CM_ SG_ 10 MAB_WhlRotToothCntrFrntRi "Wheel rotation ticks for each individual wheel. Wheel rotation impuls counter front right. For one complete wheel revolution the counter will increase by 96 (with 48 magnetic pole-pairs).";
CM_ SG_ 10 MAB_WhlRotToothCntrFrntLe "Wheel rotation ticks for each individual wheel. Wheel rotation impuls counter front left. For one complete wheel revolution the counter will increase by 96 (with 48 magnetic pole-pairs).";
CM_ SG_ 10 MAB_VehBodyHei "Signal forwareded from vehicle to ProConnect regarding Vehicle body height. Vehicle signal on Chassis CAN 2 is BodyHei. ";
CM_ SG_ 10 MAB_f_STS_Actvn "Activation and deactivation flag from MAB to ProConnect regarding the activation and deactivation of save the spoiler";
CM_ SG_ 6 MAB_BrkFricTqWhlReRiAct "Actual service brake torque. Brake torque acting on the rear right wheel.
Based on nominal brake parameters (e.g. constant pads friction) and (estimated) brake pressures (clamp forces). Not incl.: parking brake torque or regenerative brake torque.";
CM_ SG_ 6 MAB_BrkFricTqWhlReLeAct "Actual service brake torque. Brake torque acting on the rear left wheel.
Based on nominal brake parameters (e.g. constant pads friction) and (estimated) brake pressures (clamp forces). Not incl.: parking brake torque or regenerative brake torque.";
CM_ SG_ 6 MAB_BrkFricTqWhlFrntRiAct "Actual service brake torque. Brake torque acting on the front right wheel.
Based on nominal brake parameters (e.g. constant pads friction) and (estimated) brake pressures (clamp forces). Not incl.: parking brake torque or regenerative brake torque.";
CM_ SG_ 6 MAB_BrkFricTqWhlFrntLeAct "Actual service brake torque. Brake torque acting on the front left wheel.
Based on nominal brake parameters (e.g. constant pads friction) and (estimated) brake pressures (clamp forces). Not incl.: parking brake torque or regenerative brake torque.";
CM_ SG_ 2 MAB_f_LSDC_Actvn "This flag will be send via MAB in the ready state.This state is one step, before fully handover to the algorithm. It can be used to reset the rolling counter as well. ";
CM_ SG_ 0 MAB_VehSpdLgtA "Vehicle speed longitudinal based on wheel speed sensors and longitudinal acceleration.";
CM_ SG_ 0 MAB_SteerWhlSnsrAg "Actual steering wheel angle from the actual centre position of the steering wheel. ";
CM_ SG_ 0 MAB_f_VehSpd_RvsDetd "VehicleVelocity.ReverseDetected. This signal should still be clarified, whether is needed or not?";
CM_ SG_ 0 MAB_DrvModReq "driving mode request. This signal can be read on the CAN 1 and CAN 2 with different frame cyclicity. ";
CM_ SG_ 0 MAB_ADataRawSafeALgt "Longitudinal acceleration over ground.
end2endprotection=profile1A dataid= 12345 Longitudinal acceleration over ground";
CM_ SG_ 0 MAB_act_wheel_angle_front "This signal is calculated by multiplying steering gear ratio with MAB_SteerWhlSnsrAg";
CM_ SG_ 7 MAB_FourCornrReq_Act "Actual request of vehicle height adjustment from ProConnect during Save the spoiler";
CM_ SG_ 7 MAB_Veh_A "vehicle acceleration OR deceleration ";
CM_ SG_ 7 MAB_SteerWhlAg_Deg "actual steering wheel angle in degree";
CM_ SG_ 7 MAB_ReSteerAgAct "Actual rear wheel steering angle in degree";
CM_ SG_ 7 MAB_Goldbox_Alive "Status of Goldbox (alive or not)";
CM_ SG_ 7 MAB_act_wheel_angle_front_deg "actua frontl wheel angle in degree";
CM_ SG_ 4 MAB_OvrdTool_Sts "Current state of the MAB stateflow. ";
CM_ SG_ 4 MAB_Info_Message "This signal can be used to show any messages to the safety driver. ";
CM_ SG_ 4 MAB_Global_activation_status "Bit coded signal. Set true to below conditions. Value is 31 if all conditions true
0 --> All Door closed
1 --> Driver seat belt fastened
2 --> AD main switch on
3 --> Driver seat occupied ";
CM_ SG_ 4 MAB_Fault_codes "0 = NONE,1 = Glb Actvn Cdn Failed,2 = Emergency Button,3 = Drvr Intv Detd,4 = MAB Watchdog Err Detd,5 = GoldBox Cntr Err Detd,6 = Spd Lim Excdd,7 = Acc Lim Excdd,8 = IBC not in Manip Mod,9 = Steer Grdt Excdd,10 = Phy Lim Excdd,11 = Re Steer Grdt Excdd
";
CM_ SG_ 9 MAB_IsgTqAct800ActuTq "Actual Torque (at Front Motor)";
CM_ SG_ 9 MAB_WhlMotSysTqEst800Tq2Act "Actual Torque (at Rear Motor)";
CM_ SG_ 9 MAB_VehMtnSt "Vehicle motion state information based on wheel speed sensors. Provides information about vehicle stand still and vehicle rolling direction. Vehicle motion state;";
CM_ SG_ 9 MAB_BrkFricTqTotAtWhlsAct "Total actual friction brake toque at all four wheels.";
CM_ SG_ 1 HMI_f_ReSteerCtrlActvnReq "LSDC: flag for rear steering control enabled or disabled.";
CM_ SG_ 1 HMI_Drvr_Req "HMI sends the driver request and his confirmation. ";
CM_ SG_ 3 Goldbox_SteerReCtrlReqSts "Control bits for angle request, corporate with steer angle request and Qf to realize rear axle angle control.
SteerReCtrlReqSteerReCtrlSts";
CM_ SG_ 3 Goldbox_SteerReCtrlReqAgReq "Rear Steering angle request";
CM_ SG_ 3 Goldbox_LSDC_RollgCntr "A similar counter will be existing in MAB, Each cycle will the counter number be compared with the value from Goldbox. When these numbers have a deviation of more than 3, the MAB will switch to the series mode.";
CM_ SG_ 8 Goldbox_SteerWhlAgReq "steering wheel angle from the actual centre position of the steering wheel requested from Cubix AD application on Goldbox ";
CM_ SG_ 8 Goldbox_Cubix_RollgCntr "A similar counter will be existing in MAB, Each cycle will the counter number be compared with the value from Goldbox. When these numbers have a deviation of more than 3, the MAB will switch to the series mode.";
BA_DEF_ "Baudrate" INT 1000 1000000;
BA_DEF_ "BusType" STRING ;
BA_DEF_ "DBName" STRING ;
BA_DEF_ "ProtocolType" STRING ;
BA_DEF_ BU_ "NmAsrNode" ENUM "No","Yes";
BA_DEF_ BU_ "NmAsrNodeIdentifier" INT 0 255;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65536;
BA_DEF_ BO_ "GenMsgCycleTimeFast" FLOAT 0 300000;
BA_DEF_ BO_ "GenMsgDelayTime" INT 0 65536;
BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100000;
BA_DEF_ BO_ "GenMsgSendType" ENUM "cyclic","spontaneous","not-used","not-used","not-used","cyclicAndSpontaneous","not-used","cyclicIfActive","NoMsgSendType";
BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 65536;
BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType";
BA_DEF_ SG_ "GenSigStartValue" HEX 0 80000000;
BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes";
BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes";
BA_DEF_ "NmAsrBaseAddress" HEX 0 536870911;
BA_DEF_ "NmAsrMessageCount" INT 0 255;
BA_DEF_ BU_ "NodeLayerModules" STRING ;
BA_DEF_ BU_ "ILused" ENUM "No","Yes";
BA_DEF_ SG_ "GenSigFuncType" ENUM "NoFunction","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","CHK","CNTR","n/a","n/a","n/a","CNTR_AR_01","CRC_AR_01_BOTH","CRC_AR_01_ALT","CRC_AR_01_LOW","CRC_AR_01_NIBBLE","CNTR_AR_04","CRC_AR_04A","CNTR_AR_05","CRC_AR_05";
BA_DEF_ SG_ "GenSigDataID" STRING ;
BA_DEF_ SG_ "SigGroup" STRING ;
BA_DEF_DEF_ "Baudrate" 1000;
BA_DEF_DEF_ "BusType" "";
BA_DEF_DEF_ "DBName" "";
BA_DEF_DEF_ "ProtocolType" "";
BA_DEF_DEF_ "NmAsrNode" "No";
BA_DEF_DEF_ "NmAsrNodeIdentifier" 0;
BA_DEF_DEF_ "GenMsgCycleTime" 0;
BA_DEF_DEF_ "GenMsgCycleTimeFast" 0;
BA_DEF_DEF_ "GenMsgDelayTime" 0;
BA_DEF_DEF_ "GenMsgNrOfRepetition" 0;
BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType";
BA_DEF_DEF_ "GenMsgStartDelayTime" 0;
BA_DEF_DEF_ "GenSigSendType" "NoSigSendType";
BA_DEF_DEF_ "GenSigStartValue" 0;
BA_DEF_DEF_ "GenMsgILSupport" "Yes";
BA_DEF_DEF_ "NmAsrMessage" "No";
BA_DEF_DEF_ "NmAsrBaseAddress" 1280;
BA_DEF_DEF_ "NmAsrMessageCount" 64;
BA_DEF_DEF_ "NodeLayerModules" "CANoeILNLSPA.dll";
BA_DEF_DEF_ "ILused" "Yes";
BA_DEF_DEF_ "GenSigFuncType" "NoFunction";
BA_DEF_DEF_ "GenSigDataID" "";
BA_DEF_DEF_ "SigGroup" "";
BA_ "Baudrate" 500000;
BA_ "BusType" "CAN";
BA_ "ProtocolType" "CAN";
BA_ "DBName" "example_can";
BA_ "GenMsgSendType" BO_ 21 0;
BA_ "GenMsgCycleTime" BO_ 21 10;
BA_ "GenMsgCycleTime" BO_ 20 10;
BA_ "GenMsgSendType" BO_ 20 0;
BA_ "GenMsgSendType" BO_ 257 1;
BA_ "GenMsgDelayTime" BO_ 257 5;
BA_ "GenMsgSendType" BO_ 256 1;
BA_ "GenMsgDelayTime" BO_ 256 5;
BA_ "GenMsgSendType" BO_ 19 0;
BA_ "GenMsgCycleTime" BO_ 19 10;
BA_ "GenMsgSendType" BO_ 18 0;
BA_ "GenMsgCycleTime" BO_ 18 10;
BA_ "GenMsgCycleTime" BO_ 17 10;
BA_ "GenMsgSendType" BO_ 17 0;
BA_ "GenMsgCycleTime" BO_ 16 10;
BA_ "GenMsgSendType" BO_ 16 0;
BA_ "GenMsgSendType" BO_ 15 0;
BA_ "GenMsgCycleTime" BO_ 15 10;
BA_ "GenMsgSendType" BO_ 14 0;
BA_ "GenMsgCycleTime" BO_ 14 10;
BA_ "GenMsgSendType" BO_ 13 0;
BA_ "GenMsgCycleTime" BO_ 13 10;
BA_ "GenMsgSendType" BO_ 12 0;
BA_ "GenMsgCycleTime" BO_ 12 10;
BA_ "GenMsgSendType" BO_ 11 0;
BA_ "GenMsgCycleTime" BO_ 11 10;
BA_ "GenMsgCycleTime" BO_ 5 10;
BA_ "GenMsgSendType" BO_ 5 0;
BA_ "GenMsgCycleTime" BO_ 10 10;
BA_ "GenMsgSendType" BO_ 10 0;
BA_ "GenMsgCycleTime" BO_ 6 10;
BA_ "GenMsgSendType" BO_ 6 0;
BA_ "GenMsgCycleTime" BO_ 2 10;
BA_ "GenMsgSendType" BO_ 2 0;
BA_ "GenMsgCycleTime" BO_ 0 10;
BA_ "GenMsgSendType" BO_ 0 0;
BA_ "GenMsgCycleTime" BO_ 7 10;
BA_ "GenMsgSendType" BO_ 7 0;
BA_ "GenMsgCycleTime" BO_ 4 10;
BA_ "GenMsgSendType" BO_ 4 0;
BA_ "GenMsgCycleTime" BO_ 9 10;
BA_ "GenMsgSendType" BO_ 9 0;
BA_ "GenMsgCycleTime" BO_ 1 10;
BA_ "GenMsgSendType" BO_ 1 0;
BA_ "GenMsgCycleTime" BO_ 3 10;
BA_ "GenMsgSendType" BO_ 3 0;
BA_ "GenMsgCycleTime" BO_ 8 10;
BA_ "GenMsgSendType" BO_ 8 0;
BA_ "GenSigStartValue" SG_ 19 ProConnect_GPS_PE_Long_LowAccry 0;
BA_ "GenSigStartValue" SG_ 19 ProConnect_GPS_PE_Lat_LowAccry 0;
BA_ "GenSigStartValue" SG_ 13 ProConnect_GPS_PE_Longitude 0;
BA_ "GenSigStartValue" SG_ 12 ProConnect_GPS_PE_Latitude 0;
BA_ "GenSigStartValue" SG_ 9 MAB_IsgTqAct800ActuTq 2047;
BA_ "GenSigStartValue" SG_ 9 MAB_WhlMotSysTqEst800Tq2Act 8191;
BA_ "GenSigStartValue" SG_ 8 Goldbox_Verz_Anf 834;
VAL_ 20 MAB_GPS_Map_ID 6 "E_TESTMAPID_UNDEFINED" 5 "E_TESTMAPID_TEST_DRIVE" 4 "E_TESTMAPID_AD_AREA" 3 "E_TESTMAPID_STUTT_ARENA" 2 "E_TESTMAPID_ZF_LASTMILE" 1 "E_TESTMAPID_ZF_TESTTRACK_2" 0 "E_TESTMAPID_NONE" ;
VAL_ 18 ProConnect_IMU_PE_State 2 "ERROR" 1 "INIT" 0 "NO_ERROR" ;
VAL_ 18 ProConnect_GPS_PE_State 2 "ERROR" 1 "INIT" 0 "NO_ERROR" ;
VAL_ 17 Goldbox_TestMapId 6 "E_TESTMAPID_UNDEFINED" 5 "E_TESTMAPID_TEST_DRIVE" 4 "E_TESTMAPID_AD_AREA" 3 "E_TESTMAPID_STUTT_ARENA" 2 "E_TESTMAPID_ZF_LASTMILE" 1 "E_TESTMAPID_ZF_TESTTRACK_2" 0 "E_TESTMAPID_NONE" ;
VAL_ 16 MAB_IBC_Status 4 "IBC_MAB_ERR_COMM" 3 "IBC_MAB_NO_PRIO" 2 "IBC_IN_MAB_MODE" 1 "IBC_READY" 0 "IBC_NOT_READY_FAILED" ;
VAL_ 16 MAB_GearLvrIndc 7 "GearLvrIndcn2_Undefd" 6 "GearLvrIndcn2_Resd2" 5 "GearLvrIndcn2_Resd1" 4 "GearLvrIndcn2_ManModeIndcn" 3 "GearLvrIndcn2_DrvIndcn" 2 "GearLvrIndcn2_NeutIndcn" 1 "GearLvrIndcn2_RvsIndcn" 0 "GearLvrIndcn2_ParkIndcn" ;
VAL_ 16 MAB_BrakeStandStillMode 12 "SSM_ERROR" 11 "SSM_INIT" 10 "SSM_DRIVEOFF_STANDBY_ACTIVE" 9 "SSM_HOLD_STANDBY_ACTIVE" 8 "SSM_HILL_SLIPPOFF_DETECTED" 7 "SSM_RELEASE_REQ_FROM_DRIVER" 6 "SSM_RELEASE_REQ_ACTIVE" 5 "SSM_DRIVEOFF_ACTIVE" 4 "SSM_PARK_RETAINED_ACTIVE" 3 "SSM_PARK_ACTIVE" 2 "SSM_PARK_REQUESTED" 1 "SSM_HOLD_ACTIVE" 0 "SSM_NO_ACTIVE_FUNCTION" ;
VAL_ 16 MAB_DrvrGearShiftParkReq1 1 "SwtParkActv" 0 "SwtParkNotActv" ;
VAL_ 11 ProConnect_VehHeiTarReq 7 "LvlgAdjReq_Resd2" 6 "LvlgAdjReq_Resd1" 5 "LvlgAdjReq_Ll2" 4 "LvlgAdjReq_Ll1" 3 "LvlgAdjReq_Nrh" 2 "LvlgAdjReq_Hl1" 1 "LvlgAdjReq_Hl2" 0 "LvlgAdjReq_Ukwn" ;
VAL_ 5 ProConnect_OTA_Sts 7 "OTA_DOWNLOAD_FAILED" 6 "OTA_INSTALL_FAILED" 5 "OTA_INSTALL_FINISHED" 4 "OTA_INSTALL_START" 3 "OTA_DOWNLOAD_START" 2 "OTA_SCHEDULED" 1 "OTA_STANDBY" 0 "OTA_NONE" ;
VAL_ 0 MAB_DrvModReq 15 "Err" 14 "Rock" 13 "Mud" 12 "Sand" 11 "Snow" 10 "Power" 9 "Hybrid" 8 "Pure_EV" 7 "Race" 6 "Adaptive" 5 "Offroad_CrossTerrain" 4 "Individual" 3 "Dynamic_Sport" 2 "Comfort_Normal" 1 "ECO" 0 "Undefd" ;
VAL_ 7 MAB_FourCornrReq_Act 7 "LvlgAdjReq_Resd2" 6 "LvlgAdjReq_Resd1" 5 "LvlgAdjReq_Ll2" 4 "LvlgAdjReq_Ll1" 3 "LvlgAdjReq_Nrh" 2 "LvlgAdjReq_Hl1" 1 "LvlgAdjReq_Hl2" 0 "LvlgAdjReq_Ukwn" ;
VAL_ 4 MAB_OvrdTool_Sts 11 "HACKATHON" 10 "OTA" 9 "INIT" 8 "FINSHD" 7 "FLT" 6 "CUBIX_AD" 5 "SAVE_THE_SPOILER" 4 "LSDC" 3 "RDY" 2 "ACTVN_CHK" 1 "NO_MANIPULATION" 0 "NONE" ;
VAL_ 4 MAB_Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_ 4 MAB_Fault_codes 27 "UKWN" 26 "VEHSPDMAX_EXDD" 25 "STS_ALIVE" 24 "STEER_NOT_E2E_MODE" 23 "OTA_SPD" 22 "OTA_TIMER_DOWNLOAD_FAILED" 21 "OTA_MAX_TIME" 20 "CUBIXAD_STEERSTREQ_NOTACTV" 19 "CUBIXAD_DRVSTREQ_NOTACTV" 18 "SFTYDRV_INTV" 17 "LSDC_ALIVE" 16 "CUBIXAD_ALIVE" 15 "IBC_MAB_NO_PRIO" 14 "IBC_NOT_RDY" 13 "IBC_ALIVE" 12 "LSDC_GEAR" 11 "LSDC_SPD" 10 "LSDC_ACCL" 9 "IBC_NOT_MAB_MOD" 8 "GOLDBOX_ALIVE" 7 "CUBIXAD_GEAR" 6 "CUBIXAD_SPD_TESTTRACK" 5 "DRVREQCHG" 4 "RDY_TIMER" 3 "SFTY_CDN_FAILED" 2 "ACTVNCHK_SPD" 1 "ACTVNCHK_TIMR" 0 "NONE" ;
VAL_ 9 MAB_SteerActReGroupSts 7 "Diag" 6 "Inactive" 5 "Ramping" 4 "Yellow" 3 "Red" 2 "Normal" 1 "Pending" 0 "Initialisation" ;
VAL_ 1 HMI_Drvr_Req 9 "FCT_DEACTVN_REQ" 8 "FCT_ACTVN_OTA_CFMD" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_CUBIXAD_CFMD" 1 "FCT_ACTVN_CUBIXAD_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_ 3 Goldbox_SteerReCtrlReqSts 7 "CtrlSts3b_RESERVED_4" 6 "CtrlSts3b_RESERVED_3" 5 "CtrlSts3b_RESERVED_2" 4 "CtrlSts3b_RESERVED_1" 3 "CtrlSts3b_ERROR" 2 "CtrlSts3b_CONTROL_REQUESTED" 1 "CtrlSts3b_CONTROL_NOT_REQUESTED" 0 "CtrlSts3b_INIT" ;
VAL_ 8 Goldbox_DriveStateReq 3 "ACTIVE" 2 "READY" 1 "RESERVED" 0 "NOT_ACTIVE" ;
VAL_ 8 Goldbox_SteerStateReq 3 "ACTIVE" 2 "READY" 1 "RESERVED" 0 "NOT_ACTIVE" ;
VAL_ 8 Goldbox_SSM_Req 7 "HMS_TAKEOVER" 6 "RESERVED" 5 "RELESE_VIA_RAMP" 4 "DRIVEOFF" 3 "HOLD_STANDBY" 2 "PARK" 1 "HOLD" 0 "NO_REQUEST" ;

View File

@@ -0,0 +1,17 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
Source="asc_reader_test.asc"
Target="asc_writer_test.asc"

View File

@@ -0,0 +1,16 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
Source="receiver_test.asc"

View File

@@ -0,0 +1,15 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
Target="transmitter_test.asc"

View File

@@ -0,0 +1,53 @@
project(LoggerTests)
set(CMAKE_CXX_STANDARD 17)
# Define target
add_library(ComponentTest_Logger_Module SHARED "logger_test_service.h" "logger_test_service.cpp")
target_link_options(ComponentTest_Logger_Module PRIVATE)
target_include_directories(ComponentTest_Logger_Module PRIVATE ./include)
if (WIN32)
target_link_libraries(ComponentTest_Logger_Module Ws2_32 Winmm)
else()
target_link_libraries(ComponentTest_Logger_Module)
endif()
set_target_properties(ComponentTest_Logger_Module PROPERTIES PREFIX "")
set_target_properties(ComponentTest_Logger_Module PROPERTIES SUFFIX ".sdv")
# Logger
add_executable(ComponentTest_Logger
"logger_test.cpp"
)
target_include_directories(ComponentTest_Logger PRIVATE
${GTEST_INCLUDE_DIRS}
)
target_link_libraries(ComponentTest_Logger
GTest::GTest
#pthread
#stdc++fs
${CMAKE_DL_LIBS}
)
add_test(NAME ComponentTest_Logger COMMAND ComponentTest_Logger)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (WIN32)
target_link_libraries(ComponentTest_Logger Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_Logger rt)
endif()
else()
target_link_libraries(ComponentTest_Logger Rpcrt4.lib)
endif()
add_custom_command(TARGET ComponentTest_Logger POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_Logger>" ${GTEST_ARGUMENTS}ComponentTest_Logger.xml
VERBATIM
)
file (COPY ${PROJECT_SOURCE_DIR}/config/test_logger_userconfig.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)
add_dependencies(ComponentTest_Logger_Module dependency_sdv_components)
add_dependencies(ComponentTest_Logger ComponentTest_Logger_Module)

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "ComponentTest_Logger_Module.sdv"
Class = "LoggerTestService"

View File

@@ -0,0 +1,60 @@
#include <gtest/gtest.h>
#include <iostream>
#include <support/sdv_core.h>
#include <support/local_service_access.h>
#include <support/app_control.h>
#include "../../../global/process_watchdog.h"
#include "../../include/logger_test_helper.h"
#ifdef _MSC_VER
#include <process.h>
#elif defined __GNUC__
#include <unistd.h>
#endif
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
TEST(AppLoggerTest, CallbackMultiThread)
{
std::string prefix = "PA_LoggerTest_";
auto startCount = GetLoggerFilesCount(prefix);
{
SDV_LOG(sdv::core::ELogSeverity::warning, "Warning: trying to log before instantiation!");
sdv::app::CAppControl appcontrol;
std::stringstream sstreamAppConfig;
sstreamAppConfig << "[LogHandler]" << std::endl << "Tag=\"" << prefix << getpid() << "\"";
bool bResult = appcontrol.Startup(sstreamAppConfig.str());
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
SDV_LOG(sdv::core::ELogSeverity::warning, "Warning: trying to log before initialization!");
std::cout << "Logger test: Initialize Log" << std::endl;
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_logger_userconfig.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
appcontrol.SetRunningMode();
}
auto endCount = GetLoggerFilesCount(prefix);
#if defined(_WIN32)
EXPECT_TRUE(endCount > startCount);
#else
// just avoid unused variable warning
std::cout << "start:" << std::to_string(startCount) << " end:" << std::to_string(endCount) << std::endl;
#endif
}

View File

@@ -0,0 +1,11 @@
#include "logger_test_service.h"
CLoggerTestService::CLoggerTestService()
{
// auto test = sdv::core::GetObject("DataDispatchService");
// auto foo = test.GetInterface<sdv::core::IDataDispatchService>();
// foo->HasSignal(0);
SDV_LOG(sdv::core::ELogSeverity::info, "Info: Logging from Dummy test service via macro!");
}

View File

@@ -0,0 +1,23 @@
#ifndef VAPI_DUMMY_TEST_SERVICE_H
#define VAPI_DUMMY_TEST_SERVICE_H
#include <support/component_impl.h>
/**
* @brief Class to create a dummy test service.
*/
class CLoggerTestService
: public sdv::CSdvObject
{
public:
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("LoggerTestService")
CLoggerTestService();
};
DEFINE_SDV_OBJECT(CLoggerTestService)
#endif // !define VAPI_DUMMY_TEST_SERVICE_H

View File

@@ -0,0 +1,77 @@
# Define project
project(RepositoryTests VERSION 1.0 LANGUAGES CXX)
# Find the IDL compiler
# REMARKS The compiler can only be found after it has build. Having both the compiler and the unittest project build, causes an
# error during the scanning phase of CMake.
#find_program(SDVIDL NAMES "sdv_idl_compiler" PATHS "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../../bin/" NO_CACHE)
set (SDVIDL "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../../bin/sdv_idl_compiler")
message("Use IDL compiler: ${SDVIDL}")
# Compile the IDL
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/generated/test_component.h
DEPENDS sdv_idl_compiler
MAIN_DEPENDENCY test_component.idl
COMMENT "Build test_component.idl"
COMMAND ${SDVIDL} "${PROJECT_SOURCE_DIR}/test_component.idl" "-I${PROJECT_SOURCE_DIR}/../../../export" "-O${PROJECT_SOURCE_DIR}/generated"
VERBATIM
)
set_source_files_properties(test_component_ps.cpp OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/generated/test_component.h)
set_source_files_properties(test_component.cpp OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/generated/test_component.h)
# Add the dynamic library
add_library(ComponentTest_Repository_ps SHARED
"test_component_ps.cpp"
)
# Set extension to .sdv
set_target_properties(ComponentTest_Repository_ps PROPERTIES PREFIX "")
set_target_properties(ComponentTest_Repository_ps PROPERTIES SUFFIX ".sdv")
# build module example for the test
add_library(ComponentTest_Repository_test_module SHARED
test_component.cpp
)
target_link_libraries(ComponentTest_Repository_test_module ${CMAKE_DL_LIBS} GTest::GTest)
set_target_properties(ComponentTest_Repository_test_module PROPERTIES PREFIX "")
set_target_properties(ComponentTest_Repository_test_module PROPERTIES SUFFIX ".sdv")
# Execute the installation helper utility to create an installation manifest for the core files.
add_custom_target(ComponentTest_Repository_install_manifest
# TODO EVE
# COMMAND "$<TARGET_FILE:sdv_packager>" -O. --instance2005 -NComponentTest_Repository "$<TARGET_FILE:ComponentTest_Repository_test_module>" "$<TARGET_FILE:ComponentTest_Repository_ps>" "-I$<TARGET_FILE_DIR:ComponentTest_Repository_test_module>" --settings --create_configtest.toml --exclude_config_class"TestObject_CreateChain" --exclude_config_class"TestObject_CreateChainLock" --exclude_config_class"TestObject_CreateChainLockThread" --exclude_config_class"TestObject_CreateDuringShutdown" --exclude_config_class"TestObject_IObjectControlFail"
COMMAND "$<TARGET_FILE:sdv_packager>" DIRECT_INSTALL ComponentTest_Repository --instance2005 "$<TARGET_FILE:ComponentTest_Repository_test_module>" "$<TARGET_FILE:ComponentTest_Repository_ps>" "-I$<TARGET_FILE_DIR:ComponentTest_Repository_test_module>" --overwrite --user_config
DEPENDS ComponentTest_Repository_test_module ComponentTest_Repository_ps
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
# Define target
add_executable(ComponentTest_Repository
"repository_test.cpp"
"isolation_test.cpp"
)
target_link_libraries(ComponentTest_Repository ${CMAKE_DL_LIBS} GTest::GTest)
# Add the test
add_test(NAME ComponentTest_Repository COMMAND ComponentTest_Repository WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
add_custom_command(TARGET ComponentTest_Repository POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_Repository>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_Repository.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_Repository_test_module install_manifest)
add_dependencies(ComponentTest_Repository_test_module dependency_sdv_components)
add_dependencies(ComponentTest_Repository dependency_sdv_components)
add_dependencies(ComponentTest_Repository_ps dependency_sdv_components)
add_dependencies(ComponentTest_Repository ComponentTest_Repository_test_module)
add_dependencies(ComponentTest_Repository ComponentTest_Repository_ps)
add_dependencies(ComponentTest_Repository ComponentTest_Repository_install_manifest)

View File

@@ -0,0 +1,135 @@
#include <gtest/gtest.h>
#include <support/app_control.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>
#include "../../../global/exec_dir_helper.h"
#include "generated/test_component.h"
inline sdv::process::TProcessID GetProcessID()
{
static sdv::process::TProcessID tProcessID = 0;
if (!tProcessID)
{
sdv::process::IProcessInfo* pProcessInfo = sdv::core::GetObject<sdv::process::IProcessInfo>("ProcessControlService");
if (!pProcessInfo) return 0;
tProcessID = pProcessInfo->GetProcessID();
}
return tProcessID;
}
/**
* @brief Automatically configure and start the system to do tests on the test component.
*/
class CIsolatedComponentTest : public ::testing::Test, public sdv::app::CAppControl
{
public:
static void SetUpTestCase() {}
static void TearDownTestSuite() {}
/**
* @brief Setup test case
*/
virtual void SetUp()
{
bool bRet = Startup(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Main"
Instance = 2005
)code");
if (!bRet)
std::cout << "Failed to start the application for instance 1234." << std::endl;
}
/**
* @brief Tear down test case
*/
virtual void TearDown()
{
Shutdown();
}
};
// TODO EVE: Disabled until the implementation of configuration installation is finished. See
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/705891
TEST_F(CIsolatedComponentTest, DISABLED_LoadNonIsolatedSystemService)
{
// Load the hello system service
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_SystemHelloService");
ASSERT_NE(pHello, nullptr);
EXPECT_EQ(pHello->SayHello(), "Hello from system service");
sdv::process::TProcessID tPID = pHello->GetPID();
EXPECT_NE(tPID, 0u);
EXPECT_EQ(tPID, GetProcessID()); // Runs in main process
}
// TODO EVE: Disabled until the implementation of configuration installation is finished. See
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/705891
TEST_F(CIsolatedComponentTest, DISABLED_LoadNonIsolatedDevice)
{
// Load the hello device
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_HelloDevice");
ASSERT_NE(pHello, nullptr);
EXPECT_EQ(pHello->SayHello(), "Hello from device");
sdv::process::TProcessID tPID = pHello->GetPID();
EXPECT_NE(tPID, 0u);
EXPECT_EQ(tPID, GetProcessID()); // Runs in main process
}
// TODO EVE: Disabled until the implementation of configuration installation is finished. See
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/705891
TEST_F(CIsolatedComponentTest, DISABLED_LoadNonIsolatedBasicService)
{
// Load the hello basic service
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_BasicHelloService");
ASSERT_NE(pHello, nullptr);
EXPECT_EQ(pHello->SayHello(), "Hello from basic service");
sdv::process::TProcessID tPID = pHello->GetPID();
EXPECT_NE(tPID, 0u);
EXPECT_EQ(tPID, GetProcessID()); // Runs in main process
}
// TODO EVE: Disabled until the implementation of configuration installation is finished. See
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/705891
TEST_F(CIsolatedComponentTest, DISABLED_LoadIsolatedComplexService)
{
// Load the hello basic service
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_ComplexHelloService");
ASSERT_NE(pHello, nullptr);
EXPECT_EQ(pHello->SayHello(), "Hello from complex service");
sdv::process::TProcessID tPID = pHello->GetPID();
EXPECT_NE(tPID, 0u);
EXPECT_NE(tPID, GetProcessID()); // Runs in isolated process
}
/*
TEST the following:
- Main app crashes or ends... iso app also ends
- Iso app crashes/ends, object in main app will be removed
- iso and exetrnal apps are not allowed to create objects in main app
- dependencies
- on startup create objects the object is dependent on first
- on shutdown shutdown dependent objects first
// TODO EVE
// The following issues are still present:
// Lifetime of remote object
// Lifetime of iso process
// Print information during verbose
// Test when error occurs
// Utilities during startup and when running (currently disabled: see CreateUtility)
// Enabling the automatic test execution and compilation of repo tests: see CMakeLists in ComponentTest_Repository
*/

View File

@@ -0,0 +1,646 @@
#include <gtest/gtest.h>
#include <interfaces/repository.h>
#include <support/local_service_access.h>
#include <support/app_control.h>
#include "../../../global/process_watchdog.h"
#include "../../include/basic_test_helper.h"
#include "generated/test_component.h"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
const uint32_t LoopCount = 100; //< amount of loops used for concurrency tests. more loops means more thorough deadlock check at the cost of increased runtime
// used to supply external objects for testing pruposes. Implements IObjectControl to make sure this is NOT called for externally supplied objects
class TestExternalObject : public sdv::IInterfaceAccess, public sdv::IObjectControl
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
{
FAIL() << "Error: Initialize should not be called by Repo Service!";
// m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
}
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
virtual void Shutdown()
{
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
TEST(RepositoryTest, LoadNonexistentModule)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
EXPECT_FALSE(pModuleControl->Load((GetExecDirectory() / "TestFooBar.sdv").generic_u8string()));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, CreateNonexistantClass)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
EXPECT_FALSE(pRepositoryControl->CreateObject("TestFooBar", nullptr, nullptr));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, GetNonexistantObject)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("Example_Object", nullptr, nullptr);
EXPECT_TRUE(bRes);
EXPECT_EQ(nullptr, pObjectAccess->GetObject("TestFooBar"));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, InstantiateAndGet)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("Example_Object", nullptr, nullptr);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("Example_Object"));
control.SetRunningMode();
control.Shutdown();
EXPECT_EQ(nullptr, pObjectAccess->GetObject("Example_Object"));
}
TEST(RepositoryTest, InstantiateInitFail)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("TestObject_IObjectControlFail", nullptr, nullptr);
EXPECT_FALSE(bRes);
EXPECT_EQ(nullptr, pObjectAccess->GetObject("TestObject_IObjectControlFail"));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, InstantiateDuplicateCreateObjectName)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
// Instantiating the same object twice is allowed (only one instance will be created).
EXPECT_TRUE(pRepositoryControl->CreateObject("Example_Object", nullptr, nullptr));
EXPECT_TRUE(pRepositoryControl->CreateObject("Example_Object", nullptr, nullptr));
EXPECT_NE(nullptr, pObjectAccess->GetObject("Example_Object"));
// Instantiating a different object with the same name as the previous object is not allowed.
EXPECT_FALSE(pRepositoryControl->CreateObject("Example_Object_2", "Example_Object", nullptr));
// Instantiating a different object with a completely different name is allowed
EXPECT_TRUE(pRepositoryControl->CreateObject("Example_Object_2", "abracadabra", nullptr));
EXPECT_NE(nullptr, pObjectAccess->GetObject("abracadabra"));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, InstantiateDuplicateExternalObjectName)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
sdv::core::IRegisterForeignObject* pExternalObject = sdv::core::GetObject<sdv::core::IRegisterForeignObject>("RepositoryService");
ASSERT_TRUE(pExternalObject);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
//no two objects of same name allowed! Second Register fails, Get returns instance of first Register
TestExternalObject testObj1;
EXPECT_TRUE(pExternalObject->RegisterObject(&testObj1, "Example_Object"));
TestExternalObject testObj2;
EXPECT_FALSE(pExternalObject->RegisterObject(&testObj2, "Example_Object"));
EXPECT_EQ(&testObj1, pObjectAccess->GetObject("Example_Object"));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, InstantiateDuplicateObjectNameMixed)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
sdv::core::IRegisterForeignObject* pExternalObject = sdv::core::GetObject<sdv::core::IRegisterForeignObject>("RepositoryService");
ASSERT_TRUE(pExternalObject);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
//no two objects of same name allowed! Register fails, Get returns instance previously created
bool bRes = pRepositoryControl->CreateObject("Example_Object", nullptr, nullptr);
EXPECT_TRUE(bRes);
TestExternalObject testObj2;
EXPECT_FALSE(pExternalObject->RegisterObject(&testObj2, "Example_Object"));
EXPECT_NE(nullptr, pObjectAccess->GetObject("Example_Object"));
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, InstantiateTwoNamedInstances)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes1 = pRepositoryControl->CreateObject("Example_Object", "Obj_1", nullptr);
EXPECT_TRUE(bRes1);
EXPECT_NE(nullptr, pObjectAccess->GetObject("Obj_1"));
bool bRes2 = pRepositoryControl->CreateObject("Example_Object", "Obj_2", nullptr);
EXPECT_TRUE(bRes2);
EXPECT_NE(nullptr, pObjectAccess->GetObject("Obj_2"));
EXPECT_EQ(nullptr, pObjectAccess->GetObject("Example_Object"));
control.SetRunningMode();
control.Shutdown();
EXPECT_EQ(nullptr, pObjectAccess->GetObject("Obj_1"));
EXPECT_EQ(nullptr, pObjectAccess->GetObject("Obj_2"));
}
TEST(RepositoryTest, ChainCreateSimple)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", nullptr, "ChainedObject");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("TestObject_CreateChain"));
EXPECT_NE(nullptr, pObjectAccess->GetObject("ChainedObject"));
control.SetRunningMode();
control.Shutdown();
EXPECT_EQ(nullptr, pObjectAccess->GetObject("TestObject_CreateChain"));
EXPECT_EQ(nullptr, pObjectAccess->GetObject("ChainedObject"));
}
TEST(RepositoryTest, ChainCreateParallel)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
std::thread testThread([pRepositoryControl, pObjectAccess]()
{
for (uint32_t i = 0; i < LoopCount; ++i)
{
std::string count = std::to_string(i);
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Bar_" + count, "BarFoo_" + count);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("BarFoo_" + count));
}
});
for (uint32_t i = 0; i < LoopCount; ++i)
{
std::string count = std::to_string(i);
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count, "FooBar_" + count);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("FooBar_" + count));
}
testThread.join();
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, ChainCreateParallelLock)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("TestLockService", nullptr, nullptr);
ASSERT_TRUE(bRes);
auto pLock = sdv::core::GetObject("TestLockService").GetInterface<ITestLock>();
ASSERT_NE(pLock, nullptr);
//attempt to create deadlock by taking lock during initialize and by taking lock before call to create object
std::thread testThread([&]()
{
for (uint32_t i = 0; i < LoopCount; ++i)
{
std::string count = std::to_string(i);
//locks using TestLockService during construction
bRes = pRepositoryControl->CreateObject("TestObject_CreateChainLock", "Bar_" + count, "BarFoo_" + count);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("BarFoo_" + count));
}
});
for (uint32_t i = 0; i < LoopCount; ++i)
{
std::string count = std::to_string(i);
pLock->Lock();
bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count, "FooBar_" + count);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("FooBar_" + count));
pLock->Unlock();
}
testThread.join();
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, ChainCreateParallelThreadLock)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("TestLockService", nullptr, nullptr);
ASSERT_TRUE(bRes);
auto pLock = sdv::core::GetObject("TestLockService").GetInterface<ITestLock>();
ASSERT_NE(pLock, nullptr);
//attempt to create deadlock by taking lock during initialize and by taking lock before call to create object
std::thread testThread([&]()
{
for (uint32_t i = 0; i < LoopCount; ++i)
{
std::string count = std::to_string(i);
//locks using TestLockService during construction in a seperate thread
bRes = pRepositoryControl->CreateObject("TestObject_CreateChainLockThread", "Bar_" + count, "BarFoo_" + count);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("BarFoo_" + count));
}
});
for (uint32_t i = 0; i < LoopCount; ++i)
{
std::string count = std::to_string(i);
pLock->Lock();
bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count, "FooBar_" + count);
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("FooBar_" + count));
pLock->Unlock();
}
testThread.join();
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, InstantiateDuringShutdown)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto pModuleControl = sdv::core::GetObject<sdv::core::IModuleControl>("ModuleControlService");
ASSERT_TRUE(pModuleControl);
auto pRepositoryControl = sdv::core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
ASSERT_TRUE(pRepositoryControl);
auto pObjectAccess = sdv::core::GetObject<sdv::core::IObjectAccess>("RepositoryService");
ASSERT_TRUE(pObjectAccess);
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
//object creates new object during shutdown
//this is needed in case new proxies are requested during shutdown
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateDuringShutdown", nullptr, nullptr);
EXPECT_TRUE(bRes);
control.SetRunningMode();
control.Shutdown();
}
TEST(RepositoryTest, CreateUtility)
{
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Essential"
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
auto ptrUtility = sdv::core::CreateUtility("TOMLParserUtility");
ASSERT_TRUE(ptrUtility);
ptrUtility.Clear();
ASSERT_FALSE(ptrUtility);
control.SetRunningMode();
control.Shutdown();
}
// TODO EVE: Disabled until the implementation of configuration installation is finished. See
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/705891
TEST(RepositoryTest, DISABLED_MainApplication_GetInstalledAndLoadedComponent)
{
// Start the app control. The application automatically loads the installation manifests and the application configuration,
// starting automatically the objects.
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Main"
Instance = 2005
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
// The example object is part of the installation and should have automatically instantiated through the configuration.
auto pInterfaceAccess = sdv::core::GetObject<sdv::IInterfaceAccess>("Example_Object_2");
EXPECT_NE(pInterfaceAccess, nullptr);
control.SetRunningMode();
control.Shutdown();
}
// TODO EVE: Disabled until the implementation of configuration installation is finished. See
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/705891
TEST(RepositoryTest, DISABLED_MainApplication_GetInstalledComponent)
{
// Start the app control. The application automatically loads the installation manifests, but since there is no application
// configuration, it doesn't load the objects.
sdv::app::CAppControl control(R"code(
[LogHandler]
ViewFilter = "Fatal"
[Application]
Mode = "Main"
Instance = 2005
AppConfig = "" # override application config
)code");
ASSERT_TRUE(control.IsRunning());
control.SetConfigMode();
// The example object is part of the installation and should have be automatically instantiated.
auto pInterfaceAccess = sdv::core::GetObject<sdv::IInterfaceAccess>("Example_Object_2");
EXPECT_NE(pInterfaceAccess, nullptr);
control.SetRunningMode();
control.Shutdown();
}

View File

@@ -0,0 +1,870 @@
#include <gtest/gtest.h>
#include <mutex>
#include <iostream>
#include <functional>
#include <thread>
#include <support/component_impl.h>
#include <support/local_service_access.h>
#include "generated/test_component.h"
inline sdv::process::TProcessID GetProcessID()
{
static sdv::process::TProcessID tProcessID = 0;
if (!tProcessID)
{
sdv::process::IProcessInfo* pProcessInfo = sdv::core::GetObject<sdv::process::IProcessInfo>("ProcessControlService");
if (!pProcessInfo) return 0;
tProcessID = pProcessInfo->GetProcessID();
}
return tProcessID;
}
class CTestLockService : public sdv::CSdvObject, public ITestLock
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(ITestLock)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestLockService")
void Lock() override
{
m_mutex.lock();
}
void Unlock() override
{
m_mutex.unlock();
}
private:
std::recursive_mutex m_mutex;
};
DEFINE_SDV_OBJECT(CTestLockService)
/**
* @brief Example component testing IObjectControl
*/
class CTestObjectControl
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
~CTestObjectControl()
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::destruction_pending);
}
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("Example_Object")
/**
* @brief Initialize method. On success, a subsequent call to GetStatus returns EObjectStatus::running
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown method called before the object is destroyed.
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the object!
* After a call to shutdown any threads/callbacks/etc that could call other SDV objects need to have been stopped.
* The SDV object itself is to remain in a state where it can respond to calls to its interfaces as other objects may still call it during the shutdown sequence!
* Any subsequent call to GetStatus should return EObjectStatus::destruction_pending
*/
virtual void Shutdown()
{
EXPECT_TRUE(m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized ||
m_eObjectStatus == sdv::EObjectStatus::configuring);
if (m_eObjectStatus != sdv::EObjectStatus::running && m_eObjectStatus != sdv::EObjectStatus::initialized
&& m_eObjectStatus != sdv::EObjectStatus::configuring)
std::cout << "Object status = " << static_cast<uint32_t>(m_eObjectStatus) << " (expected initialized=" <<
static_cast<uint32_t>(sdv::EObjectStatus::initialized) << " or configuring=" <<
static_cast<uint32_t>(sdv::EObjectStatus::configuring) << " or running=" <<
static_cast<uint32_t>(sdv::EObjectStatus::running) << ")." << std::endl;
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectControl)
/**
* @brief Example component testing IObjectControl - 2nd component to test duplicate instantiation
*/
class CTestObjectControl2
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
~CTestObjectControl2()
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::destruction_pending);
}
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("Example_Object_2")
/**
* @brief Initialize method. On success, a subsequent call to GetStatus returns EObjectStatus::running
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown method called before the object is destroyed.
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the object!
* After a call to shutdown any threads/callbacks/etc that could call other SDV objects need to have been stopped.
* The SDV object itself is to remain in a state where it can respond to calls to its interfaces as other objects may still call it during the shutdown sequence!
* Any subsequent call to GetStatus should return EObjectStatus::destruction_pending
*/
virtual void Shutdown()
{
EXPECT_TRUE(m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized ||
m_eObjectStatus == sdv::EObjectStatus::configuring);
if (m_eObjectStatus != sdv::EObjectStatus::running && m_eObjectStatus != sdv::EObjectStatus::initialized
&& m_eObjectStatus != sdv::EObjectStatus::configuring)
std::cout << "Object status = " << static_cast<uint32_t>(m_eObjectStatus) << " (expected initialized=" <<
static_cast<uint32_t>(sdv::EObjectStatus::initialized) << " or configuring=" <<
static_cast<uint32_t>(sdv::EObjectStatus::configuring) << " or running=" <<
static_cast<uint32_t>(sdv::EObjectStatus::running) << ")." << std::endl;
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectControl2)
/**
* @brief Example component testing IObjectControl
*/
class CTestObjectControlFail
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestObject_IObjectControlFail")
/**
* @brief Initialize method. On success, a subsequent call to GetStatus returns EObjectStatus::running
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
{
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown method called before the object is destroyed.
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the object!
* After a call to shutdown any threads/callbacks/etc that could call other SDV objects need to have been stopped.
* The SDV object itself is to remain in a state where it can respond to calls to its interfaces as other objects may still call it during the shutdown sequence!
* Any subsequent call to GetStatus should return EObjectStatus::destruction_pending
*/
virtual void Shutdown()
{}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectControlFail)
/**
* @brief Example component testing chained object creation in Initialize
*/
class CTestObjectCreate
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestObject_CreateChain")
/**
* @brief Initialize method. On success, a subsequent call to GetStatus returns EObjectStatus::running
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize( const sdv::u8string& ssObjectConfig)
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
//create new example object with name ssObjectConfig
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
ASSERT_FALSE(ssObjectConfig.empty());
ASSERT_TRUE(pCreate->CreateObject("Example_Object", ssObjectConfig,nullptr));
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown method called before the object is destroyed.
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the object!
* After a call to shutdown any threads/callbacks/etc that could call other SDV objects need to have been stopped.
* The SDV object itself is to remain in a state where it can respond to calls to its interfaces as other objects may still call it during the shutdown sequence!
* Any subsequent call to GetStatus should return EObjectStatus::destruction_pending
*/
virtual void Shutdown()
{
EXPECT_TRUE(m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized ||
m_eObjectStatus == sdv::EObjectStatus::configuring);
if (m_eObjectStatus != sdv::EObjectStatus::running && m_eObjectStatus != sdv::EObjectStatus::initialized
&& m_eObjectStatus != sdv::EObjectStatus::configuring)
std::cout << "Object status = " << static_cast<uint32_t>(m_eObjectStatus) << " (expected initialized=" <<
static_cast<uint32_t>(sdv::EObjectStatus::initialized) << " or configuring=" <<
static_cast<uint32_t>(sdv::EObjectStatus::configuring) << " or running=" <<
static_cast<uint32_t>(sdv::EObjectStatus::running) << ")." << std::endl;
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectCreate)
/**
* @brief Example component testing chained object creation in Initialize while holding a lock
*/
class CTestObjectCreateLock
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestObject_CreateChainLock")
/**
* @brief Initialize the object. Overload of sdv::IObjectControl::Initialize.
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize(const sdv::u8string& ssObjectConfig)
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
//create new example object with name ssObjectConfig while holding lock
auto pLock = sdv::core::GetObject<ITestLock>("TestLockService");
ASSERT_NE(pLock,nullptr);
struct SAutoLock
{
SAutoLock(ITestLock* pLockParam) : m_pLockParam(pLockParam) { pLockParam->Lock(); }
~SAutoLock() { m_pLockParam->Unlock(); }
ITestLock* m_pLockParam = nullptr;
} sAutoLock(pLock);
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
ASSERT_FALSE(ssObjectConfig.empty());
ASSERT_TRUE(pCreate->CreateObject("Example_Object", ssObjectConfig, nullptr));
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown called before the object is destroyed. Overload of sdv::IObjectControl::Shutdown.
*/
virtual void Shutdown()
{
EXPECT_TRUE(m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized ||
m_eObjectStatus == sdv::EObjectStatus::configuring);
if (m_eObjectStatus != sdv::EObjectStatus::running && m_eObjectStatus != sdv::EObjectStatus::initialized
&& m_eObjectStatus != sdv::EObjectStatus::configuring)
std::cout << "Object status = " << static_cast<uint32_t>(m_eObjectStatus) << " (expected initialized=" <<
static_cast<uint32_t>(sdv::EObjectStatus::initialized) << " or configuring=" <<
static_cast<uint32_t>(sdv::EObjectStatus::configuring) << " or running=" <<
static_cast<uint32_t>(sdv::EObjectStatus::running) << ")." << std::endl;
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectCreateLock)
/**
* @brief Example component testing chained object creation in Initialize in extra thread holding a lock
*/
class CTestObjectCreateLockThread
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestObject_CreateChainLockThread")
/**
* @brief Initialize the object. Overload of sdv::IObjectControl::Initialize.
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize(const sdv::u8string& ssObjectConfig)
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
auto fun = [ssObjectConfig]()
{
//create new example object with name ssObjectConfig while holding lock
auto pLock = sdv::core::GetObject<ITestLock>("TestLockService");
ASSERT_NE(pLock, nullptr);
struct SAutoLock
{
SAutoLock(ITestLock* pLockParam) : m_pLockParam(pLockParam) { pLockParam->Lock(); }
~SAutoLock() { m_pLockParam->Unlock(); }
ITestLock* m_pLockParam = nullptr;
} sAutoLock(pLock);
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
ASSERT_FALSE(ssObjectConfig.empty());
ASSERT_TRUE(pCreate->CreateObject("Example_Object", ssObjectConfig, nullptr));
};
std::thread testThread(fun);
testThread.join();
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown called before the object is destroyed. Overload of sdv::IObjectControl::Shutdown.
*/
virtual void Shutdown()
{
EXPECT_TRUE(m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized ||
m_eObjectStatus == sdv::EObjectStatus::configuring);
if (m_eObjectStatus != sdv::EObjectStatus::running && m_eObjectStatus != sdv::EObjectStatus::initialized
&& m_eObjectStatus != sdv::EObjectStatus::configuring)
std::cout << "Object status = " << static_cast<uint32_t>(m_eObjectStatus) << " (expected initialized=" <<
static_cast<uint32_t>(sdv::EObjectStatus::initialized) << " or configuring=" <<
static_cast<uint32_t>(sdv::EObjectStatus::configuring) << " or running=" <<
static_cast<uint32_t>(sdv::EObjectStatus::running) << ")." << std::endl;
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectCreateLockThread)
/**
* @brief Example component testing IObjectControl
*/
class CTestObjectCreateDuringShutdown
: public sdv::CSdvObject
, public sdv::IObjectControl
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestObject_CreateDuringShutdown")
/**
* @brief Initialize method. On success, a subsequent call to GetStatus returns EObjectStatus::running
* @param[in] ssObjectConfig Optional configuration string.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown method called before the object is destroyed.
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the object!
* After a call to shutdown any threads/callbacks/etc that could call other SDV objects need to have been stopped.
* The SDV object itself is to remain in a state where it can respond to calls to its interfaces as other objects may still call it during the shutdown sequence!
* Any subsequent call to GetStatus should return EObjectStatus::destruction_pending
*/
virtual void Shutdown()
{
EXPECT_TRUE(m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized ||
m_eObjectStatus == sdv::EObjectStatus::configuring);
if (m_eObjectStatus != sdv::EObjectStatus::running && m_eObjectStatus != sdv::EObjectStatus::initialized
&& m_eObjectStatus != sdv::EObjectStatus::configuring)
std::cout << "Object status = " << static_cast<uint32_t>(m_eObjectStatus) << " (expected initialized=" <<
static_cast<uint32_t>(sdv::EObjectStatus::initialized) << " or configuring=" <<
static_cast<uint32_t>(sdv::EObjectStatus::configuring) << " or running=" <<
static_cast<uint32_t>(sdv::EObjectStatus::running) << ")." << std::endl;
//create new example object
//this is allowed during shutdown as it's needed in case new proxies are created
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
ASSERT_FALSE(pCreate->CreateObject("Example_Object", nullptr, nullptr));
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectCreateDuringShutdown)
/**
* @brief Hello device
*/
class CHelloDevice : public sdv::CSdvObject, public IHello
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("TestObject_HelloDevice")
/**
* @brief Say hello. Overload of IHello::SayHello.
* @return The greetings string.
*/
virtual sdv::u8string SayHello() const override
{
return "Hello from device";
}
/**
* @brief Get the PID of the process the component is running in... Overload of IHello::GetPID.
*/
sdv::process::TProcessID GetPID() const
{
return GetProcessID();
}
};
DEFINE_SDV_OBJECT(CHelloDevice)
/**
* @brief Basic hello service
*/
class CBasicHelloService : public sdv::CSdvObject, public IHello
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("TestObject_BasicHelloService")
/**
* @brief Say hello. Overload of IHello::SayHello.
* @return The greetings string.
*/
virtual sdv::u8string SayHello() const override
{
return "Hello from basic service";
}
/**
* @brief Get the PID of the process the component is running in... Overload of IHello::GetPID.
*/
sdv::process::TProcessID GetPID() const
{
return GetProcessID();
}
};
DEFINE_SDV_OBJECT(CBasicHelloService)
/**
* @brief Complex hello service
*/
class CComplexHelloService : public sdv::CSdvObject, public IHello
{
public:
CComplexHelloService()
{
std::cout << "CComplexHelloService constructor" << std::endl;
}
~CComplexHelloService()
{
std::cout << "CComplexHelloService destructor" << std::endl;
}
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::ComplexService)
DECLARE_OBJECT_CLASS_NAME("TestObject_ComplexHelloService")
/**
* @brief Say hello. Overload of IHello::SayHello.
* @return The greetings string.
*/
virtual sdv::u8string SayHello() const override
{
return "Hello from complex service";
}
/**
* @brief Get the PID of the process the component is running in... Overload of IHello::GetPID.
*/
sdv::process::TProcessID GetPID() const
{
return GetProcessID();
}
};
DEFINE_SDV_OBJECT(CComplexHelloService)
/**
* @brief Hello utlity
*/
class CHelloUtility : public sdv::CSdvObject, public IHello
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Utility)
DECLARE_OBJECT_CLASS_NAME("TestObject_HelloUtility")
/**
* @brief Say hello. Overload of IHello::SayHello.
* @return The greetings string.
*/
virtual sdv::u8string SayHello() const override
{
return "Hello from utility";
}
/**
* @brief Get the PID of the process the component is running in... Overload of IHello::GetPID.
*/
sdv::process::TProcessID GetPID() const
{
return GetProcessID();
}
};
DEFINE_SDV_OBJECT(CHelloUtility)
/**
* @brief Hello utlity
*/
class CSystemHelloService : public sdv::CSdvObject, public IHello
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::SystemObject)
DECLARE_OBJECT_CLASS_NAME("TestObject_SystemHelloService")
/**
* @brief Say hello. Overload of IHello::SayHello.
* @return The greetings string.
*/
virtual sdv::u8string SayHello() const override
{
return "Hello from system service";
}
/**
* @brief Get the PID of the process the component is running in... Overload of IHello::GetPID.
*/
sdv::process::TProcessID GetPID() const
{
return GetProcessID();
}
};
DEFINE_SDV_OBJECT(CSystemHelloService)

View File

@@ -0,0 +1,35 @@
#include <interfaces/core.idl>
#include <interfaces/process.idl>
/**
* @brief Example interface
*/
interface ITestLock
{
/**
* @brief Lock Mutex
*/
void Lock();
/**
* @brief Unlock Mutex
*/
void Unlock();
};
/**
* @brief Hello interface
*/
interface IHello
{
/**
* @brief Say hello
* @return The greetings string.
*/
u8string SayHello() const;
/**
* @brief Get the PID of the process the component is running in...
*/
sdv::process::TProcessID GetPID() const;
};

View File

@@ -0,0 +1 @@
#include "generated/ps/proxystub.cpp"

View File

@@ -0,0 +1,60 @@
# Define project (multiple EXEs)
project(TaskTimerTests VERSION 1.0 LANGUAGES CXX)
# TaskTimer executable
add_executable(ComponentTest_TaskTimer
task_timer_test.cpp
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(ComponentTest_TaskTimer GTest::GTest ${CMAKE_THREAD_LIBS_INIT} stdc++fs)
if (WIN32)
target_link_libraries(ComponentTest_TaskTimer Winmm Ws2_32 Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_TaskTimer rt ${CMAKE_DL_LIBS})
endif()
else()
target_link_libraries(ComponentTest_TaskTimer GTest::GTest Winmm Rpcrt4.lib)
endif()
# Add the tasktimer unittest
add_test(NAME ComponentTest_TaskTimer COMMAND ComponentTest_TaskTimer)
# Execute the test
add_custom_command(TARGET ComponentTest_TaskTimer POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_TaskTimer>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_TaskTimer.xml
VERBATIM
)
# SimulationTaskTimer executable
add_executable(ComponentTest_Simulation_TaskTimer
task_simulation_timer_test.cpp
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(ComponentTest_Simulation_TaskTimer GTest::GTest ${CMAKE_THREAD_LIBS_INIT} stdc++fs)
if (WIN32)
target_link_libraries(ComponentTest_Simulation_TaskTimer Winmm Ws2_32 Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_Simulation_TaskTimer rt ${CMAKE_DL_LIBS})
endif()
else()
target_link_libraries(ComponentTest_Simulation_TaskTimer GTest::GTest Winmm Rpcrt4.lib)
endif()
# Add the tasktimer unittest
add_test(NAME ComponentTest_Simulation_TaskTimer COMMAND ComponentTest_Simulation_TaskTimer)
# Execute the test
add_custom_command(TARGET ComponentTest_Simulation_TaskTimer POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_Simulation_TaskTimer>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_Simulation_TaskTimer.xml
VERBATIM
)
# copy the configuration to output folder 'config'
# and build dependencies
add_dependencies(ComponentTest_TaskTimer dependency_sdv_components)
add_dependencies(ComponentTest_TaskTimer task_timer)
add_dependencies(ComponentTest_Simulation_TaskTimer dependency_sdv_components)
add_dependencies(ComponentTest_Simulation_TaskTimer simulation_task_timer)
file (COPY ${PROJECT_SOURCE_DIR}/test_tt_config.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)
file (COPY ${PROJECT_SOURCE_DIR}/test_simulation_tt_config.toml DESTINATION ${CMAKE_BINARY_DIR}/tests/bin/config/)

View File

@@ -0,0 +1,404 @@
#include "gtest/gtest.h"
#include <support/timer.h>
#include <chrono>
#include <thread>
#include <support/app_control.h>
#include "../../../global/process_watchdog.h"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
//test object which counts how many times the cb has been called
class CTestTask : public sdv::core::ITaskExecute, public sdv::IInterfaceAccess
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IInterfaceAccess)
SDV_INTERFACE_ENTRY(sdv::core::ITaskExecute)
END_SDV_INTERFACE_MAP()
std::atomic_bool m_bEnabled = true;
void Enable(bool bEnable) { m_bEnabled = bEnable; }
virtual void Execute() override
{
if (!m_bEnabled) return;
counter++;
}
uint32_t counter = 0;
};
TEST(TaskSimulationTimerTest, Initialization)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
appcontrol.SetRunningMode();
sdv::TInterfaceAccessPtr ptrDispatchService = sdv::core::GetObject("SimulationTaskTimerService");
sdv::core::ITaskTimer* pTimerSvc = ptrDispatchService.GetInterface<sdv::core::ITaskTimer>();
EXPECT_NE(pTimerSvc, nullptr);
appcontrol.Shutdown();
}
TEST(TaskSimulationTimerTest, BasicCounterTestInterface)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task;
sdv::core::CTaskTimer timer(3, &task);
EXPECT_TRUE(timer);
appcontrol.SetRunningMode();
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
uint32_t expected = 5;
uint32_t expectedAdditional = 11;
uint32_t loop = expected;
while (loop > 0) // 5 x 3 steps = 15 steps ==> 5 executions
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected, task.counter);
loop = expected;
while (loop > 0) // 5 * 7 steps = 35 steps ==> 11 executions, 2 rest
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected + expectedAdditional, task.counter);
pTimerSimulationStep->SimulationStep(1000); // one more step, one more execution
EXPECT_EQ(expected + expectedAdditional + 1, task.counter);
timer.Reset();
appcontrol.Shutdown();
}
TEST(TaskSimulationTimerTest, LargerTaskPeriodTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task150;
CTestTask task1150;
CTestTask task3100;
sdv::core::CTaskTimer timer150(150, &task150);
sdv::core::CTaskTimer timer1150(1150, &task1150);
sdv::core::CTaskTimer timer3100(3100, &task3100);
EXPECT_TRUE(timer150);
EXPECT_TRUE(timer1150);
EXPECT_TRUE(timer3100);
appcontrol.SetRunningMode();
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
uint32_t expected150 = 33;
uint32_t expected1150 = 4;
uint32_t expected3100 = 1;
uint32_t loop = 5000;
while (loop > 0) // 5 x 3 steps = 15 steps ==> 5 executions
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected150, task150.counter);
EXPECT_EQ(expected1150, task1150.counter);
EXPECT_EQ(expected3100, task3100.counter);
loop = 7000;
while (loop > 0)
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected150 + 47, task150.counter);
EXPECT_EQ(expected1150 + 6, task1150.counter);
EXPECT_EQ(expected3100 + 2, task3100.counter);
timer150.Reset();
timer1150.Reset();
timer3100.Reset();
appcontrol.Shutdown();
}
TEST(TaskSimulationTimerTest, MultipleTimerIdenticalTaskPeriodTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task1;
CTestTask task2;
CTestTask task3;
sdv::core::CTaskTimer timer1(3, &task1);
sdv::core::CTaskTimer timer2(3, &task2);
sdv::core::CTaskTimer timer3(3, &task3);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer2);
EXPECT_TRUE(timer3);
appcontrol.SetRunningMode();
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
uint32_t expected = 5;
uint32_t expectedAdditional = 11;
uint32_t loop = expected;
while (loop > 0) // 5 x 3 steps = 15 steps ==> 5 executions
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected, task1.counter);
EXPECT_EQ(expected, task2.counter);
EXPECT_EQ(expected, task3.counter);
loop = expected;
while (loop > 0) // 5 * 7 steps = 35 steps ==> 11 executions, 2 rest
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected + expectedAdditional, task1.counter);
EXPECT_EQ(expected + expectedAdditional, task2.counter);
EXPECT_EQ(expected + expectedAdditional, task3.counter);
pTimerSimulationStep->SimulationStep(1000); // one more step, one more execution
EXPECT_EQ(expected + expectedAdditional + 1, task1.counter);
EXPECT_EQ(expected + expectedAdditional + 1, task2.counter);
EXPECT_EQ(expected + expectedAdditional + 1, task3.counter);
timer1.Reset();
timer2.Reset();
timer3.Reset();
appcontrol.Shutdown();
}
TEST(TaskSimulationTimerTest, MultipleTimerDifferentTaskPeriodTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task2;
CTestTask task3;
CTestTask task4;
sdv::core::CTaskTimer timer2(2, &task2);
sdv::core::CTaskTimer timer3(3, &task3);
sdv::core::CTaskTimer timer4(4, &task4);
EXPECT_TRUE(timer2);
EXPECT_TRUE(timer3);
EXPECT_TRUE(timer4);
appcontrol.SetRunningMode();
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
uint32_t expected2 = 7;
uint32_t expected3 = 5;
uint32_t expected4 = 3;
uint32_t expectedAdditional2 = 18;
uint32_t expectedAdditional3 = 11;
uint32_t expectedAdditional4 = 9;
uint32_t loop = 5;
while (loop > 0) // 5 x 3 steps = 15 steps ==> 5 executions
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected2, task2.counter);
EXPECT_EQ(expected3, task3.counter);
EXPECT_EQ(expected4, task4.counter);
loop = 5;
while (loop > 0)
{
loop--;
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
pTimerSimulationStep->SimulationStep(1000);
}
EXPECT_EQ(expected2 + expectedAdditional2, task2.counter);
EXPECT_EQ(expected3 + expectedAdditional3, task3.counter);
EXPECT_EQ(expected4 + expectedAdditional4, task4.counter);
pTimerSimulationStep->SimulationStep(1000);
EXPECT_EQ(expected2 + expectedAdditional2 + 0, task2.counter);
EXPECT_EQ(expected3 + expectedAdditional3 + 1, task3.counter);
EXPECT_EQ(expected4 + expectedAdditional4 + 0, task4.counter);
timer2.Reset();
timer3.Reset();
timer4.Reset();
appcontrol.Shutdown();
}
TEST(TaskSimulationTimerTest, MultipleTimerLargeSimulationStepTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task1;
CTestTask task150;
CTestTask task450;
sdv::core::CTaskTimer timer1(1, &task1);
sdv::core::CTaskTimer timer150(150, &task150);
sdv::core::CTaskTimer timer450(450, &task450);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer150);
EXPECT_TRUE(timer450);
appcontrol.SetRunningMode();
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
uint32_t expected1 = 480;
uint32_t expected150 = 3;
uint32_t expected450 = 1;
pTimerSimulationStep->SimulationStep(80000);
pTimerSimulationStep->SimulationStep(80000);
pTimerSimulationStep->SimulationStep(80000);
pTimerSimulationStep->SimulationStep(80000);
pTimerSimulationStep->SimulationStep(80000);
pTimerSimulationStep->SimulationStep(80000);
EXPECT_EQ(expected1, task1.counter);
EXPECT_EQ(expected150, task150.counter);
EXPECT_EQ(expected450, task450.counter);
timer1.Reset();
timer150.Reset();
timer450.Reset();
appcontrol.Shutdown();
}
TEST(TaskSimulationTimerTest, MultipleTimerLargeAndDifferentSimulationStepTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_simulation_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task1;
CTestTask task150;
CTestTask task450;
sdv::core::CTaskTimer timer1(1, &task1);
sdv::core::CTaskTimer timer150(150, &task150);
sdv::core::CTaskTimer timer450(450, &task450);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer150);
EXPECT_TRUE(timer450);
appcontrol.SetRunningMode();
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
uint32_t expected1 = 480;
uint32_t expected150 = 3;
uint32_t expected450 = 1;
pTimerSimulationStep->SimulationStep(67000);
pTimerSimulationStep->SimulationStep(99000);
pTimerSimulationStep->SimulationStep(72000);
pTimerSimulationStep->SimulationStep(64000);
pTimerSimulationStep->SimulationStep(85000);
pTimerSimulationStep->SimulationStep(93000);
EXPECT_EQ(expected1, task1.counter);
EXPECT_EQ(expected150, task150.counter);
EXPECT_EQ(expected450, task450.counter);
timer1.Reset();
timer150.Reset();
timer450.Reset();
appcontrol.Shutdown();
}

View File

@@ -0,0 +1,267 @@
#include "gtest/gtest.h"
#include <support/timer.h>
#include <chrono>
#include <thread>
#include <support/app_control.h>
#include "../../../global/process_watchdog.h"
static uint32_t TimeTolerance = 50; //tolerate a small delay for task execution
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
//test object which counts how many times the cb has been called
class CTestTask : public sdv::core::ITaskExecute, public sdv::IInterfaceAccess
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IInterfaceAccess)
SDV_INTERFACE_ENTRY(sdv::core::ITaskExecute)
END_SDV_INTERFACE_MAP()
std::atomic_bool m_bEnabled = true;
void Enable(bool bEnable) { m_bEnabled = bEnable; }
virtual void Execute() override
{
if (!m_bEnabled) return;
std::unique_lock<std::mutex> lock(mtxTimes);
vecTimes.push_back(std::chrono::high_resolution_clock::now());
counter++;
}
double CalcAvrgTime()
{
if (vecTimes.empty()) return 0.0;
double dTotal = 0.0;
for (size_t n = 1; n < vecTimes.size(); n++)
dTotal += std::chrono::duration<double>(vecTimes[n] - vecTimes[n - 1]).count();
return dTotal / static_cast<double>(vecTimes.size() - 1);
}
std::atomic<uint64_t> counter = 0ull;
std::mutex mtxTimes;
std::vector<std::chrono::high_resolution_clock::time_point> vecTimes;
};
TEST(TaskTimerTest, Initialization)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
appcontrol.SetRunningMode();
sdv::TInterfaceAccessPtr ptrDispatchService = sdv::core::GetObject("TaskTimerService");
sdv::core::ITaskTimer* pTimerSvc = ptrDispatchService.GetInterface<sdv::core::ITaskTimer>();
EXPECT_NE(pTimerSvc, nullptr);
appcontrol.Shutdown();
}
TEST(TaskTimerTest, BasicCounterTestInterface)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task;
sdv::core::CTaskTimer timer(100, &task);
EXPECT_TRUE(timer);
appcontrol.SetRunningMode();
std::chrono::milliseconds sleepDuration (500 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
timer.Reset();
EXPECT_EQ(5ull, task.counter);
sleepDuration = std::chrono::milliseconds(20 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
EXPECT_EQ(5ull, task.counter);
appcontrol.Shutdown();
}
TEST(TaskTimerTest, BasicCounterTestFunction)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task;
sdv::core::CTaskTimer timer(100, [&]() {task.Execute(); });
EXPECT_TRUE(timer);
appcontrol.SetRunningMode();
std::chrono::milliseconds sleepDuration (500 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
timer.Reset();
EXPECT_EQ(5ull, task.counter);
sleepDuration = std::chrono::milliseconds(20 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
EXPECT_EQ(5ull, task.counter);
// 1ms buffer
if (0.101 <= task.CalcAvrgTime())
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (0.101) > (task.CalcAvrgTime()), actual: " <<
(0.101) << "vs" << task.CalcAvrgTime() << std::endl;
//EXPECT_GT(0.101, task.CalcAvrgTime());
if (0.099 >= task.CalcAvrgTime())
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (0.099) < (task.CalcAvrgTime()), actual: " <<
(0.099) << "vs" << task.CalcAvrgTime() << std::endl;
//EXPECT_LT(0.099, task.CalcAvrgTime());
appcontrol.Shutdown();
}
TEST(TaskTimerTest, LongPeriodTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task;
sdv::core::CTaskTimer timer(1500, &task);
EXPECT_TRUE(timer);
appcontrol.SetRunningMode();
std::chrono::milliseconds sleepDuration (3000 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
timer.Reset();
EXPECT_EQ(2ull, task.counter);
// 1ms buffer
if (1.501 <= task.CalcAvrgTime())
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (1.501) > (task.CalcAvrgTime()), actual: " <<
(1.501) << "vs" << task.CalcAvrgTime() << std::endl;
//EXPECT_GT(1.501, task.CalcAvrgTime());
if (1.499 >= task.CalcAvrgTime())
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (1.499) < (task.CalcAvrgTime()), actual: " <<
(1.499) << "vs" << task.CalcAvrgTime() << std::endl;
//EXPECT_LT(1.499, task.CalcAvrgTime());
appcontrol.Shutdown();
}
TEST(TaskTimerTest, SpawnTaskTwice)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
CTestTask task;
sdv::core::CTaskTimer timer1(100, &task);
sdv::core::CTaskTimer timer2(100, &task);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer2);
appcontrol.SetRunningMode();
std::chrono::milliseconds sleepDuration (500 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
//shutdown both tasks here
timer1.Reset();
timer2.Reset();
//check for counter - expectation: twice the count
EXPECT_EQ(10ull, task.counter);
appcontrol.Shutdown();
}
TEST(TaskTimerTest, MultiTaskTest)
{
sdv::app::CAppControl appcontrol;
bool bResult = appcontrol.Startup("");
EXPECT_TRUE(bResult);
appcontrol.SetConfigMode();
sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_tt_config.toml");
EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful);
uint32_t rguiPeriods[] = { 100, 133, 150, 250, 333, 50, 73, 120, 10, 415, 115, 60, 5/*, 1*/ };
const size_t nExtent = std::extent_v<decltype(rguiPeriods)>;
CTestTask rgtask[nExtent];
sdv::core::CTaskTimer rgtimer[nExtent];
for (size_t n = 0; n < nExtent; n++)
{
rgtask[n].Enable(false);
rgtimer[n] = sdv::core::CTaskTimer(rguiPeriods[n], rgtask + n);
EXPECT_TRUE(rgtimer[n]);
}
appcontrol.SetRunningMode();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (size_t n = 0; n < std::extent_v<decltype(rguiPeriods)>; n++)
{
rgtask[n].Enable(true);
}
std::chrono::milliseconds sleepDuration(1500 + TimeTolerance);
std::this_thread::sleep_for(sleepDuration);
// NOTE: If running in a virtual environment, the constraints cannot be kept.
for (size_t n = 0; n < nExtent; n++)
{
rgtimer[n].Reset();
EXPECT_FALSE(rgtimer[n]);
if (rgtask[n].counter < 1500 / rguiPeriods[n])
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (rgtask[n].counter) >= (1500 / (rguiPeriods[n]), actual: " << rgtask[n].counter << "vs" << (1500 / rguiPeriods[n]) << std::endl;
//EXPECT_GE(rgtask[n].counter, 1500 / rguiPeriods[n]);
// 1ms buffer
if ((static_cast<double>(rguiPeriods[n]) / 1000.0 + 0.001) <= rgtask[n].CalcAvrgTime())
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (static_cast<double>(rguiPeriods[n]) / 1000.0 + 0.001) > (rgtask[n].CalcAvrgTime()), actual: " <<
(static_cast<double>(rguiPeriods[n]) / 1000.0 + 0.001) << "vs" << rgtask[n].CalcAvrgTime() << std::endl;
//EXPECT_GT(static_cast<double>(rguiPeriods[n]) / 1000.0 + 0.001, rgtask[n].CalcAvrgTime());
if ((static_cast<double>(rguiPeriods[n]) / 1000.0 - 0.001) >= rgtask[n].CalcAvrgTime())
std::cout << __FILE__ << ":" << __LINE__ << ":" << "Warning" << std::endl <<
"Expected: (static_cast<double>(rguiPeriods[n]) / 1000.0 - 0.001) < (rgtask[n].CalcAvrgTime()), actual: " <<
(static_cast<double>(rguiPeriods[n]) / 1000.0 + 0.001) << "vs" << rgtask[n].CalcAvrgTime() << std::endl;
//EXPECT_LT(static_cast<double>(rguiPeriods[n]) / 1000.0 - 0.001, rgtask[n].CalcAvrgTime());
}
appcontrol.Shutdown();
}

View File

@@ -0,0 +1,7 @@
[Configuration]
Version = 100
[[Component]]
Path = "simulation_task_timer.sdv"
Class = "SimulationTaskTimerService"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"

View File

@@ -0,0 +1,34 @@
# Define project
project (VSSUtilTests VERSION 1.0 LANGUAGES CXX)
file (COPY ${PROJECT_SOURCE_DIR}/vss_multiple_names.csv DESTINATION ${CMAKE_BINARY_DIR}/bin/)
file (COPY ${PROJECT_SOURCE_DIR}/vss_unique_names.csv DESTINATION ${CMAKE_BINARY_DIR}/bin/)
# VSS util component test executable
add_executable(ComponentTest_VSSUtil vss_util_test.cpp)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(THREADS_PREFER_PTHREAD_FLAG ON)
target_link_libraries(ComponentTest_VSSUtil ${CMAKE_THREAD_LIBS_INIT} GTest::GTest)
if (WIN32)
target_link_libraries(ComponentTest_VSSUtil Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(ComponentTest_VSSUtil ${CMAKE_DL_LIBS} rt)
endif()
else()
target_link_libraries(ComponentTest_VSSUtil GTest::GTest Rpcrt4.lib)
endif()
# Add the VSS utility component test
add_test(NAME ComponentTest_VSSUtil COMMAND ComponentTest_VSSUtil WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
add_custom_command(TARGET ComponentTest_VSSUtil POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_VSSUtil>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_VSSUtil.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_VSSUtil sdv_vss_util)

View File

@@ -0,0 +1,18 @@
;Class name;Function name;Signal name;vss;Signal direction;type;DBC CAN name includes CAN message name
;;;;;;;
VD;SteeringWheel;SteeringWheelAngle_VD;angle_VD;Vehicle.ChassisVD.SteeringWheel.Angle;RX;float;CAN_Input.SteeringWheel
VD;SteeringWheel;VehicleSpeed_VD;speed_VD;Vehicle.ChassisVD.SteeringWheel.Angle;RX;float;CAN_Input.Speed
VD;SteeringWheel;VehicleDoor_VD;doorStatus_VD;Vehicle.ChassisVD.SteeringWheel.Angle;RX;uint8;CAN_Input.Door
VD;SteeringWheel;VehicleWeight_VD;weight_VD;Vehicle.ChassisVD.SteeringWheel.Angle;RX;float;CAN_Input.Weight
VD;VehicleChassisAxle;RearAxleAngle_VD;rearAngle_VD;Vehicle.ChassisVD.RearAxle.Row.Wheel;TX;float;CAN_Output.RearAngle
VD;VehicleChassisAxle;ApplicationCounter_VD;liveCounter_VD;Vehicle.ChassisVD.RearAxle.Row.Wheel;TX;uint8;CAN_Output.IsActiveCounter
VD;VehicleChassisAxle;VehicleFrontLight_VD;frontLightStatus_VD;Vehicle.ChassisVD.RearAxle.Row.Wheel;TX;boolean;CAN_Output.FrontLight
VD;VehicleChassisAxle;VehicleBackLight_VD;backLightStatus_VD;Vehicle.ChassisVD.RearAxle.Row.Wheel;TX;boolean;CAN_Output.BackLight
BS;SteeringWheel;SteeringWheelAngle_BS;angle_BS;Vehicle.ChassisBS.SteeringWheel.Angle;RX;float;Vehicle.ChassisVD.SteeringWheel.Angle
BS;SteeringWheel;VehicleSpeed_BS;speed_BS;Vehicle.ChassisBS.SteeringWheel.Angle;RX;float;Vehicle.ChassisVD.SteeringWheel.Angle
BS;SteeringWheel;VehicleDoor_BS;doorStatus_BS;Vehicle.ChassisBS.SteeringWheel.Angle;RX;uint8;Vehicle.ChassisVD.SteeringWheel.Angle
BS;SteeringWheel;VehicleWeight_BS;weight_BS;Vehicle.ChassisBS.SteeringWheel.Angle;RX;float;Vehicle.ChassisVD.SteeringWheel.Angle
BS;VehicleChassisAxle;RearAxleAngle_BS;rearAngle_BS;Vehicle.ChassisBS.RearAxle.Row.Wheel;TX;float;Vehicle.ChassisVD.RearAxle.Row.Wheel
BS;VehicleChassisAxle;ApplicationCounter_BS;liveCounter_BS;Vehicle.ChassisBS.RearAxle.Row.Wheel;TX;uint8;Vehicle.ChassisVD.RearAxle.Row.Wheel
BS;VehicleChassisAxle;VehicleFrontLight_BS;frontLightStatus_BS;Vehicle.ChassisBS.RearAxle.Row.Wheel;TX;boolean;Vehicle.ChassisVD.RearAxle.Row.Wheel
BS;VehicleChassisAxle;VehicleBackLight_BS;backLightStatus_BS;Vehicle.ChassisBS.RearAxle.Row.Wheel;TX;boolean;Vehicle.ChassisVD.RearAxle.Row.Wheel
1 Class name Function name Signal name vss Signal direction type DBC CAN name includes CAN message name
2
3 VD SteeringWheel SteeringWheelAngle_VD angle_VD Vehicle.ChassisVD.SteeringWheel.Angle RX float CAN_Input.SteeringWheel
4 VD SteeringWheel VehicleSpeed_VD speed_VD Vehicle.ChassisVD.SteeringWheel.Angle RX float CAN_Input.Speed
5 VD SteeringWheel VehicleDoor_VD doorStatus_VD Vehicle.ChassisVD.SteeringWheel.Angle RX uint8 CAN_Input.Door
6 VD SteeringWheel VehicleWeight_VD weight_VD Vehicle.ChassisVD.SteeringWheel.Angle RX float CAN_Input.Weight
7 VD VehicleChassisAxle RearAxleAngle_VD rearAngle_VD Vehicle.ChassisVD.RearAxle.Row.Wheel TX float CAN_Output.RearAngle
8 VD VehicleChassisAxle ApplicationCounter_VD liveCounter_VD Vehicle.ChassisVD.RearAxle.Row.Wheel TX uint8 CAN_Output.IsActiveCounter
9 VD VehicleChassisAxle VehicleFrontLight_VD frontLightStatus_VD Vehicle.ChassisVD.RearAxle.Row.Wheel TX boolean CAN_Output.FrontLight
10 VD VehicleChassisAxle VehicleBackLight_VD backLightStatus_VD Vehicle.ChassisVD.RearAxle.Row.Wheel TX boolean CAN_Output.BackLight
11 BS SteeringWheel SteeringWheelAngle_BS angle_BS Vehicle.ChassisBS.SteeringWheel.Angle RX float Vehicle.ChassisVD.SteeringWheel.Angle
12 BS SteeringWheel VehicleSpeed_BS speed_BS Vehicle.ChassisBS.SteeringWheel.Angle RX float Vehicle.ChassisVD.SteeringWheel.Angle
13 BS SteeringWheel VehicleDoor_BS doorStatus_BS Vehicle.ChassisBS.SteeringWheel.Angle RX uint8 Vehicle.ChassisVD.SteeringWheel.Angle
14 BS SteeringWheel VehicleWeight_BS weight_BS Vehicle.ChassisBS.SteeringWheel.Angle RX float Vehicle.ChassisVD.SteeringWheel.Angle
15 BS VehicleChassisAxle RearAxleAngle_BS rearAngle_BS Vehicle.ChassisBS.RearAxle.Row.Wheel TX float Vehicle.ChassisVD.RearAxle.Row.Wheel
16 BS VehicleChassisAxle ApplicationCounter_BS liveCounter_BS Vehicle.ChassisBS.RearAxle.Row.Wheel TX uint8 Vehicle.ChassisVD.RearAxle.Row.Wheel
17 BS VehicleChassisAxle VehicleFrontLight_BS frontLightStatus_BS Vehicle.ChassisBS.RearAxle.Row.Wheel TX boolean Vehicle.ChassisVD.RearAxle.Row.Wheel
18 BS VehicleChassisAxle VehicleBackLight_BS backLightStatus_BS Vehicle.ChassisBS.RearAxle.Row.Wheel TX boolean Vehicle.ChassisVD.RearAxle.Row.Wheel

View File

@@ -0,0 +1,10 @@
;Class name;Function name;Signal name;vss;Signal direction;type;DBC CAN name includes CAN message name
;;;;;;;
VD;SteeringWheel;SteeringWheelAngle_VD;angle_VD;Vehicle.ChassisVD.SteeringWheel.Angle;RX;float;CAN_Input.SteeringWheel
VD;Vehicle;VehicleSpeed_VD;speed_VD;Vehicle.ChassisVD.Vehicle.Speed;RX;float;CAN_Input.Speed
VD;VehicleChassisAxle;RearAxleAngle_VD;rearAngle_VD;Vehicle.ChassisVD.RearAxle.Row.Wheel;TX;float;CAN_Output.RearAngle
VD;VehicleApplication;ApplicationCounter_VD;liveCounter_VD;Vehicle.SoftwareVD.Application.SystemCounter;TX;uint8;CAN_Output.IsActiveCounter
BS;SteeringWheel;SteeringWheelAngle_BS;angle_BS;Vehicle.ChassisBS.SteeringWheel.Angle;RX;float;Vehicle.ChassisVD.SteeringWheel.Angle
BS;Vehicle;VehicleSpeed_BS;speed_BS;Vehicle.ChassisBS.Vehicle.Speed;RX;float;Vehicle.ChassisVD.Vehicle.Speed
BS;VehicleChassisAxle;RearAxleAngle_BS;rearAngle_BS;Vehicle.ChassisBS.RearAxle.Row.Wheel;TX;float;Vehicle.ChassisVD.RearAxle.Row.Wheel
BS;VehicleApplication;ApplicationCounter_BS;liveCounter_BS;Vehicle.SoftwareBS.Application.SystemCounter;TX;uint8;Vehicle.SoftwareVD.Application.SystemCounter
1 Class name Function name Signal name vss Signal direction type DBC CAN name includes CAN message name
2
3 VD SteeringWheel SteeringWheelAngle_VD angle_VD Vehicle.ChassisVD.SteeringWheel.Angle RX float CAN_Input.SteeringWheel
4 VD Vehicle VehicleSpeed_VD speed_VD Vehicle.ChassisVD.Vehicle.Speed RX float CAN_Input.Speed
5 VD VehicleChassisAxle RearAxleAngle_VD rearAngle_VD Vehicle.ChassisVD.RearAxle.Row.Wheel TX float CAN_Output.RearAngle
6 VD VehicleApplication ApplicationCounter_VD liveCounter_VD Vehicle.SoftwareVD.Application.SystemCounter TX uint8 CAN_Output.IsActiveCounter
7 BS SteeringWheel SteeringWheelAngle_BS angle_BS Vehicle.ChassisBS.SteeringWheel.Angle RX float Vehicle.ChassisVD.SteeringWheel.Angle
8 BS Vehicle VehicleSpeed_BS speed_BS Vehicle.ChassisBS.Vehicle.Speed RX float Vehicle.ChassisVD.Vehicle.Speed
9 BS VehicleChassisAxle RearAxleAngle_BS rearAngle_BS Vehicle.ChassisBS.RearAxle.Row.Wheel TX float Vehicle.ChassisVD.RearAxle.Row.Wheel
10 BS VehicleApplication ApplicationCounter_BS liveCounter_BS Vehicle.SoftwareBS.Application.SystemCounter TX uint8 Vehicle.SoftwareVD.Application.SystemCounter

View File

@@ -0,0 +1,348 @@
#include <gtest/gtest.h>
#include <fstream>
#include <sstream>
#include <algorithm>
#include "../../../global/process_watchdog.h"
#include "../global/exec_dir_helper.h"
#ifdef _WIN32
#include <windows.h>
#endif
class VSSUtilTest : public ::testing::Test
{
public:
virtual void SetUp() override {}
virtual void TearDown() override {}
static void SetUpTestCase()
{
std::cout << "SetUpTestCase()" << std::endl;
std::vector<std::string> subFolders = { "generated0", "generated1", "generated2" };
for (auto subFolder : subFolders)
{
auto generatedPath = GetExecDirectory() / subFolder;
try
{
if (std::filesystem::is_directory(generatedPath))
{
for (const auto& entry : std::filesystem::directory_iterator(generatedPath))
{
std::filesystem::remove_all(entry.path());
}
}
}
catch (const std::filesystem::filesystem_error& e)
{
std::cout << "catch (const std::filesystem::filesystem_error& e)" << std::endl;
std::cout << "Error removing directory: " << e.what() << '\n';
}
}
}
static void TearDownTestSuite() {}
};
std::uintmax_t CountNumberOfFiles(const std::filesystem::path allFilesPath)
{
std::uintmax_t allFilesCount = 0;
for (const auto& entry : std::filesystem::recursive_directory_iterator(allFilesPath))
{
if (std::filesystem::is_regular_file(entry.status()))
{
++allFilesCount;
}
}
return allFilesCount;
}
void DeleteExistingHeaderFiles(const std::filesystem::path allFilesPath)
{
std::string doNotDeleteSignalIdentifier = "signal_identifier.h";
if (std::filesystem::is_directory(allFilesPath))
{
for (const auto& entry : std::filesystem::directory_iterator(allFilesPath))
{
if (entry.path().extension() == ".h")
{
if (entry.path().filename() != doNotDeleteSignalIdentifier)
{
try
{
std::filesystem::remove(entry.path());
std::cout << "File deleted: " << entry.path().filename().string() << std::endl;
} catch (const std::filesystem::filesystem_error&)
{
std::cout << "Failed to delete: " << entry.path().filename().string() << std::endl;
}
}
}
}
}
}
void DeletePSAndSerdesFolder(const std::filesystem::path allFilesPath)
{
auto psFolder = allFilesPath / "ps";
auto serdesolder = allFilesPath / "serdes";
if (std::filesystem::is_directory(psFolder))
{
try
{
std::filesystem::remove_all(psFolder);
}
catch (const std::filesystem::filesystem_error& e)
{
std::cout << "catch (const std::filesystem::filesystem_error& e)" << std::endl;
std::cout << "Error removing directory: " << e.what() << '\n';
}
}
if (std::filesystem::is_directory(serdesolder))
{
try
{
std::filesystem::remove_all(serdesolder);
}
catch (const std::filesystem::filesystem_error& e)
{
std::cout << "catch (const std::filesystem::filesystem_error& e)" << std::endl;
std::cout << "Error removing directory: " << e.what() << '\n';
}
}
}
std::filesystem::path GetExportFolder(std::filesystem::path folder)
{
while (!folder.empty())
{
auto exportFolder = folder / "export";
if (std::filesystem::is_directory(exportFolder))
return exportFolder;
folder = folder.parent_path();
}
return {};
}
/**
* @brief Build the command line by quoting all arguments. This is the one argument function.
* @param[in] rssArg The argument to quote.
* @return The quoted argument.
*/
inline std::string BuildCommandLine(const std::string& rssArg)
{
return std::string("\"") + rssArg + std::string("\"");
}
/**
* @brief Build the command line by quoting all arguments. This is the multiple argument function.
* @tparam ...TArgs Argument types. Needs to be implicitly convertable to std::string.
* @param[in] rssArg The one argument to quote.
* @param[in] rgtArgs The other arguments to quote.
* @return The command line with the quoted arguments.
*/
template <typename... TArgs>
inline std::string BuildCommandLine(const std::string& rssArg, const TArgs&... rgtArgs)
{
return std::string("\"") + rssArg + std::string("\" ") + BuildCommandLine(rgtArgs...);
}
/**
* @brief Platform specific implementation for executing command having space in the command path and in the parameters.
* @tparam ...TArgs
* @param[in] rssCommand The command line string.
* @param[in] rgtArgs List of string arguments.
* @return The result of the application or -1 when the application could not be started.
*/
template <typename... TArgs>
inline int ExecuteCommand(const std::string& rssCommand, const TArgs&... rgtArgs)
{
// Build the command line by quoting each argument.
std::string ssFullCommand = BuildCommandLine(rssCommand, rgtArgs...);
// NOTE: The std::system command is a bit peculiar when dealing with spaces int he path name under Windows. Even though each
// command line argument is quoted, the quotes are removed before the command line is supplied to CMD /C. To solve this issue
// add additional quotes at the beginning and end of the complete command line: \"app arg1 arg2 arg3\". See also:
// https://stackoverflow.com/questions/27975969/how-to-run-an-executable-with-spaces-using-stdsystem-on-windows
// --> This seems to work with the std::system of MSVC, not not of MINGW!
// --> For MINGW there is no solution... use platform specific solution is the advice.
#ifdef _WIN32
STARTUPINFOA si{};
PROCESS_INFORMATION pi{};
si.cb = sizeof(si);
// Convert std::string to LPSTR
LPSTR szCommand = const_cast<char*>(ssFullCommand.c_str());
// Start the child process
if (!CreateProcessA(NULL, szCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
std::cerr << "CreateProcess failed (" << GetLastError() << ")." << std::endl;
return -1;
}
// Wait until child process exits
WaitForSingleObject(pi.hProcess, INFINITE);
// Get the exit code
int iRet = 0;
GetExitCodeProcess(pi.hProcess, reinterpret_cast<DWORD*>(&iRet));
// Close process and thread handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return iRet;
#elif defined __unix__
return std::system(ssFullCommand.c_str());
#else
#error The OS is not supported!
#endif
}
int CreateCode(const std::string& document, const std::string& subfolder, const bool bCreateComponents)
{
auto vssUtility = (GetExecDirectory() / "../../bin/sdv_vss_util").lexically_normal();
auto documentPath = (GetExecDirectory() / "../../bin" / document).lexically_normal();
auto outputFolder = (GetExecDirectory() / subfolder).lexically_normal();
// VSS_Sheet_Single.csv -O${VSSUTIL_OUTPUT_DIRECTORY}/generated/ --version1.0.0.2 --prefixdemo --enable_components
if (bCreateComponents)
{
return ExecuteCommand(vssUtility.generic_string(), documentPath.generic_string(), std::string("-O") + outputFolder.generic_string(),
std::string("--enable_components"), std::string("--prefixdemo"), std::string("--version1.2.3.4"), std::string("--silent"));//
}
return ExecuteCommand(vssUtility.generic_string(), documentPath.generic_string(), std::string("-O") + outputFolder.generic_string(),
std::string("--prefixdemo"), std::string("--version1.2.3.4"), std::string("--silent"));
}
int CompileIDLFiles(const std::filesystem::path allFilesPath)
{
bool noFilesFound = true;
int result = 0;
auto idlCompiler = GetExecDirectory() / "../../bin/sdv_idl_compiler";
auto idlFiles = allFilesPath / "vss_files";
for (const auto& entry : std::filesystem::directory_iterator(idlFiles))
{
if (!entry.is_regular_file() || entry.path().extension() != ".idl") continue;
noFilesFound = false;
std::cout << "Call IDL Compiler for file " << entry.path().filename().string() << std::endl;
// C:/Data/out/build/x64-Debug/tests/bin/../../bin/sdv_idl_compiler "../tests/bin/generated2/vss_files/VSS_VehicleVehicleDrivetrainTransmissionIsParkLockEngaged_tx.idl"
// -O../tests/bin/generated2/vss_files -I../tests/bin/generated2/vss_files -I../../../../export
result += ExecuteCommand(idlCompiler.lexically_normal().generic_string(),
(idlFiles.lexically_normal() / entry.path().filename()).generic_string(),
std::string("-O") + idlFiles.lexically_normal().generic_string(),
std::string("-I") + idlFiles.lexically_normal().generic_string(),
std::string("-I") + GetExportFolder(allFilesPath).lexically_normal().generic_string());
}
if (noFilesFound)
{
return 1;
}
return result;
}
TEST_F(VSSUtilTest, CreateCodeValidateGeneratedFilesUniqueSignalNamesNoComponents)
{
EXPECT_EQ(0, CreateCode("vss_unique_names.csv", "generated0", false));
// files created by VSS_DifferentVDandBSSingleSignals.csv
// find expected IDL files and check number of files in folder 'generated0'
std::filesystem::path allFilesPath = GetExecDirectory() / "generated0";
std::filesystem::path vssFilePath = allFilesPath / "vss_files";
std::filesystem::path signalIdentifierVDFilePath = vssFilePath / "signal_identifier.h";
std::filesystem::path summaryVDFilePath = vssFilePath / "summary.txt";
EXPECT_TRUE(std::filesystem::exists(summaryVDFilePath));
EXPECT_TRUE(std::filesystem::exists(signalIdentifierVDFilePath));
std::uintmax_t allFilesCount = CountNumberOfFiles(allFilesPath);
// 4 signals, but they are combined in the same vss definition so we have 1 rx and 1 tx
uint32_t signals = 4; // 8 header files *.h + 0 cpp files *.cpp + 0 cmake files + 8 *.idl + 2 * identifier.h + 2 * summary.txt
uint32_t expected = 2 * signals + 2;
EXPECT_EQ(allFilesCount, expected);
auto result = CompileIDLFiles(allFilesPath);
EXPECT_EQ(0, result);
DeletePSAndSerdesFolder(vssFilePath); // created by the idl compiler
allFilesCount = CountNumberOfFiles(allFilesPath);
EXPECT_EQ(allFilesCount, expected + (2 * signals)); // + compiled header files
}
TEST_F(VSSUtilTest, ValidateGeneratedFilesUniqueSignalNames)
{
EXPECT_EQ(0, CreateCode("vss_unique_names.csv", "generated1", true));
// files created by VSS_DifferentVDandBSSingleSignals.csv
// find expected IDL files and check number of files in folder 'generated1'
std::filesystem::path allFilesPath = GetExecDirectory() / "generated1";
std::filesystem::path vssFilePath = allFilesPath / "vss_files";
std::filesystem::path signalIdentifierVDFilePath = vssFilePath / "signal_identifier.h";
std::filesystem::path summaryVDFilePath = vssFilePath / "summary.txt";
EXPECT_TRUE(std::filesystem::exists(summaryVDFilePath));
EXPECT_TRUE(std::filesystem::exists(signalIdentifierVDFilePath));
std::uintmax_t allFilesCount = CountNumberOfFiles(allFilesPath);
// 4 signals, but they are combined in the same vss definition so we have 1 rx and 1 tx
uint32_t signals = 4; // 2 header files *.h + 2 cpp files *.cpp + 2 cmake files + 2 *.idl + 2 * identifier.h + 2 * summary.txt
uint32_t expected = 2 * signals + 2 * signals + 2 *signals + (2 * signals) + 2;
EXPECT_EQ(allFilesCount, expected);
auto result = CompileIDLFiles(allFilesPath);
EXPECT_EQ(0, result);
DeletePSAndSerdesFolder(vssFilePath); // created by the idl compiler
allFilesCount = CountNumberOfFiles(allFilesPath);
EXPECT_EQ(allFilesCount, expected + (2 * signals)); // + compiled header files
}
TEST_F(VSSUtilTest, ValidateGeneratedFilesCombinedSignalNames)
{
EXPECT_EQ(0, CreateCode("vss_multiple_names.csv", "generated2", true));
// files created by VSS_DifferentVDandBSMultipleSignals.csv
// find expected IDL files and check number of files in folder 'generated2'
std::filesystem::path allFilesPath = GetExecDirectory() / "generated2";
std::filesystem::path vssFilePath = allFilesPath / "vss_files";
std::filesystem::path signalIdentifierVDFilePath = vssFilePath / "signal_identifier.h";
std::filesystem::path summaryVDFilePath = vssFilePath / "summary.txt";
EXPECT_TRUE(std::filesystem::exists(summaryVDFilePath));
EXPECT_TRUE(std::filesystem::exists(signalIdentifierVDFilePath));
std::uintmax_t allFilesCount = CountNumberOfFiles(allFilesPath);
// 4 signals, but they are combined in the same vss definition so we have 1 rx and 1 tx
uint32_t signals = 2; // 2 signals = 4 *.h + 4 *.cpp + 4 cmakelists + 4 *.idl + 2 * identifier.h + 2 * summary.txt
uint32_t expected = (2 * signals) + (2 * signals) + (2 * signals) + (2 * signals) + 2;
EXPECT_EQ(allFilesCount, expected);
EXPECT_EQ(0, CompileIDLFiles(allFilesPath));
DeletePSAndSerdesFolder(vssFilePath); // created by the idl compiler
allFilesCount = CountNumberOfFiles(allFilesPath);
EXPECT_EQ(allFilesCount, expected + (2 * signals));
}
extern "C" int main(int argc, char* argv[])
{
CProcessWatchdog watchdog;
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
return result;
}

View File

@@ -0,0 +1,45 @@
#include "../../global/exec_dir_helper.h"
#include <filesystem>
inline std::filesystem::path GetRootDirectory()
{
std::filesystem::path path = GetExecDirectory();
std::filesystem::path root = path.root_path();
// Check for three existing directories: sdv_services, export and tests. This is the root!
do
{
if (!std::filesystem::exists(path / "sdv_services"))
continue;
if (!std::filesystem::exists(path / "export"))
continue;
if (!std::filesystem::exists(path / "tests"))
continue;
// Root directory found
break;
} while ((path = path.parent_path()), path != root);
;
return path;
}
inline std::filesystem::path GetConfigFilePath(const std::filesystem::path& filename)
{
return GetExecDirectory() / "config" / filename;
}
inline std::string GetConfigFile(const std::filesystem::path& filename)
{
std::filesystem::path configPath = GetConfigFilePath(filename);
std::ifstream inputStream(configPath);
std::string configFileContent((std::istreambuf_iterator<char>(inputStream)), std::istreambuf_iterator<char>());
return configFileContent;
}
inline std::string GetRepositoryServiceModulePath()
{
std::filesystem::path currentPath = GetExecDirectory() / "../../bin/repository_service.sdv";
return currentPath.generic_u8string();
}

View File

@@ -0,0 +1,59 @@
#ifndef GTEST_CUSTOM_H
#define GTEST_CUSTOM_H
#ifdef _MSC_VER
#pragma warning(disable: 4102)
#endif
#define GTEST_HAS_EXCEPTIONS 1
#include <gtest/gtest.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#ifndef countof
/**
* @brief Count the amount of elements in the array.
* @tparam T Array base type.
* @tparam N The amount of elements.
* @return The amount of elements in the array.
*/
template <typename T, int N>
constexpr int countof(T const (&)[N]) noexcept
{
return N;
}
#endif
/**
* @brief Equality test macro for container functions.
*/
#define EXPECT_ARREQ(val1, ...) { bool b = val1 == decltype(val1)({__VA_ARGS__}); EXPECT_TRUE(b); }
/**
* @brief Unequality test macro for container functions.
*/
#define EXPECT_ARRNE(val1, ...) { bool b = val1 == decltype(val1)({__VA_ARGS__}); EXPECT_FALSE(b); }
/**
* @brief Check for equality fo floating point values.
*/
#define EXPECT_FPEQ(val1, val2) EXPECT_TRUE(std::fabs(val1 - val2) < std::numeric_limits<decltype(val1)>::epsilon());
#include "simple_cpp_decomposer.h"
/**
* @brief Compare CPP code for equality.
*/
#define EXPECT_CPPEQ(s1, s2) \
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperCPPEQ, s1, s2)
/**
* @brief Compare CPP code for inequality.
*/
#define EXPECT_CPPNE(s1, s2) \
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperCPPNE, s1, s2)
#endif // ! defined GTEST_CUSTOM_H

View File

@@ -0,0 +1,112 @@
#if defined(_WIN32)
#include "../../global/exec_dir_helper.h"
inline int GetLoggerFilesCount(const std::string& prefix)
{
int count = 0;
std::string path = GetExecDirectory().generic_string();
for (const auto& entry : std::filesystem::directory_iterator(path))
{
std::string filename = entry.path().filename().generic_string().c_str();
if (filename.rfind(prefix, 0) == 0)
{
count++;
}
}
return count;
}
inline void DeleteLoggerFile(const std::string& filename)
{
auto path = GetExecDirectory() / filename;
try
{
std::filesystem::remove(path);
} catch (const std::filesystem::filesystem_error&)
{}
}
inline uint32_t GetErrorCountFromLogFile(const std::string& filename)
{
uint32_t errorCount = 0;
auto path = GetExecDirectory() / filename;
std::ifstream infile(path);
if (infile.is_open())
{
std::string line;
while (std::getline(infile, line))
{
size_t foundStart = line.find("Error;");
if (foundStart != std::string::npos)
{
std::cout << line << std::endl;
errorCount++;
}
}
}
if (errorCount != 0)
{
std::cout << "Checking " << filename << ", found: " << std::to_string(errorCount) << std::endl;
}
return errorCount;
}
inline bool FileNameStartsWith(const std::string& fileName, const std::string& startOfLogName)
{
if (!startOfLogName.empty())
{
if (fileName.rfind(startOfLogName, 0) != 0) // returns std::string::npos (i.e. not found)
{
return false;
}
}
return true;
}
inline uint32_t GetStringCountFromLogFiles(const std::string& startOfLogName, const std::string& subString)
{
uint32_t errorCount = 0;
auto path = GetExecDirectory();
for (const auto& entry : std::filesystem::directory_iterator(path))
{
if ((entry.path().extension() == ".log") &&
(FileNameStartsWith(entry.path().filename().string(), startOfLogName)))
{
std::ifstream infile(entry.path());
if (infile.is_open())
{
std::string line;
while (std::getline(infile, line))
{
size_t foundStart = line.find(subString);
if (foundStart != std::string::npos)
{
errorCount++;
}
}
infile.close();
}
}
}
return errorCount;
}
inline uint32_t GetErrorCountFromLogFiles(const std::string& logName) { return GetStringCountFromLogFiles(logName, ";Error;"); }
inline uint32_t GetWarningCountFromLogFiles(const std::string& logName) { return GetStringCountFromLogFiles(logName, "Warning;"); }
inline uint32_t GetTraceCountFromLogFiles(const std::string& logName) { return GetStringCountFromLogFiles(logName, "Trace;"); }
#else
inline int GetLoggerFilesCount(const std::string& ) { return 0; }
inline void DeleteLoggerFile(const std::string& ) { return; }
inline uint32_t GetErrorCountFromLogFile(const std::string&) { return 0; }
inline uint32_t GetErrorCountFromLogFiles(const std::string&) { return 0; }
inline uint32_t GetWarningCountFromLogFiles(const std::string&) { return 0; }
inline uint32_t GetTraceCountFromLogFiles(const std::string&) { return 0; }
#endif

View File

@@ -0,0 +1,96 @@
#ifndef SIMPLE_CPP_DECOMPOSER_H
#define SIMPLE_CPP_DECOMPOSER_H
#include <list>
#include <string>
/**
* @brief Decomposes C++ code into text chunks. Supports simple grammar.
*/
class CSimpleCppDecomposer
{
public:
/**
* @brief Constructor
* @param[in] rssCppCode Reference to the source code to decompose.
*/
CSimpleCppDecomposer(const std::string& rssCppCode);
/**
* @brief Get the list of decomposed source code chunks.
* @return A reference to the list of source code chunks.
*/
const std::list<std::string>& GetDecomposedCode() const;
/**
* @brief Compare with another decomposed code for equality.
* @param[in] rdecompChunk Reference to the decomposed chunk of code to use for this comparison.
* @return Returns 'true' when equal; 'false' when not.
*/
bool operator==(const CSimpleCppDecomposer& rdecompChunk) const;
/**
* @brief Compare with another decomposed code for un-equality.
* @param[in] rdecompChunk Reference to the decomposed chunk of code to use for this comparison.
* @return Returns 'true' when not equal; 'false' when equal.
*/
bool operator!=(const CSimpleCppDecomposer& rdecompChunk) const;
private:
/**
* @brief Iterate through the source code collecting the source code chunks.
*/
void Process();
/**
* @brief Skip whitespace
*/
void SkipWhitespace();
/**
* @brief Skip the rest of the line.
*/
void SkipLine();
/**
*@brief Skip C-comments.
*/
void SkipComment();
/**
* @brief Process text and numbers
*/
void ProcessText();
/**
* @brief Process strings
*/
void ProcessString();
/**
* @brief Process symbols.
*/
void ProcessSymbol();
std::string m_ssCode; ///< Current position within the source code.
size_t m_nPos = 0; ///< The current position.
std::list<std::string> m_lstCode; ///< Decomposed code.
bool m_bNewLine = true; ///< Set when a new line has occurred (ignoring any whitespace).
};
namespace testing::internal
{
// Additional helpers for testing C++ code
GTEST_API_ AssertionResult CmpHelperCPPEQ(const char* szLeftExpression, const char* szRightExpression,
const char* szLeft, const char* szRight);
GTEST_API_ AssertionResult CmpHelperCPPNE(const char* szLeftExpression, const char* szRightExpression,
const char* szLeft, const char* szRight);
GTEST_API_ AssertionResult CmpHelperCPPEQ(const char* szLeftExpression, const char* szRightExpression,
const std::string& rssLeft, const std::string& rssRight);
GTEST_API_ AssertionResult CmpHelperCPPNE(const char* szLeftExpression, const char* szRightExpression,
const std::string& rssLeft, const std::string& rssRight);
}
#include "simple_cpp_decomposer.inl"
#endif //! SIMPLE_CPP_DECOMPOSER_H

View File

@@ -0,0 +1,241 @@
#ifndef SIMPLE_CPP_DECOMPOSER_INL
#define SIMPLE_CPP_DECOMPOSER_INL
#ifndef SIMPLE_CPP_DECOMPOSER_H
#error Do not include "simple_cpp_composer.inl" directly. Include "simple_cpp_composer.h" instead!
#endif
#include <cassert>
namespace testing::internal
{
// Additional helpers for testing C++ code
inline GTEST_API_ AssertionResult CmpHelperCPPEQ(const char* szLeftExpression, const char* szRightExpression,
const char* szLeft, const char* szRight)
{
if (CSimpleCppDecomposer(szLeft) == CSimpleCppDecomposer(szRight))
{
return AssertionSuccess();
}
return EqFailure(szLeftExpression, szRightExpression, PrintToString(szLeft), PrintToString(szRight), false);
}
inline GTEST_API_ AssertionResult CmpHelperCPPNE(const char* szLeftExpression, const char* szRightExpression,
const char* szLeft, const char* szRight)
{
if (CSimpleCppDecomposer(szLeft) != CSimpleCppDecomposer(szRight))
{
return AssertionSuccess();
}
return EqFailure(szLeftExpression, szRightExpression, PrintToString(szLeft), PrintToString(szRight), false);
}
inline GTEST_API_ AssertionResult CmpHelperCPPEQ(const char* szLeftExpression, const char* szRightExpression,
const std::string& rssLeft, const std::string& rssRight)
{
if (CSimpleCppDecomposer(rssLeft) == CSimpleCppDecomposer(rssRight))
{
return AssertionSuccess();
}
return EqFailure(szLeftExpression, szRightExpression, PrintToString(rssLeft), PrintToString(rssRight), false);
}
inline GTEST_API_ AssertionResult CmpHelperCPPNE(const char* szLeftExpression, const char* szRightExpression,
const std::string& rssLeft, const std::string& rssRight)
{
if (CSimpleCppDecomposer(rssLeft) != CSimpleCppDecomposer(rssRight))
{
return AssertionSuccess();
}
return EqFailure(szLeftExpression, szRightExpression, PrintToString(rssLeft), PrintToString(rssRight), false);
}
}
inline CSimpleCppDecomposer::CSimpleCppDecomposer(const std::string& rssCppCode) : m_ssCode(rssCppCode)
{
Process();
}
inline const std::list<std::string>& CSimpleCppDecomposer::GetDecomposedCode() const
{
return m_lstCode;
}
inline bool CSimpleCppDecomposer::operator==(const CSimpleCppDecomposer& rdecompChunk) const
{
return m_lstCode == rdecompChunk.GetDecomposedCode();
}
inline bool CSimpleCppDecomposer::operator!=(const CSimpleCppDecomposer& rdecompChunk) const
{
return m_lstCode != rdecompChunk.GetDecomposedCode();
}
inline void CSimpleCppDecomposer::Process()
{
while (m_nPos < m_ssCode.size())
{
// First skip whitespace...
SkipWhitespace();
if (m_nPos >= m_ssCode.size()) break;
// Check for preproc directives... skip those
if (m_ssCode[m_nPos] == '#')
{
SkipLine();
continue;
}
// Check for comment
if (m_ssCode[m_nPos] == '/' && (m_ssCode[m_nPos + 1] == '/' || m_ssCode[m_nPos + 1] == '*'))
{
SkipComment();
continue;
}
// If the current character represents an underscore a string or a number, it is a keyword, variable, prefix or a number.
if (std::isalnum(m_ssCode[m_nPos]) || m_ssCode[m_nPos] == '_')
{
ProcessText();
continue;
}
// If the current character represents a quote (single or double), it is a string or a character.
// NOTE: Cannot deal with raw strings
if (m_ssCode[m_nPos] == '\"' || m_ssCode[m_nPos] == '\'')
{
ProcessString();
continue;
}
// If the current character is anything else, it represents a symbol.
ProcessSymbol();
}
}
inline void CSimpleCppDecomposer::SkipWhitespace()
{
while (m_nPos < m_ssCode.size() && std::isspace(m_ssCode[m_nPos]))
{
// Skip concatinating lines (not setting the new line flag).
if (m_ssCode[m_nPos] == '\\' && m_ssCode[m_nPos + 1] == '\r' && m_ssCode[m_nPos + 2] == '\n')
{
m_nPos += 3;
continue;
}
else if (m_ssCode[m_nPos] == '\\' && m_ssCode[m_nPos + 2] == '\n')
{
m_nPos += 2;
continue;
}
// Remember the new line
if (m_ssCode[m_nPos] == '\n') m_bNewLine = true;
// Skip the whitespace
m_nPos++;
}
}
inline void CSimpleCppDecomposer::SkipLine()
{
while (m_nPos < m_ssCode.size())
{
// Ignore the line ending with concatinating lines
if (m_ssCode[m_nPos] == '\\' && m_ssCode[m_nPos + 1] == '\r' && m_ssCode[m_nPos + 2] == '\n')
{
m_nPos += 3;
continue;
}
else if (m_ssCode[m_nPos] == '\\' && m_ssCode[m_nPos + 2] == '\n')
{
m_nPos += 2;
continue;
}
// Finished when a new line has been reached
if (m_ssCode[m_nPos] == '\n')
{
m_nPos++; // Skip the newline
m_bNewLine = true;
break;
}
// Skip the character
m_nPos++;
}
}
inline void CSimpleCppDecomposer::SkipComment()
{
if (m_nPos >= m_ssCode.size()) return;
if (m_ssCode[m_nPos] != '/') return;
if (m_ssCode[m_nPos + 1] == '/') // C++ comment
{
SkipLine();
return;
}
if (m_ssCode[m_nPos + 1] != '*') return;
// C comment
m_nPos += 2;
while (m_nPos < m_ssCode.size())
{
// End of comment
if (m_ssCode[m_nPos] == '*' && m_ssCode[m_nPos + 1] == '/')
{
m_nPos += 2;
break;
}
// Ignore the line ending with concatinating lines
if (m_ssCode[m_nPos] == '\\' && m_ssCode[m_nPos + 1] == '\r' && m_ssCode[m_nPos + 2] == '\n')
{
m_nPos += 3;
continue;
}
else if (m_ssCode[m_nPos] == '\\' && m_ssCode[m_nPos + 2] == '\n')
{
m_nPos += 2;
continue;
}
// Detect a new line
if (m_ssCode[m_nPos] == '\n') m_bNewLine = true;
// Skip the character
m_nPos++;
}
}
inline void CSimpleCppDecomposer::ProcessText()
{
m_bNewLine = false;
size_t nStart = m_nPos;
while (m_nPos < m_ssCode.size() && (std::isalnum(m_ssCode[m_nPos]) || m_ssCode[m_nPos] == '_'))
m_nPos++;
if (m_nPos == nStart) return;
m_lstCode.push_back(m_ssCode.substr(nStart, m_nPos - nStart));
}
inline void CSimpleCppDecomposer::ProcessString()
{
m_bNewLine = false;
size_t nStart = m_nPos;
m_nPos++; // Skip quote
while (m_nPos < m_ssCode.size() && m_ssCode[m_nPos] != '\"' && m_ssCode[m_nPos] == '\'') m_nPos++;
if (m_nPos < m_ssCode.size()) m_nPos++; // Skip quote
if (m_nPos == nStart) return;
m_lstCode.push_back(m_ssCode.substr(nStart, m_nPos - nStart));
}
inline void CSimpleCppDecomposer::ProcessSymbol()
{
m_bNewLine = false;
if (m_nPos >= m_ssCode.size()) return;
m_lstCode.push_back(std::string(1, m_ssCode[m_nPos]));
m_nPos++; // Skip symbol
}
#endif // !defined SIMPLE_CPP_DECOMPOSER_INL

View File

@@ -0,0 +1,103 @@
#ifndef TEST_WATCHDOG_H
#define TEST_WATCHDOG_H
#include <thread>
#include <cstdint>
#include <iostream>
#ifdef _WIN32
// Prevent reassignment of "interface"
#pragma push_macro("interface")
#undef interface
#ifndef NOMINMAX
#define NOMINMAX
#endif
// Include windows headers
#include <WinSock2.h>
#include <Windows.h>
#include <objbase.h>
// Use previous assignment of "interface"
#pragma pop_macro("interface")
// Remove "GetObject" assignment
#ifdef GetObject
#undef GetObject
#endif
// Remove "GetClassInfo" assignment
#ifdef GetClassInfo
#undef GetClassInfo
#endif
#elif defined __unix__
#include <signal.h>
#include <unistd.h>
#else
#error The OS is not supported!
#endif
/**
* @brief Test watchdog class; ends test process when runtime duration has superseded.
*/
class CProcessWatchdog
{
public:
/**
* @brief Constructor
* @param[in] m_iWatchdogTimeS The duration the watchdog is monitoring before process termination in seconds (default 300s).
*/
CProcessWatchdog(int64_t iWatchdogTimeS = 300ll)
{
m_threadWatchdog = std::thread(&CProcessWatchdog::WatchdogThreadFunc, this, iWatchdogTimeS );
}
/**
* @breif Destructor; cancels the watch thread.
*/
~CProcessWatchdog()
{
m_bTerminateWatchdog = true;
if (m_threadWatchdog.joinable())
m_threadWatchdog.join();
}
private:
/**
* @brief Watch thread function.
* @param[in] iWatchdogTimeS The duration the watchdog is monitoring before process termination in seconds (default 120s).
*/
void WatchdogThreadFunc(int64_t iWatchdogTimeS = 120ll)
{
// Run for the most the set time; then terminate...
auto tpStart = std::chrono::steady_clock::now();
while (!m_bTerminateWatchdog)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
auto tpNow = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::seconds>(tpNow - tpStart).count() > iWatchdogTimeS)
{
std::cerr << "ERROR PROCESS WATCHDOG: POTENTIAL DEADLOCK DETECTED - TERMINATION ENFORCED!!!" << std::endl;
std::cerr.flush();
#ifdef _WIN32
// Get the current process handle
HANDLE hProcess = GetCurrentProcess();
// Terminate the current process with exit code -100
TerminateProcess(hProcess, static_cast<UINT>(-100));
#elif defined __unix__
// Send SIGTERM signal to the current process
kill(getpid(), SIGTERM);
#else
#error The OS is not supported!
#endif
}
}
}
bool m_bTerminateWatchdog = false; ///< When set, allows the thread to terminate.
std::thread m_threadWatchdog; ///< The watchdog thread.
};
#endif // !defined TEST_WATCHDOG_H

View File

@@ -0,0 +1,40 @@
################################## ATTENTION #################################
# Shell Script to execute the tests on Linux #
# Adjust the permission with: chmod +x loop_test_runner_linux.sh #
# Run the script with: ./loop_test_runner_linux.sh <TestName> <NumberOfRuns> #
# or: bash ./loop_test_runner_linux.sh <TestName> <NumberOfRuns> #
##############################################################################
#!/bin/bash
# Check if the correct number of arguments is provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <TestName> <NumberOfRuns>"
echo "Example: $0 UnitTest_SharedMemConnectTests 1000"
exit 1
fi
# Get the test name and number of runs from command-line arguments
TEST_NAME="$1"
MAX_RUNS="$2"
# Build the full path to the test executable
TARGET_TEST="../build/tests/bin/$TEST_NAME"
# Check if the test executable exists
if [ -f "$TARGET_TEST" ]; then
echo -e "\nStarting looped execution of $TARGET_TEST to catch intermittent failures..."
# Loop the test execution for the specified number of times
for i in $(seq 1 $MAX_RUNS); do
echo -e "\nRun #$i"
$TARGET_TEST
if [ $? -ne 0 ]; then
echo -e "\nTest failed on run #$i"
break
fi
done
else
echo "Target test $TARGET_TEST not found!"
exit 1
fi

View File

@@ -0,0 +1,36 @@
<#
.SYNOPSIS
PowerShell script to loop a specific test executable multiple times to catch intermittent failures.
.DESCRIPTION
Usage: .\loop_test_runner.ps1 <TestName> <NumberOfRuns>
Example: .\loop_test_runner.ps1 UnitTest_SharedMemConnectTests.exe 1000
#>
param (
[Parameter(Mandatory = $true)]
[string]$TestName,
[Parameter(Mandatory = $true)]
[int]$NumberOfRuns
)
# Build the full path to the test executable
$TargetTest = Join-Path "..\build\tests\bin" $TestName
# Check if the test executable exists
if (Test-Path $TargetTest) {
Write-Host "`nStarting looped execution of $TargetTest to catch intermittent failures..." -ForegroundColor Cyan
for ($i = 1; $i -le $NumberOfRuns; $i++) {
Write-Host "`nRun #$i" -ForegroundColor Yellow
& $TargetTest
if ($LASTEXITCODE -ne 0) {
Write-Host "`nTest failed on run #$i" -ForegroundColor Red
break
}
}
} else {
Write-Host "Target test $TargetTest not found!" -ForegroundColor Red
exit 1
}

View File

@@ -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"

View 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)

View 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.

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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();
}

View File

@@ -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();
}

View 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;
}

View 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;
}

View File

@@ -0,0 +1,40 @@
############################## ATTENTION ##############################
# Shell Script to execute the tests on Linux #
# Adjust the permission with: chmod +x run_tests_on_linux.sh #
# Run the script with: ./run_tests_on_linux.sh #
# or: bash ./run_tests_on_linux.sh #
#######################################################################
#!/bin/bash
# Define the directory to search
directory="bin"
# Sammeln der ausführbaren Dateien in einem Array
IFS=$'\n' read -r -d '' -a RUN_TESTS < <(find bin -type f \( -name "ComponentTest_*" -o -name "UnitTest_*" \) -executable -exec sh -c 'for file; do [ "${file##*.}" = "$file" ] && echo "$file"; done' sh {} \; && printf '\0')
# Array to hold failed tests
FAILED_TESTS=()
# Run all tests and capture output
for TEST_EXECUTABLE in "${RUN_TESTS[@]}"; do
if [ -f "$TEST_EXECUTABLE" ]; then
OUTPUT=$($TEST_EXECUTABLE --gtest_output=xml:../bin/$(basename $TEST_EXECUTABLE).xml 2>&1)
echo "$OUTPUT"
if echo "$OUTPUT" | grep -q "FAILED"; then
FAILED_TESTS+=("$TEST_EXECUTABLE")
fi
else
echo "Executable $TEST_EXECUTABLE not found!"
fi
done
# List all failed tests at the end
if [ ${#FAILED_TESTS[@]} -ne 0 ]; then
echo -e "\n\e[31mFailed tests:\e[0m"
for TEST in "${FAILED_TESTS[@]}"; do
echo -e "\e[31m$TEST\e[0m"
done
else
echo -e "\n\e[32mAll tests passed!\e[0m"
fi

View File

@@ -0,0 +1,37 @@
# PowerShell Script to execute the tests on Windows
# Save this script as run_tests_on_windows.ps1
# Run the script with: .\run_tests_on_windows.ps1
# Set the paths to the executables
$runTests = Get-ChildItem -Path "bin" -Filter "*.exe" | Where-Object {
$_.Name -like "ComponentTest_*" -or $_.Name -like "UnitTest_*"
} | ForEach-Object {
$_.FullName
}
# Array to hold failed tests
$failedTests = @()
# Run all tests and capture output
foreach ($testExecutable in $runTests) {
if (Test-Path $testExecutable) {
$output = & $testExecutable --gtest_output=xml:../bin/$(Split-Path -Leaf $testExecutable).xml 2>&1
Write-Output $output
if ($output -match "FAILED") {
$failedTests += $testExecutable
}
} else {
Write-Output "Executable $testExecutable not found!"
}
}
# List all failed tests at the end
if ($failedTests.Count -ne 0) {
Write-Host "`nFailed tests:" -ForegroundColor Red
foreach ($test in $failedTests) {
Write-Host $test -ForegroundColor Red
}
} else {
Write-Host "`nAll tests passed!" -ForegroundColor Green
}

View File

@@ -0,0 +1,2 @@
# Location of the SDV core library
directory = "../../bin"

View File

@@ -0,0 +1,20 @@
# Define project
project (UnitTest_App_Connect VERSION 1.0 LANGUAGES CXX)
# Compile the source code
add_executable(UnitTest_App_Connect
"main.cpp"
"app_connect_local.cpp")
target_link_libraries(UnitTest_App_Connect ${CMAKE_DL_LIBS} GTest::GTest)
# Add the IDL Compiler unittest
add_test(NAME UnitTest_App_Connect COMMAND UnitTest_App_Connect)
# Execute the test
add_custom_command(TARGET UnitTest_App_Connect POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_App_Connect>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_App_Connect.xml
VERBATIM
)
# Build dependencies
add_dependencies(UnitTest_App_Connect dependency_sdv_components)

View File

@@ -0,0 +1,7 @@
/**
- Default instantiate listener
- Instantiate with specific info
- Multiple instantiate with identical info (failure)
- Multiple instantiate with different info
- Default instantiate client and get connection information
- */

View File

@@ -0,0 +1,19 @@
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#include "../../../global/localmemmgr.h"
/**
* @brief Main function
*/
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
CLocalMemMgr memmgr;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,27 @@
# Define project
project (UnitTest_ASC_Format VERSION 1.0 LANGUAGES CXX)
# Compile the source code
add_executable(UnitTest_ASC_Format
"asc_reader_test.cpp"
"main.cpp"
"asc_writer_test.cpp")
target_link_libraries(UnitTest_ASC_Format ${CMAKE_DL_LIBS} GTest::GTest)
# Add the IDL Compiler unittest
add_test(NAME UnitTest_ASC_Format COMMAND UnitTest_ASC_Format)
# Execute the test
add_custom_command(TARGET UnitTest_ASC_Format POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_ASC_Format>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_ASC_Format.xml
VERBATIM
)
# copy the ASC test file to binary folder
file (COPY ${PROJECT_SOURCE_DIR}/asc_reader_timing_test.asc DESTINATION ${CMAKE_BINARY_DIR}/tests/bin)
file (COPY ${PROJECT_SOURCE_DIR}/asc_reader_test.asc DESTINATION ${CMAKE_BINARY_DIR}/tests/bin)
file (COPY ${PROJECT_SOURCE_DIR}/asc_reader_ext_id_test.asc DESTINATION ${CMAKE_BINARY_DIR}/tests/bin)
file (COPY ${PROJECT_SOURCE_DIR}/asc_reader_canfd_test.asc DESTINATION ${CMAKE_BINARY_DIR}/tests/bin)
# Build dependencies
add_dependencies(UnitTest_ASC_Format dependency_sdv_components)

View File

@@ -0,0 +1,9 @@
date Dez. 3 2014 16:34:20
base hex timestamps absolute
no internal events logged
Begin Triggerblock
3.35516 1 B4323x Rx D 8 72 E4 19 2F 14 00 00 00
3.35522 6 52 Rx D 2 6C 60
3.36716 1 B4323x Rx D 8 73 E5 E9 24 e2 00 00 00
3.36722 CANFD 15 Rx 86 1 0 8 8 48 75 6d 61 6e 69 73 6d 0 0 3000 0 0 0
End TriggerBlock

View File

@@ -0,0 +1,11 @@
date Mon Mai 19 15:37:13.000 2014
base hex timestamps absolute
internal events logged
// version 8.5.0
Begin Triggerblock Mon Mai 19 15:37:13.690 2014
0.590000 1 539 Rx d 1 03 Length 108000 BitCount = 58 ID = 1337
0.619000 1 71x Rx d 1 42 Length 152000 BitCount = 80 ID = 113x
0.690000 1 539 Rx d 1 04 Length 106000 BitCount = 57 ID = 1337
0.690000 log trigger event
0.719000 1 71x Rx d 1 42 Length 152000 BitCount 80 ID 113x
End TriggerBlock

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,512 @@
#include "../../include/gtest_custom.h"
#include "../../../global/ascformat/ascreader.cpp"
#include <iostream>
#include <fstream>
#include "../../../global/exec_dir_helper.h"
TEST(CAscReaderTest, ReadASCFile)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.IsBOF());
EXPECT_TRUE(reader.IsEOF());
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
EXPECT_TRUE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
}
TEST(CAscReaderTest, SingleSampleNavigation)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
// First value
EXPECT_TRUE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.007096);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0xb6ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 5ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x06);
EXPECT_EQ(prSample.first.rguiData[1], 0x06);
EXPECT_EQ(prSample.first.rguiData[2], 0x80);
EXPECT_EQ(prSample.first.rguiData[3], 0x00);
EXPECT_EQ(prSample.first.rguiData[4], 0xc8);
EXPECT_EQ(prSample.first.rguiData[5], 0x00);
// Next value
++reader;
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.007123);
EXPECT_EQ(prSample.first.uiChannel, 2ul);
EXPECT_EQ(prSample.first.uiId, 0x85ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 8ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x00);
EXPECT_EQ(prSample.first.rguiData[1], 0x00);
EXPECT_EQ(prSample.first.rguiData[2], 0x00);
EXPECT_EQ(prSample.first.rguiData[3], 0x00);
EXPECT_EQ(prSample.first.rguiData[4], 0xff);
EXPECT_EQ(prSample.first.rguiData[5], 0xff);
EXPECT_EQ(prSample.first.rguiData[6], 0xf3);
EXPECT_EQ(prSample.first.rguiData[7], 0x1d);
EXPECT_EQ(prSample.first.rguiData[8], 0x00);
// Next value
++reader;
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.007333);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0x19eul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 8ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x00);
EXPECT_EQ(prSample.first.rguiData[1], 0xec);
EXPECT_EQ(prSample.first.rguiData[2], 0xef);
EXPECT_EQ(prSample.first.rguiData[3], 0xfc);
EXPECT_EQ(prSample.first.rguiData[4], 0xff);
EXPECT_EQ(prSample.first.rguiData[5], 0x0c);
EXPECT_EQ(prSample.first.rguiData[6], 0x00);
EXPECT_EQ(prSample.first.rguiData[7], 0x85);
EXPECT_EQ(prSample.first.rguiData[8], 0x00);
// Previous value
--reader;
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.007123);
EXPECT_EQ(prSample.first.uiChannel, 2ul);
EXPECT_EQ(prSample.first.uiId, 0x85ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 8ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x00);
EXPECT_EQ(prSample.first.rguiData[1], 0x00);
EXPECT_EQ(prSample.first.rguiData[2], 0x00);
EXPECT_EQ(prSample.first.rguiData[3], 0x00);
EXPECT_EQ(prSample.first.rguiData[4], 0xff);
EXPECT_EQ(prSample.first.rguiData[5], 0xff);
EXPECT_EQ(prSample.first.rguiData[6], 0xf3);
EXPECT_EQ(prSample.first.rguiData[7], 0x1d);
EXPECT_EQ(prSample.first.rguiData[8], 0x00);
// Previous value
--reader;
EXPECT_TRUE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.007096);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0xb6ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 5ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x06);
EXPECT_EQ(prSample.first.rguiData[1], 0x06);
EXPECT_EQ(prSample.first.rguiData[2], 0x80);
EXPECT_EQ(prSample.first.rguiData[3], 0x00);
EXPECT_EQ(prSample.first.rguiData[4], 0xc8);
EXPECT_EQ(prSample.first.rguiData[5], 0x00);
// Jump to end
reader.JumpEnd();
EXPECT_FALSE(reader.IsBOF());
EXPECT_TRUE(reader.IsEOF());
prSample = reader.Get();
EXPECT_FALSE(prSample.second);
// Jump to begin
reader.JumpBegin();
EXPECT_TRUE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.007096);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0xb6ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 5ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x06);
EXPECT_EQ(prSample.first.rguiData[1], 0x06);
EXPECT_EQ(prSample.first.rguiData[2], 0x80);
EXPECT_EQ(prSample.first.rguiData[3], 0x00);
EXPECT_EQ(prSample.first.rguiData[4], 0xc8);
EXPECT_EQ(prSample.first.rguiData[5], 0x00);
}
TEST(CAscReaderTest, NormalPlayback)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Do measurement
asc::SCanMessage sMsg{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg = rsMsg; }, false);
EXPECT_TRUE(reader.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(250));
reader.StopPlayback();
// Last sent message is the one before the current message.
--reader;
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsg.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsg.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsg.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsg.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsg.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsg.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsg.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsg.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsg.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsg.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsg.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsg.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsg.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsg.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsg.rguiData[8]);
// Time deviation
std::cout << "The current timestamp is " << sMsg.dTimestamp << " (should be somewhat more than 250ms)" << std::endl;
}
TEST(CAscReaderTest, PlaybackRestart)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Do first measurement
asc::SCanMessage sMsg1{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg1 = rsMsg; }, false);
EXPECT_TRUE(reader.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(250));
reader.StopPlayback();
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
// Last sent message is the one before the current message.
--reader;
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsg1.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsg1.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsg1.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsg1.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsg1.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsg1.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsg1.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsg1.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsg1.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsg1.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsg1.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsg1.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsg1.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsg1.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsg1.rguiData[8]);
// Do second measurement
asc::SCanMessage sMsg2{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg2 = rsMsg; }, false);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
reader.StopPlayback();
// Last sent message is the one before the current message.
--reader;
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsg2.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsg2.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsg2.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsg2.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsg2.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsg2.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsg2.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsg2.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsg2.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsg2.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsg2.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsg2.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsg2.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsg2.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsg2.rguiData[8]);
// The time of message 1 should be less than the time of message 2.
EXPECT_LT(sMsg1.dTimestamp, sMsg2.dTimestamp);
}
TEST(CAscReaderTest, PlaybackReset)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Do first measurement
asc::SCanMessage sMsg1{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg1 = rsMsg; }, false);
EXPECT_TRUE(reader.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(250));
reader.StopPlayback();
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
// Last sent message is the one before the current message.
--reader;
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsg1.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsg1.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsg1.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsg1.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsg1.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsg1.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsg1.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsg1.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsg1.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsg1.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsg1.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsg1.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsg1.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsg1.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsg1.rguiData[8]);
// Do second measurement
asc::SCanMessage sMsg2{};
reader.ResetPlayback();
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg2 = rsMsg; }, false);
std::this_thread::sleep_for(std::chrono::milliseconds(125));
reader.StopPlayback();
// Last sent message is the one before the current message.
--reader;
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsg2.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsg2.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsg2.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsg2.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsg2.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsg2.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsg2.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsg2.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsg2.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsg2.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsg2.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsg2.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsg2.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsg2.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsg2.rguiData[8]);
// The time of message 1 should be more than the time of message 2.
EXPECT_GT(sMsg1.dTimestamp, sMsg2.dTimestamp);
}
TEST(CAscReaderTest, FinishPlayback)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Do measurement
reader.JumpEnd();
for (size_t n = 0; n < 150; n++)
--reader;
asc::SCanMessage sMsg{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg = rsMsg; }, false);
EXPECT_TRUE(reader.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(250));
EXPECT_FALSE(reader.PlaybackRunning());
reader.StopPlayback(); // Just in case...
EXPECT_TRUE(reader.IsEOF());
// Last sent message is the one before the current message.
--reader;
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsg.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsg.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsg.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsg.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsg.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsg.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsg.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsg.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsg.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsg.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsg.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsg.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsg.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsg.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsg.rguiData[8]);
}
TEST(CAscReaderTest, RepeatPlayback)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Do a measurement startin at the end
reader.JumpEnd();
for (size_t n = 0; n < 20; n++)
--reader;
asc::SCanMessage sMsgStart = reader.Get().first;
asc::SCanMessage sMsgCurrent{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsgCurrent = rsMsg; }, true);
EXPECT_TRUE(reader.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(250));
reader.StopPlayback();
// Last sent message is the one before the current message.
--reader;
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, sMsgCurrent.dTimestamp);
EXPECT_EQ(prSample.first.uiChannel, sMsgCurrent.uiChannel);
EXPECT_EQ(prSample.first.uiId, sMsgCurrent.uiId);
EXPECT_EQ(prSample.first.bExtended, sMsgCurrent.bExtended);
EXPECT_EQ(prSample.first.eDirection, sMsgCurrent.eDirection);
EXPECT_EQ(prSample.first.uiLength, sMsgCurrent.uiLength);
EXPECT_EQ(prSample.first.rguiData[0], sMsgCurrent.rguiData[0]);
EXPECT_EQ(prSample.first.rguiData[1], sMsgCurrent.rguiData[1]);
EXPECT_EQ(prSample.first.rguiData[2], sMsgCurrent.rguiData[2]);
EXPECT_EQ(prSample.first.rguiData[3], sMsgCurrent.rguiData[3]);
EXPECT_EQ(prSample.first.rguiData[4], sMsgCurrent.rguiData[4]);
EXPECT_EQ(prSample.first.rguiData[5], sMsgCurrent.rguiData[5]);
EXPECT_EQ(prSample.first.rguiData[6], sMsgCurrent.rguiData[6]);
EXPECT_EQ(prSample.first.rguiData[7], sMsgCurrent.rguiData[7]);
EXPECT_EQ(prSample.first.rguiData[8], sMsgCurrent.rguiData[8]);
// The time of start message should be more than the time of the current message.
EXPECT_GT(sMsgStart.dTimestamp, sMsgCurrent.dTimestamp);
}
TEST(CAscReaderTest, RepeatPlaybackCheckLoopExecution)
{
asc::CAscReader readerOneLoop;
EXPECT_TRUE(readerOneLoop.Read(GetExecDirectory() / "asc_reader_timing_test.asc"));
asc::SCanMessage sMsgOneLoop{};
readerOneLoop.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsgOneLoop = rsMsg; }, false);
EXPECT_TRUE(readerOneLoop.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(400));
readerOneLoop.StopPlayback();
EXPECT_TRUE(readerOneLoop.GetLoopCount() == 1);
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_timing_test.asc"));
asc::SCanMessage sMsg{};
reader.StartPlayback([&](const asc::SCanMessage& rsMsg) { sMsg = rsMsg; }, true);
EXPECT_TRUE(reader.PlaybackRunning());
std::this_thread::sleep_for(std::chrono::milliseconds(400));
reader.StopPlayback();
// Second loop must run in the same speed, therfore LoopCount = 2, not mmore
EXPECT_TRUE((readerOneLoop.GetLoopCount() + 1) == reader.GetLoopCount());
}
TEST(CAscReaderTest, ExtendedId)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_ext_id_test.asc"));
// First value
EXPECT_TRUE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.590000);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0x539ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 1ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x03);
EXPECT_EQ(prSample.first.rguiData[1], 0x00);
// Next value
++reader;
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 0.619000);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0x71ul);
EXPECT_TRUE(prSample.first.bExtended);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 1ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x42);
EXPECT_EQ(prSample.first.rguiData[1], 0x00);
}
TEST(CAscReaderTest, CAN_FD)
{
asc::CAscReader reader;
EXPECT_TRUE(reader.Read(GetExecDirectory() / "asc_reader_canfd_test.asc"));
EXPECT_TRUE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
// Skip two values
++reader;
++reader;
// third value
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
auto prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 3.36716);
EXPECT_EQ(prSample.first.uiChannel, 1ul);
EXPECT_EQ(prSample.first.uiId, 0xB4323ul);
EXPECT_TRUE(prSample.first.bExtended);
EXPECT_FALSE(prSample.first.bCanFd);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 8ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x73);
EXPECT_EQ(prSample.first.rguiData[1], 0xe5);
EXPECT_EQ(prSample.first.rguiData[2], 0xe9);
EXPECT_EQ(prSample.first.rguiData[3], 0x24);
EXPECT_EQ(prSample.first.rguiData[4], 0xe2);
EXPECT_EQ(prSample.first.rguiData[5], 0x00);
EXPECT_EQ(prSample.first.rguiData[6], 0x00);
EXPECT_EQ(prSample.first.rguiData[7], 0x00);
EXPECT_EQ(prSample.first.rguiData[8], 0x00);
// Next value
++reader;
EXPECT_FALSE(reader.IsBOF());
EXPECT_FALSE(reader.IsEOF());
prSample = reader.Get();
EXPECT_TRUE(prSample.second);
EXPECT_EQ(prSample.first.dTimestamp, 3.36722);
EXPECT_EQ(prSample.first.uiChannel, 15ul);
EXPECT_EQ(prSample.first.uiId, 0x86ul);
EXPECT_FALSE(prSample.first.bExtended);
EXPECT_TRUE(prSample.first.bCanFd);
EXPECT_EQ(prSample.first.eDirection, asc::SCanMessage::EDirection::rx);
EXPECT_EQ(prSample.first.uiLength, 8ul);
EXPECT_EQ(prSample.first.rguiData[0], 0x48);
EXPECT_EQ(prSample.first.rguiData[1], 0x75);
EXPECT_EQ(prSample.first.rguiData[2], 0x6d);
EXPECT_EQ(prSample.first.rguiData[3], 0x61);
EXPECT_EQ(prSample.first.rguiData[4], 0x6e);
EXPECT_EQ(prSample.first.rguiData[5], 0x69);
EXPECT_EQ(prSample.first.rguiData[6], 0x73);
EXPECT_EQ(prSample.first.rguiData[7], 0x6d);
EXPECT_EQ(prSample.first.rguiData[8], 0x00);
}

View File

@@ -0,0 +1,15 @@
date Wed Jul 28 06:47:19 pm 2010
base hex timestamps absolute
internal events logged
// version 7.0.1
Begin Triggerblock Wed Jul 28 06:47:19 pm 2010
0.000000 Start of measurement
0.005502 CAN 1 Status:chip status error active
0.005675 CAN 2 Status:chip status error active
0.007096 1 B6 Rx d 5 06 06 80 00 C8
0.007123 2 85 Rx d 8 00 00 00 00 FF FF F3 1D
0.007333 1 19E Rx d 8 00 EC EF FC FF 0C 00 85
0.110300 2 D8 Rx d 8 01 80 00 FF F8 7F 05 34
0.210421 1 A8 Rx d 8 EE 45 01 00 00 00 00 00
0.310541 2 E3 Rx d 8 00 80 10 00 FE 7F 05 24
End TriggerBlock

View File

@@ -0,0 +1,224 @@
#include "../../include/gtest_custom.h"
#include "../../../global/ascformat/ascwriter.cpp"
#include <iostream>
#include <fstream>
#include "../../../global/exec_dir_helper.h"
#include <support/sdv_test_macro.h>
TEST(CAscWriterTest, AddSamplesDirect)
{
asc::CAscReader readerGroundThruth;
EXPECT_TRUE(readerGroundThruth.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Add 20 samples
asc::CAscWriter writer;
for (size_t n = 0; n < 20; n++)
{
auto prSample = readerGroundThruth.Get();
EXPECT_TRUE(prSample.second);
writer.AddSample(prSample.first);
++readerGroundThruth;
}
// Write the samples
writer.Write(GetExecDirectory() / "asc_writer_test.asc");
// Read the samples
asc::CAscReader readerGenerate;
EXPECT_TRUE(readerGenerate.Read(GetExecDirectory() / "asc_writer_test.asc"));
// Check whether the 20 samples correspond to the original samples
readerGroundThruth.JumpBegin();
while (!readerGenerate.IsEOF())
{
auto prSampleGroundTruth = readerGroundThruth.Get();
EXPECT_TRUE(prSampleGroundTruth.second);
auto prSampleGenerated = readerGenerate.Get();
EXPECT_EQ(prSampleGroundTruth.first.dTimestamp, prSampleGenerated.first.dTimestamp);
EXPECT_EQ(prSampleGroundTruth.first.uiChannel, prSampleGenerated.first.uiChannel);
EXPECT_EQ(prSampleGroundTruth.first.uiId, prSampleGenerated.first.uiId);
EXPECT_EQ(prSampleGroundTruth.first.bExtended, prSampleGenerated.first.bExtended);
EXPECT_EQ(prSampleGroundTruth.first.eDirection, prSampleGenerated.first.eDirection);
EXPECT_EQ(prSampleGroundTruth.first.uiLength, prSampleGenerated.first.uiLength);
for (size_t nIndex = 0; nIndex < 64; nIndex++)
EXPECT_EQ(prSampleGroundTruth.first.rguiData[nIndex], prSampleGenerated.first.rguiData[nIndex]);
++readerGroundThruth;
++readerGenerate;
}
}
TEST(CAscWriterTest, AddTimedSamples)
{
asc::CAscReader readerGroundThruth;
EXPECT_TRUE(readerGroundThruth.Read(GetExecDirectory() / "asc_reader_test.asc"));
// Skip 100 samples
for (size_t n = 0; n < 100; n++)
++readerGroundThruth;
EXPECT_FALSE(readerGroundThruth.IsBOF());
EXPECT_FALSE(readerGroundThruth.IsEOF());
// Start the timer
asc::CAscWriter writer;
writer.StartTimer();
// Add 250ms of samples
readerGroundThruth.StartPlayback([&](const asc::SCanMessage& rsSample)
{
asc::SCanMessage sSampleCopy(rsSample);
sSampleCopy.dTimestamp = 0.000;
writer.AddSample(sSampleCopy);
}, false);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
readerGroundThruth.StopPlayback();
// Write the samples
writer.Write(GetExecDirectory() / "asc_writer_test.asc");
// Read the samples
asc::CAscReader readerGenerate;
EXPECT_TRUE(readerGenerate.Read(GetExecDirectory() / "asc_writer_test.asc"));
// Start at the 101st sample
readerGroundThruth.JumpBegin();
for (size_t n = 0; n < 100; n++)
++readerGroundThruth;
auto fnRound = [](double dTimestamp) { return std::round(dTimestamp * 1000.0) / 1000.0; };
// Check whether the samples correspond to the original samples, except for the generated timestamp
double dLastTSGroundThruth = fnRound(readerGroundThruth.Get().first.dTimestamp);
double dLastTSGenerated = fnRound(readerGenerate.Get().first.dTimestamp);
++readerGroundThruth;
++readerGenerate;
while (!readerGenerate.IsEOF())
{
auto prSampleGroundTruth = readerGroundThruth.Get();
EXPECT_TRUE(prSampleGroundTruth.second);
auto prSampleGenerated = readerGenerate.Get();
// Delta timestamp should not differ more than +/- 2 ms.
double dDeltaTSGroundThruth = fnRound(readerGroundThruth.Get().first.dTimestamp) - dLastTSGroundThruth;
dLastTSGroundThruth = fnRound(readerGroundThruth.Get().first.dTimestamp);
double dDeltaTSGenerated = fnRound(readerGenerate.Get().first.dTimestamp) - dLastTSGenerated;
dLastTSGenerated = fnRound(readerGenerate.Get().first.dTimestamp);
if (dDeltaTSGenerated < dDeltaTSGroundThruth - 0.002)
{
if(SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_TIMING_EXPECT_GE(dDeltaTSGenerated, dDeltaTSGroundThruth - 0.002, sdv::TEST::WarningLevel::WARNING_REDUCED);
else
SDV_TIMING_EXPECT_GE(dDeltaTSGenerated, dDeltaTSGroundThruth - 0.002, sdv::TEST::WarningLevel::WARNING_ENABLED);
}
if (dDeltaTSGenerated > dDeltaTSGroundThruth + 0.002)
{
if(SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_TIMING_EXPECT_LE(dDeltaTSGenerated, dDeltaTSGroundThruth + 0.002, sdv::TEST::WarningLevel::WARNING_REDUCED);
else
SDV_TIMING_EXPECT_LE(dDeltaTSGenerated, dDeltaTSGroundThruth + 0.002, sdv::TEST::WarningLevel::WARNING_ENABLED);
}
std::cout << "TIMING: Expected generated timestamp <= ground truth + 2ms (generated=" << dDeltaTSGenerated << "ms, ground truth=" << dDeltaTSGroundThruth << ")..." << std::endl;
EXPECT_EQ(prSampleGroundTruth.first.uiChannel, prSampleGenerated.first.uiChannel);
EXPECT_EQ(prSampleGroundTruth.first.uiId, prSampleGenerated.first.uiId);
EXPECT_EQ(prSampleGroundTruth.first.bExtended, prSampleGenerated.first.bExtended);
EXPECT_EQ(prSampleGroundTruth.first.eDirection, prSampleGenerated.first.eDirection);
EXPECT_EQ(prSampleGroundTruth.first.uiLength, prSampleGenerated.first.uiLength);
for (size_t nIndex = 0; nIndex < 64; nIndex++)
EXPECT_EQ(prSampleGroundTruth.first.rguiData[nIndex], prSampleGenerated.first.rguiData[nIndex]);
++readerGroundThruth;
++readerGenerate;
}
}
TEST(CAscWriterTest, ExtendedID)
{
asc::CAscReader readerGroundThruth;
SDV_EXPECT_TRUE(readerGroundThruth.Read(GetExecDirectory() / "asc_reader_ext_id_test.asc"), sdv::TEST::WarningLevel::WARNING_REDUCED);
// Add all samples
asc::CAscWriter writer;
while (!readerGroundThruth.IsEOF())
{
auto prSample = readerGroundThruth.Get();
EXPECT_TRUE(prSample.second);
writer.AddSample(prSample.first);
++readerGroundThruth;
}
// Write the samples
writer.Write(GetExecDirectory() / "asc_writer_test.asc");
// Read the samples
asc::CAscReader readerGenerate;
EXPECT_TRUE(readerGenerate.Read(GetExecDirectory() / "asc_writer_test.asc"));
// Check whether the samples correspond to the original samples
readerGroundThruth.JumpBegin();
while (!readerGenerate.IsEOF())
{
auto prSampleGroundTruth = readerGroundThruth.Get();
EXPECT_TRUE(prSampleGroundTruth.second);
auto prSampleGenerated = readerGenerate.Get();
EXPECT_EQ(prSampleGroundTruth.first.dTimestamp, prSampleGenerated.first.dTimestamp);
EXPECT_EQ(prSampleGroundTruth.first.uiChannel, prSampleGenerated.first.uiChannel);
EXPECT_EQ(prSampleGroundTruth.first.uiId, prSampleGenerated.first.uiId);
EXPECT_EQ(prSampleGroundTruth.first.bExtended, prSampleGenerated.first.bExtended);
EXPECT_EQ(prSampleGroundTruth.first.eDirection, prSampleGenerated.first.eDirection);
EXPECT_EQ(prSampleGroundTruth.first.uiLength, prSampleGenerated.first.uiLength);
for (size_t nIndex = 0; nIndex < 64; nIndex++)
EXPECT_EQ(prSampleGroundTruth.first.rguiData[nIndex], prSampleGenerated.first.rguiData[nIndex]);
++readerGroundThruth;
++readerGenerate;
}
}
TEST(CAscWriterTest, CAN_FD)
{
asc::CAscReader readerGroundThruth;
EXPECT_TRUE(readerGroundThruth.Read(GetExecDirectory() / "asc_reader_canfd_test.asc"));
// Add all samples
asc::CAscWriter writer;
while (!readerGroundThruth.IsEOF())
{
auto prSample = readerGroundThruth.Get();
EXPECT_TRUE(prSample.second);
writer.AddSample(prSample.first);
++readerGroundThruth;
}
// Write the samples
writer.Write(GetExecDirectory() / "asc_writer_test.asc");
// Read the samples
asc::CAscReader readerGenerate;
EXPECT_TRUE(readerGenerate.Read(GetExecDirectory() / "asc_writer_test.asc"));
// Check whether the samples correspond to the original samples
readerGroundThruth.JumpBegin();
while (!readerGenerate.IsEOF())
{
auto prSampleGroundTruth = readerGroundThruth.Get();
EXPECT_TRUE(prSampleGroundTruth.second);
auto prSampleGenerated = readerGenerate.Get();
EXPECT_EQ(prSampleGroundTruth.first.dTimestamp, prSampleGenerated.first.dTimestamp);
EXPECT_EQ(prSampleGroundTruth.first.uiChannel, prSampleGenerated.first.uiChannel);
EXPECT_EQ(prSampleGroundTruth.first.uiId, prSampleGenerated.first.uiId);
EXPECT_EQ(prSampleGroundTruth.first.bExtended, prSampleGenerated.first.bExtended);
EXPECT_EQ(prSampleGroundTruth.first.bCanFd, prSampleGenerated.first.bCanFd);
EXPECT_EQ(prSampleGroundTruth.first.eDirection, prSampleGenerated.first.eDirection);
EXPECT_EQ(prSampleGroundTruth.first.uiLength, prSampleGenerated.first.uiLength);
for (size_t nIndex = 0; nIndex < 64; nIndex++)
EXPECT_EQ(prSampleGroundTruth.first.rguiData[nIndex], prSampleGenerated.first.rguiData[nIndex]);
++readerGroundThruth;
++readerGenerate;
}
}

View File

@@ -0,0 +1,19 @@
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#include "../../../global/localmemmgr.h"
/**
* @brief Main function
*/
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
CLocalMemMgr memmgr;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,39 @@
# Define project (multiple EXEs)
project(BasicTypesTests VERSION 1.0 LANGUAGES CXX)
# BasicTypes unit test executable
add_executable(UnitTest_BasicTypes
"main.cpp"
"basic_types_test.h"
"basic_types_test.cpp"
"string.cpp"
"u8string.cpp"
"u16string.cpp"
"u32string.cpp"
"wstring.cpp"
"ptr.cpp"
"ptr_simple.cpp"
"ptr_complex.cpp"
"sequence_simple.cpp"
"sequence_complex.cpp"
"serdes.cpp"
"crc.cpp"
"interface.cpp"
"any.cpp" )
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(UnitTest_BasicTypes GTest::GTest ${CMAKE_THREAD_LIBS_INIT} stdc++fs)
else()
target_link_libraries(UnitTest_BasicTypes GTest::GTest)
endif()
# Add the BasicTypes unittest
add_test(NAME UnitTest_BasicTypes COMMAND UnitTest_BasicTypes)
# Execute the test
add_custom_command(TARGET UnitTest_BasicTypes POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_BasicTypes>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_BasicTypes.xml
VERBATIM
)
# Build dependencies
add_dependencies(UnitTest_BasicTypes dependency_sdv_components)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
#include "basic_types_test.h"
void CBasicTypesTest::SetUpTestCase()
{
ASSERT_TRUE(true);
}
void CBasicTypesTest::TearDownTestCase() {}
void CBasicTypesTest::SetUp()
{}
void CBasicTypesTest::TearDown()
{}
size_t CBasicTypesTestAllocator::GetPtrCount() const
{
return m_setPointers.size();
}
void CBasicTypesTestAllocator::ResetPtrSet()
{
m_setPointers.clear();
}
void* CBasicTypesTestAllocator::Alloc(size_t nSize)
{
void* p = CLocalMemMgr::Alloc(nSize);
m_setPointers.insert(p);
return p;
}
void* CBasicTypesTestAllocator::Realloc(void* pData, size_t nSize)
{
m_setPointers.erase(pData);
void* p = CLocalMemMgr::Realloc(pData, nSize);
m_setPointers.insert(p);
return p;
}
void CBasicTypesTestAllocator::Free(void* pData)
{
m_setPointers.erase(pData);
CLocalMemMgr::Free(pData);
}

View File

@@ -0,0 +1,162 @@
#ifndef BASIC_TYPES_TEST_H
#define BASIC_TYPES_TEST_H
#include <gtest/gtest.h>
#define NO_SDV_LOCAL_CORE_FUNC
#include "../../../global/localmemmgr.h"
class CBasicTypesTestAllocator : public CLocalMemMgr
{
public:
/**
* @brief Get the amount of pointers allocated.
* @return
*/
size_t GetPtrCount() const;
/**
* @brief Reset the pointer set to start a new measurement.
*/
void ResetPtrSet();
private:
/**
* @brief Allocate memory. Overload of sdv::internal::IInternalMemAlloc::Alloc.
* @param[in] nSize The size of the memory to allocate (in bytes).
* @return Pointer to the memory allocation or NULL when memory allocation failed.
*/
virtual void* Alloc(size_t nSize) override;
/**
* @brief Reallocate memory. Overload of sdv::internal::IInternalMemAlloc::Realloc.
* @param[in] pData Pointer to a previous allocation or NULL when no previous allocation was available.
* @param[in] nSize The size of the memory to allocate (in bytes).
* @return Pointer to the memory allocation or NULL when memory allocation failed.
*/
virtual void* Realloc(void* pData, size_t nSize) override;
/**
* @brief Free a memory allocation. Overload of sdv::internal::IInternalMemAlloc::Free.
* @param[in] pData Pointer to a previous allocation.
*/
virtual void Free(void* pData) override;
std::set<void*> m_setPointers; ///< Pointer set for pointer tracking.
};
/**
* @brief Get the instance of the local memory manager.
* @return Reference to the memory manager.
*/
inline CBasicTypesTestAllocator& GetMemMgr()
{
static CBasicTypesTestAllocator memmgr;
return memmgr;
}
namespace sdv
{
namespace core
{
/**
* @brief Access to the core.
* @return Smart pointer to the core services interface.
*/
inline TInterfaceAccessPtr GetCore()
{
static CBasicTypesTestAllocator& rmemmgr = ::GetMemMgr();
return &rmemmgr;
}
/**
* @brief Access to specific interface of the core.
* @tparam TInterface Type of interface to return.
* @return Pointer to the interface or NULL when the interface was not exposed.
*/
template <typename TInterface>
inline TInterface* GetCore()
{
return GetCore().GetInterface<TInterface>();
}
}
}
/**
* @brief Test class for code genertion tests.
*/
class CBasicTypesTest : public testing::Test
{
public:
/**
* @brief Constructor
*/
CBasicTypesTest() = default;
/**
* @brief Set up the test suite.
*/
static void SetUpTestCase();
/**
* @brief Tear down the test suite.
*/
static void TearDownTestCase();
/**
* @brief Test setup.
*/
void SetUp() override;
/**
* @brief Test teardown.
*/
void TearDown() override;
};
namespace testing::internal
{
// Helper function for *_STREQ on wide strings.
inline AssertionResult CmpHelperSTREQ(const char* lhs_expression, const char* rhs_expression, const char16_t* lhs, const char16_t* rhs)
{
if (std::equal(lhs, lhs + std::char_traits<char16_t>::length(lhs), rhs))
{
return AssertionSuccess();
}
return EqFailure(lhs_expression, rhs_expression, PrintToString(lhs), PrintToString(rhs), false);
}
inline AssertionResult CmpHelperSTRNE(const char* s1_expression, const char* s2_expression, const char16_t* lhs, const char16_t* rhs)
{
if (!std::equal(lhs, lhs + std::char_traits<char16_t>::length(lhs), rhs))
{
return AssertionSuccess();
}
return AssertionFailure() << "Expected: (" << s1_expression << ") != (" << s2_expression
<< "), actual: " << PrintToString(lhs) << " vs " << PrintToString(rhs);
}
inline AssertionResult CmpHelperSTREQ(const char* lhs_expression, const char* rhs_expression, const char32_t* lhs, const char32_t* rhs)
{
if (std::equal(lhs, lhs + std::char_traits<char32_t>::length(lhs), rhs))
{
return AssertionSuccess();
}
return EqFailure(lhs_expression, rhs_expression, PrintToString(lhs), PrintToString(rhs), false);
}
inline AssertionResult CmpHelperSTRNE(const char* s1_expression, const char* s2_expression, const char32_t* lhs, const char32_t* rhs)
{
if (!std::equal(lhs, lhs + std::char_traits<char32_t>::length(lhs), rhs))
{
return AssertionSuccess();
}
return AssertionFailure() << "Expected: (" << s1_expression << ") != (" << s2_expression
<< "), actual: " << PrintToString(lhs) << " vs " << PrintToString(rhs);
}
}
#endif // !defined BASIC_TYPES_TEST_H

View File

@@ -0,0 +1,102 @@
#include <support/crc.h>
#include "basic_types_test.h"
using CCrcTest = CBasicTypesTest;
TEST_F(CCrcTest, BitReflection)
{
uint8_t ui8 = 0b11001010;
EXPECT_EQ(sdv::reflect(ui8), 0b01010011);
uint16_t ui16 = 0b0111001111001010;
EXPECT_EQ(sdv::reflect(ui16), 0b0101001111001110);
uint32_t ui32 = 0b01110011110010100111001111001010u;
EXPECT_EQ(sdv::reflect(ui32), 0b01010011110011100101001111001110u);
uint64_t ui64 = 0b0111001111001010011100111100101001110011110010100111001111001010ull;
EXPECT_EQ(sdv::reflect(ui64), 0b0101001111001110010100111100111001010011110011100101001111001110ull);
}
TEST_F(CCrcTest, CalcCRC)
{
// Create data table
constexpr auto arrTable = []
{
std::array<uint8_t, 1024> arrTemp{};
for (size_t n = 0; n < 1024; n++)
arrTemp[n] = static_cast<uint8_t>(n & 0xff);
return arrTemp;
}();
// Use http://www.sunshine2k.de/coding/javascript/crc/crc_js.html to check the CRC values.
// for (size_t nRow = 0; nRow < 64; nRow++)
//{
// for (size_t nCol = 0; nCol < 16; nCol++)
// std::cout << " 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)arrTable[nRow * 16 + nCol];
// std::cout << std::endl;
//}
// SAE-J1850: polynomial 0x1D, initial = 0xFF, final_xor = 0xFF, reflect_input = false, reflect_output = false
sdv::crcSAE_J1850 crcSAE_J1850;
EXPECT_EQ(crcSAE_J1850.calc_checksum(arrTable.data(), 1024), 0x84);
// AUTOSAR_8H2F: polynomial 0x2F, initial = 0xFF, final_xor = 0xFF, reflect_input = false, reflect_output = false)
sdv::crcAUTOSAR_8H2F crcAUTOSAR_8H2F;
EXPECT_EQ(crcAUTOSAR_8H2F.calc_checksum(arrTable.data(), 1024), 0x36);
// CCITT-FALSE: polynomial 0x1021, initial = 0xFFFF, final_xor = 0, reflect_input = false, reflect_output = false
sdv::crcCCITT_FALSE crcCCITT_FALSE;
EXPECT_EQ(crcCCITT_FALSE.calc_checksum(arrTable.data(), 1024), 0x758f);
// ARC: polynomial 0x8005, initial = 0, final_xor = 0, reflect_input = true, reflect_output = true
sdv::crcARC crcARC;
EXPECT_EQ(crcARC.calc_checksum(arrTable.data(), 1024), 0x3840);
// IEEE_802_3 polynomial 0x04C11DB7, initial = 0xFFFFFFFF, final_xor = 0xFFFFFFFF, reflect_input = true, reflect_output = true
sdv::crcIEEE_802_3 crcIEEE_802_3;
EXPECT_EQ(crcIEEE_802_3.calc_checksum(arrTable.data(), 1024), 0xB70B4C26);
// AUTOSAR_P4 polynomial 0xF4ACFB13, initial = 0xFFFFFFFF, final_xor = 0xFFFFFFFF, reflect_input = true, reflect_output = true
sdv::crcAUTOSAR_P4 crcAUTOSAR_P4;
EXPECT_EQ(crcAUTOSAR_P4.calc_checksum(arrTable.data(), 1024), 0xCF0881B6);
// CRC32-C Castagnoli polynomial 0x1EDC6F41, initial = 0xFFFFFFFF, final_xor = 0xFFFFFFFF, reflect_input = true, reflect_output
// = true
sdv::crcCRC32C crcCRC32C;
EXPECT_EQ(crcCRC32C.calc_checksum(arrTable.data(), 1024), 0x2CDF6E8Fu);
// ECMA (polynomial 0x42F0E1EBA9EA3693, initial = 0xFFFFFFFFFFFFFFFF, final_xor = 0xFFFFFFFFFFFFFFFF, reflect_input = true,
// reflect_output = true)
sdv::crcECMA crcECMA;
EXPECT_EQ(crcECMA.calc_checksum(arrTable.data(), 1024), 0xD51FB58DC789C400);
}
TEST_F(CCrcTest, CalcPartialCRC)
{
// Create data table
constexpr auto arrTable = []
{
std::array<uint8_t, 1024> arrTemp{};
for (size_t n = 0; n < 1024; n++)
arrTemp[n] = static_cast<uint8_t>(n & 0xff);
return arrTemp;
}();
sdv::crcCRC32C crcCRC32C;
// Full calculation
EXPECT_EQ(crcCRC32C.get_checksum(), 0x00000000u);
crcCRC32C.calc_checksum(arrTable.data(), 1024);
EXPECT_EQ(crcCRC32C.get_checksum(), 0x2CDF6E8Fu);
// Partial calulcation
crcCRC32C.reset();
EXPECT_EQ(crcCRC32C.get_checksum(), 0x00000000u);
crcCRC32C.calc_checksum(arrTable.data(), 512);
EXPECT_EQ(crcCRC32C.get_checksum(), 0xAE10EE5Au);
crcCRC32C.calc_checksum(arrTable.data() + 512, 512);
EXPECT_EQ(crcCRC32C.get_checksum(), 0x2CDF6E8Fu);
crcCRC32C.set_checksum(0xAE10EE5Au);
crcCRC32C.calc_checksum(arrTable.data() + 512, 512);
EXPECT_EQ(crcCRC32C.get_checksum(), 0x2CDF6E8Fu);
}

View File

@@ -0,0 +1,162 @@
#include <support/string.h>
#include <sstream>
#include "basic_types_test.h"
using CInterfaceTypeTest = CBasicTypesTest;
// Test class
class CTest : public sdv::IInterfaceAccess, public sdv::core::IMemoryAlloc
{
public:
// Interface map
BEGIN_SDV_INTERFACE_MAP()
END_SDV_INTERFACE_MAP()
/**
* @brief Allocate a memory block of the provided length. Overload of IMemoryAlloc::Allocate.
* @param[in] uiLength The length of the memory block to allocate.
* @return Smart pointer to the memory allocation or NULL when allocating was not possible.
*/
virtual sdv::pointer<uint8_t> Allocate(/*in*/ uint32_t /*uiLength*/) override { return sdv::pointer<uint8_t>(); };
};
TEST_F(CInterfaceTypeTest, Constructor)
{
sdv::interface_t ifc;
EXPECT_FALSE(ifc);
CTest test;
sdv::interface_t ifc2(static_cast<sdv::IInterfaceAccess*>(&test));
EXPECT_TRUE(ifc2);
sdv::interface_t ifc3(ifc2);
EXPECT_TRUE(ifc3);
EXPECT_EQ(ifc2, ifc3);
sdv::interface_t ifc4(std::move(ifc3));
EXPECT_FALSE(ifc3);
EXPECT_TRUE(ifc4);
EXPECT_EQ(ifc2, ifc4);
sdv::interface_t ifc5(nullptr);
EXPECT_FALSE(ifc5);
}
TEST_F(CInterfaceTypeTest, AssignmentOperator)
{
sdv::interface_t ifc, ifc2, ifc3;
EXPECT_FALSE(ifc);
EXPECT_FALSE(ifc2);
EXPECT_FALSE(ifc3);
CTest test;
ifc = static_cast<sdv::IInterfaceAccess*>(&test);
EXPECT_TRUE(ifc);
ifc2 = ifc;
EXPECT_TRUE(ifc);
EXPECT_TRUE(ifc2);
ifc3 = std::move(ifc2);
EXPECT_TRUE(ifc3);
EXPECT_FALSE(ifc2);
ifc3 = nullptr;
EXPECT_FALSE(ifc3);
ifc = static_cast<sdv::core::IMemoryAlloc*>(&test);
EXPECT_TRUE(ifc);
}
TEST_F(CInterfaceTypeTest, Reset)
{
CTest test;
sdv::interface_t ifc(static_cast<sdv::IInterfaceAccess*>(&test));
EXPECT_TRUE(ifc);
ifc.reset();
EXPECT_FALSE(ifc);
}
TEST_F(CInterfaceTypeTest, ID)
{
CTest test;
sdv::interface_t ifc(static_cast<sdv::IInterfaceAccess*>(&test));
EXPECT_TRUE(ifc);
EXPECT_EQ(ifc.id(), sdv::GetInterfaceId<sdv::IInterfaceAccess>());
ifc = static_cast<sdv::core::IMemoryAlloc*>(&test);
EXPECT_EQ(ifc.id(), sdv::GetInterfaceId<sdv::core::IMemoryAlloc>());
}
TEST_F(CInterfaceTypeTest, Get)
{
CTest test;
sdv::interface_t ifc(static_cast<sdv::IInterfaceAccess*>(&test));
EXPECT_TRUE(ifc);
EXPECT_EQ(ifc.template get<sdv::IInterfaceAccess>(), static_cast<sdv::IInterfaceAccess*>(&test));
EXPECT_EQ(ifc.template get<sdv::core::IMemoryAlloc>(), nullptr);
ifc = static_cast<sdv::core::IMemoryAlloc*>(&test);
EXPECT_EQ(ifc.template get<sdv::core::IMemoryAlloc>(), static_cast<sdv::core::IMemoryAlloc*>(&test));
EXPECT_EQ(ifc.template get<sdv::IInterfaceAccess>(), nullptr);
}
TEST_F(CInterfaceTypeTest, Compare)
{
CTest test;
sdv::interface_t ifc(static_cast<sdv::IInterfaceAccess*>(&test));
sdv::interface_t ifc2(static_cast<sdv::IInterfaceAccess*>(&test));
sdv::interface_t ifc3(static_cast<sdv::core::IMemoryAlloc*>(&test));
EXPECT_TRUE(ifc);
EXPECT_TRUE(ifc2);
EXPECT_TRUE(ifc3);
EXPECT_EQ(ifc.compare(ifc2), 0);
if (sdv::GetInterfaceId<sdv::IInterfaceAccess>() > sdv::GetInterfaceId<sdv::core::IMemoryAlloc>())
EXPECT_GT(ifc.compare(ifc3), 0);
else
EXPECT_LT(ifc.compare(ifc3), 0);
}
TEST_F(CInterfaceTypeTest, CompareOperators)
{
CTest test;
sdv::interface_t ifc(static_cast<sdv::IInterfaceAccess*>(&test));
sdv::interface_t ifc2(static_cast<sdv::IInterfaceAccess*>(&test));
sdv::interface_t ifc3(static_cast<sdv::core::IMemoryAlloc*>(&test));
sdv::interface_t ifc4;
EXPECT_TRUE(ifc);
EXPECT_TRUE(ifc2);
EXPECT_TRUE(ifc3);
EXPECT_EQ(ifc, ifc2);
EXPECT_NE(ifc2, ifc3);
if (sdv::GetInterfaceId<sdv::IInterfaceAccess>() > sdv::GetInterfaceId<sdv::core::IMemoryAlloc>())
{
EXPECT_GT(ifc2, ifc3);
EXPECT_GE(ifc2, ifc3);
EXPECT_LT(ifc3, ifc2);
EXPECT_LE(ifc3, ifc2);
} else
{
EXPECT_GT(ifc3, ifc2);
EXPECT_GE(ifc3, ifc2);
EXPECT_LT(ifc2, ifc3);
EXPECT_LE(ifc2, ifc3);
}
EXPECT_NE(ifc2, nullptr);
EXPECT_NE(nullptr, ifc2);
EXPECT_GT(ifc2, nullptr);
EXPECT_GE(ifc2, nullptr);
EXPECT_FALSE(ifc2 < nullptr);
EXPECT_FALSE(ifc2 <= nullptr);
EXPECT_LT(nullptr, ifc2);
EXPECT_LE(nullptr, ifc2);
EXPECT_FALSE(nullptr > ifc2);
EXPECT_FALSE(nullptr >= ifc2);
EXPECT_EQ(nullptr, ifc4);
EXPECT_EQ(ifc4, nullptr);
}

View File

@@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])
#else
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,935 @@
#include <sstream>
#include <support/pointer.h>
#include <cstring>
#include "basic_types_test.h"
// There are some versions of GCC that produce bogus warnings for -Wstringop-overflow (e.g. version 9.4 warns, 11.4 not - changing
// the compile order without changing the logical behavior, will produce different results).
// See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100477
// And https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115074
// Suppress this warning for the string class.
// NOTE 03.08.2025: Additional bogus warnigs/errors are suppressed for newer versions of the compiler.
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
using CPointerTypeTest = CBasicTypesTest;
TEST_F(CPointerTypeTest, MakeFixedPointer)
{
sdv::pointer<uint32_t, 1> ptr0;
EXPECT_TRUE(ptr0);
}
TEST_F(CPointerTypeTest, MakeDynamicPointer)
{
sdv::pointer<uint32_t> ptr0 = sdv::make_ptr<uint32_t>(0);
EXPECT_TRUE(ptr0);
sdv::pointer<uint32_t> ptr1 = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr1);
sdv::pointer<uint32_t> ptr2 = sdv::make_ptr<uint32_t>(2);
EXPECT_TRUE(ptr2);
}
TEST_F(CPointerTypeTest, ConstructorDynamicPointer)
{
// Default constructor
sdv::pointer<uint32_t> ptr;
EXPECT_FALSE(ptr);
// Allocate
ptr = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr);
// Copy constructor
sdv::pointer<uint32_t> ptrCopy(ptr);
EXPECT_TRUE(ptrCopy);
// Move constructor
sdv::pointer<uint32_t> ptrMove(std::move(ptr));
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrMove);
// Destructor
GetMemMgr().ResetPtrSet();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
sdv::pointer<uint32_t>* pptr = new sdv::pointer<uint32_t>(sdv::make_ptr<uint32_t>());
EXPECT_NE(pptr, nullptr);
EXPECT_NE(GetMemMgr().GetPtrCount(), 0);
delete pptr;
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
}
TEST_F(CPointerTypeTest, ConstructorFixedPointer)
{
// Default constructor
sdv::pointer<uint32_t, 1> ptr;
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
// Copy constructor
sdv::pointer<uint32_t, 1> ptrCopy1(ptr);
EXPECT_TRUE(ptrCopy1);
EXPECT_EQ(ptrCopy1.size(), 0);
sdv::pointer<uint32_t, 10> ptrCopy10(ptr);
EXPECT_TRUE(ptrCopy10);
EXPECT_EQ(ptrCopy10.size(), 0);
using TCopy2 = sdv::pointer<uint32_t, 2>;
EXPECT_NO_THROW(TCopy2 ptrCopy2(ptrCopy10));
ptrCopy10.resize(5);
EXPECT_EQ(ptrCopy10.size(), 5);
using TCopy3 = sdv::pointer<uint32_t, 3>;
EXPECT_THROW(TCopy3 ptrCopy3(ptrCopy10), sdv::XBufferTooSmall);
// Move constructor
ptr.resize(1);
EXPECT_EQ(ptr.size(), 1);
sdv::pointer<uint32_t, 1> ptrMove(std::move(ptr));
EXPECT_TRUE(ptr);
EXPECT_TRUE(ptrMove);
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(ptrMove.size(), 1);
}
TEST_F(CPointerTypeTest, ConstructorMixedPointer)
{
// Default constructor
sdv::pointer<uint32_t> ptr0;
sdv::pointer<uint32_t, 1> ptr1;
sdv::pointer<uint32_t, 5> ptr5;
EXPECT_FALSE(ptr0);
EXPECT_TRUE(ptr1);
EXPECT_TRUE(ptr5);
// Copy constructor
sdv::pointer<uint32_t> ptrCopy0a(ptr0);
EXPECT_FALSE(ptrCopy0a);
EXPECT_EQ(ptrCopy0a.size(), 0);
sdv::pointer<uint32_t> ptrCopy0b(ptr1);
EXPECT_TRUE(ptrCopy0b);
EXPECT_EQ(ptrCopy0b.size(), 0);
sdv::pointer<uint32_t> ptrCopy0c(ptr5);
EXPECT_TRUE(ptrCopy0c);
EXPECT_EQ(ptrCopy0c.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1a(ptr0);
EXPECT_TRUE(ptrCopy1a);
EXPECT_EQ(ptrCopy1a.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1b(ptr1);
EXPECT_TRUE(ptrCopy1b);
EXPECT_EQ(ptrCopy1b.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1c(ptr5);
EXPECT_TRUE(ptrCopy1c);
EXPECT_EQ(ptrCopy1c.size(), 0);
ptr0.resize(3);
ptr1.resize(1);
ptr5.resize(3);
using TCopy2 = sdv::pointer<uint32_t, 2>;
EXPECT_THROW(TCopy2 ptrCopy2a(ptr5), sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 2> ptrCopy2b(ptr1);
EXPECT_TRUE(ptrCopy2b);
EXPECT_EQ(ptrCopy2b.size(), 1);
EXPECT_THROW(TCopy2 ptrCopy2c(ptr5), sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 3> ptrCopy3a(ptr0);
EXPECT_TRUE(ptrCopy3a);
EXPECT_EQ(ptrCopy3a.size(), 3);
sdv::pointer<uint32_t, 3> ptrCopy3b(ptr1);
EXPECT_TRUE(ptrCopy3b);
EXPECT_EQ(ptrCopy3b.size(), 1);
sdv::pointer<uint32_t, 3> ptrCopy3c(ptr5);
EXPECT_TRUE(ptrCopy3c);
EXPECT_EQ(ptrCopy3c.size(), 3);
}
TEST_F(CPointerTypeTest, AssignmentOperatorsDynamicPointer)
{
// Create pointer
sdv::pointer<uint32_t> ptr = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr);
// Copy assignment
sdv::pointer<uint32_t> ptrCopy;
EXPECT_FALSE(ptrCopy);
ptrCopy = ptr;
EXPECT_TRUE(ptrCopy);
// Move assignment
sdv::pointer<uint32_t> ptrMove;
EXPECT_FALSE(ptrMove);
ptrMove = std::move(ptr);
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrMove);
}
TEST_F(CPointerTypeTest, AssignmentOperatorsFixedPointer)
{
// Copy assignment
sdv::pointer<uint32_t, 3> ptr;
sdv::pointer<uint32_t, 1> ptrCopy;
EXPECT_TRUE(ptrCopy);
ptrCopy = ptr;
EXPECT_TRUE(ptrCopy);
ptr.resize(1);
EXPECT_EQ(ptr.size(), 1);
ptrCopy = ptr;
EXPECT_EQ(ptrCopy.size(), 1);
ptr.resize(2);
EXPECT_EQ(ptr.size(), 2);
EXPECT_THROW(ptrCopy = ptr, sdv::XBufferTooSmall);
// Move assignment
sdv::pointer<uint32_t, 3> ptrMove;
EXPECT_TRUE(ptrMove);
ptrMove = std::move(ptr);
EXPECT_TRUE(ptr);
EXPECT_TRUE(ptrMove);
}
TEST_F(CPointerTypeTest, AssignmentOperatorsMixedPointer)
{
sdv::pointer<uint32_t> ptr0;
sdv::pointer<uint32_t, 1> ptr1;
sdv::pointer<uint32_t, 5> ptr5;
EXPECT_FALSE(ptr0);
EXPECT_TRUE(ptr1);
EXPECT_TRUE(ptr5);
// Copy constructor
sdv::pointer<uint32_t> ptrCopy0a;
EXPECT_FALSE(ptrCopy0a);
ptrCopy0a = ptr0;
EXPECT_FALSE(ptrCopy0a);
EXPECT_EQ(ptrCopy0a.size(), 0);
sdv::pointer<uint32_t> ptrCopy0b;
EXPECT_FALSE(ptrCopy0b);
ptrCopy0b = ptr1;
EXPECT_TRUE(ptrCopy0b);
EXPECT_EQ(ptrCopy0b.size(), 0);
sdv::pointer<uint32_t> ptrCopy0c;
EXPECT_FALSE(ptrCopy0c);
ptrCopy0c = ptr5;
EXPECT_TRUE(ptrCopy0c);
EXPECT_EQ(ptrCopy0c.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1a;
EXPECT_TRUE(ptrCopy1a);
ptrCopy1a = ptr0;
EXPECT_TRUE(ptrCopy1a);
EXPECT_EQ(ptrCopy1a.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1b;
EXPECT_TRUE(ptrCopy1b);
ptrCopy1b = ptr1;
EXPECT_TRUE(ptrCopy1b);
EXPECT_EQ(ptrCopy1b.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1c;
EXPECT_TRUE(ptrCopy1c);
ptrCopy1c = ptr5;
EXPECT_TRUE(ptrCopy1c);
EXPECT_EQ(ptrCopy1c.size(), 0);
ptr0.resize(3);
ptr1.resize(1);
ptr5.resize(3);
sdv::pointer<uint32_t, 2> ptrCopy2a;
EXPECT_TRUE(ptrCopy2a);
EXPECT_THROW(ptrCopy2a = ptr5, sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 2> ptrCopy2b;
EXPECT_TRUE(ptrCopy2b);
ptrCopy2b = ptr1;
EXPECT_TRUE(ptrCopy2b);
EXPECT_EQ(ptrCopy2b.size(), 1);
sdv::pointer<uint32_t, 2> ptrCopy2c;
EXPECT_TRUE(ptrCopy2c);
EXPECT_THROW(ptrCopy2c = ptr5, sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 3> ptrCopy3a;
EXPECT_TRUE(ptrCopy3a);
ptrCopy3a = ptr0;
EXPECT_TRUE(ptrCopy3a);
EXPECT_EQ(ptrCopy3a.size(), 3);
sdv::pointer<uint32_t, 3> ptrCopy3b;
EXPECT_TRUE(ptrCopy3b);
ptrCopy3b = ptr1;
EXPECT_TRUE(ptrCopy3b);
EXPECT_EQ(ptrCopy3b.size(), 1);
sdv::pointer<uint32_t, 3> ptrCopy3c;
EXPECT_TRUE(ptrCopy3c);
ptrCopy3c = ptr5;
EXPECT_TRUE(ptrCopy3c);
EXPECT_EQ(ptrCopy3c.size(), 3);
}
TEST_F(CPointerTypeTest, AttachmentDynamicPointer)
{
// Functions are protected. Derive the class to access the functions
class CDerivedPtr : public sdv::pointer<uint32_t>
{
public:
void attach(pointer<uint8_t>&& rptrBuffer) { sdv::pointer<uint32_t>::attach(std::move(rptrBuffer)); }
pointer<uint8_t>&& detach() { return sdv::pointer<uint32_t>::detach(); }
};
// Create the buffer
sdv::pointer<uint8_t> ptrBuffer = sdv::make_ptr<uint8_t>(101);
EXPECT_TRUE(ptrBuffer);
EXPECT_EQ(ptrBuffer.size(), 101);
EXPECT_EQ(ptrBuffer.ref_count(), 1);
// Attach
CDerivedPtr ptr;
EXPECT_FALSE(ptr);
ptr.attach(std::move(ptrBuffer));
EXPECT_FALSE(ptrBuffer);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 25);
EXPECT_EQ(ptr.ref_count(), 1);
// Detach
ptrBuffer = ptr.detach();
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrBuffer);
EXPECT_EQ(ptrBuffer.size(), 101);
EXPECT_EQ(ptrBuffer.ref_count(), 1);
}
TEST_F(CPointerTypeTest, ResetFunctionStaticPointer)
{
// Create pointer
sdv::pointer<uint32_t, 10> ptr;
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10);
ptr.reset();
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
}
TEST_F(CPointerTypeTest, ResetFunction)
{
// Create pointer
GetMemMgr().ResetPtrSet();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
sdv::pointer<uint32_t> ptr = sdv::make_ptr<uint32_t>();
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10);
EXPECT_NE(GetMemMgr().GetPtrCount(), 0);
ptr.reset();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
EXPECT_EQ(ptr.size(), 0);
}
TEST_F(CPointerTypeTest, SwapFunctionStaticPointer)
{
// Allocate
sdv::pointer<uint32_t, 250> ptr1;
EXPECT_TRUE(ptr1);
ptr1.resize(100);
EXPECT_EQ(ptr1.size(), 100);
sdv::pointer<uint32_t, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200);
EXPECT_EQ(ptr2.size(), 100);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100);
EXPECT_EQ(ptr2.size(), 200);
// Swap with empty pointer
sdv::pointer<uint32_t, 150> ptr3;
ptr3.swap(ptr1);
EXPECT_TRUE(ptr3);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr3.size(), 100);
EXPECT_EQ(ptr1.size(), 0);
sdv::pointer<uint32_t, 150> ptr4;
EXPECT_THROW(sdv::swap(ptr4, ptr2), sdv::XBufferTooSmall);
}
TEST_F(CPointerTypeTest, SwapFunctionDynamicPointer)
{
// Allocate
sdv::pointer<uint32_t> ptr1 = sdv::make_ptr<uint32_t>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100);
sdv::pointer<uint32_t> ptr2 = sdv::make_ptr<uint32_t>(200);
EXPECT_TRUE(ptr2);
EXPECT_EQ(ptr2.size(), 200);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200);
EXPECT_EQ(ptr2.size(), 100);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100);
EXPECT_EQ(ptr2.size(), 200);
// Swap with empty pointer
sdv::pointer<uint32_t> ptr3;
ptr3.swap(ptr1);
EXPECT_TRUE(ptr3);
EXPECT_FALSE(ptr1);
sdv::swap(ptr3, ptr1);
EXPECT_FALSE(ptr3);
EXPECT_TRUE(ptr1);
}
TEST_F(CPointerTypeTest, SwapFunctionMixedPointer)
{
// Allocate
sdv::pointer<uint32_t> ptr1 = sdv::make_ptr<uint32_t>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100);
sdv::pointer<uint32_t, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200);
EXPECT_EQ(ptr2.size(), 100);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100);
EXPECT_EQ(ptr2.size(), 200);
}
TEST_F(CPointerTypeTest, AccessFunctions)
{
struct STest
{
uint32_t uiValue;
};
// Empty pointer
sdv::pointer<STest> ptr;
EXPECT_FALSE(ptr);
// Get
EXPECT_EQ(ptr.get(), nullptr);
EXPECT_THROW(*ptr, sdv::XNullPointer);
EXPECT_THROW(ptr->uiValue, sdv::XNullPointer);
// Allocate
ptr = sdv::make_ptr<STest>(100);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 100);
// Get function
EXPECT_NE(ptr.get(), nullptr);
// Assign the value to the array
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr.get()[uiIndex].uiValue = uiIndex;
// Reference functions
EXPECT_EQ((*ptr).uiValue, 0u);
*ptr = STest{101u};
EXPECT_EQ(ptr->uiValue, 101u);
EXPECT_EQ((*ptr.get()).uiValue, 101u);
ptr->uiValue = 0;
EXPECT_EQ((*ptr).uiValue, 0u);
EXPECT_EQ((*ptr.get()).uiValue, 0u);
// Indexed values
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex] = STest{uiIndex + 200u};
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
EXPECT_EQ(ptr.get()[uiIndex].uiValue, uiIndex + 200u);
EXPECT_THROW(ptr[100], sdv::XIndexOutOfRange);
}
TEST_F(CPointerTypeTest, SizeFunctionsStaticPointer)
{
// Empty pointer
sdv::pointer<uint32_t, 150> ptr;
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(ptr.capacity(), 150);
EXPECT_NO_THROW(ptr.resize(100));
EXPECT_EQ(ptr.size(), 100);
EXPECT_EQ(ptr.capacity(), 150);
// Resize to many
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex] = uiIndex + 1000;
EXPECT_THROW(ptr[101], sdv::XIndexOutOfRange);
// Resize smaller
ptr.resize(50);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 50);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[51], sdv::XIndexOutOfRange);
// Resize larger (the first 50 should still be valid)
ptr.resize(150);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 150);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[151], sdv::XIndexOutOfRange);
// Exceed buffer capacity
EXPECT_THROW(ptr.resize(151), sdv::XBufferTooSmall);
}
TEST_F(CPointerTypeTest, SizeFunctionsDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptr;
EXPECT_FALSE(ptr);
EXPECT_EQ(ptr.size(), 0);
EXPECT_NO_THROW(ptr.resize(100));
EXPECT_EQ(ptr.size(), 100);
EXPECT_EQ(ptr.capacity(), 100);
// Allocate zero
ptr = sdv::make_ptr<uint32_t>(0);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(ptr.capacity(), 0);
// Resize to many
ptr.resize(100);
EXPECT_EQ(ptr.size(), 100);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex] = uiIndex + 1000;
EXPECT_THROW(ptr[101], sdv::XIndexOutOfRange);
// Resize smaller
ptr.resize(50);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 50);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[51], sdv::XIndexOutOfRange);
// Resize larger (the first 50 should still be valid)
ptr.resize(150);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 150);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[151], sdv::XIndexOutOfRange);
// Copy the pointer an resize to giant; both pointers should still be valid.
sdv::pointer<uint32_t> ptrGiant(ptr);
EXPECT_EQ(ptr, ptrGiant);
ptrGiant.resize(1024 * 1024 * 8);
EXPECT_EQ(ptr, ptrGiant);
}
TEST_F(CPointerTypeTest, RefCountFunctionDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptr;
EXPECT_EQ(ptr.ref_count(), 0);
// Allocate
ptr = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.ref_count(), 1);
// Copy
sdv::pointer<uint32_t> ptrCopy(ptr);
EXPECT_TRUE(ptrCopy);
EXPECT_EQ(ptr.ref_count(), 2);
EXPECT_EQ(ptrCopy.ref_count(), 2);
sdv::pointer<uint32_t> ptrCopy2;
EXPECT_FALSE(ptrCopy2);
ptrCopy2 = ptrCopy;
EXPECT_TRUE(ptrCopy2);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 3);
EXPECT_EQ(ptrCopy2.ref_count(), 3);
// Move
sdv::pointer<uint32_t> ptrMove(std::move(ptrCopy));
EXPECT_TRUE(ptrMove);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 0);
EXPECT_EQ(ptrCopy2.ref_count(), 3);
EXPECT_EQ(ptrMove.ref_count(), 3);
sdv::pointer<uint32_t> ptrMove2;
EXPECT_FALSE(ptrMove2);
ptrMove2 = std::move(ptrCopy2);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 0);
EXPECT_EQ(ptrCopy2.ref_count(), 0);
EXPECT_EQ(ptrMove.ref_count(), 3);
EXPECT_EQ(ptrMove2.ref_count(), 3);
// Reset
ptrMove.reset();
EXPECT_EQ(ptr.ref_count(), 2);
EXPECT_EQ(ptrMove.ref_count(), 0);
EXPECT_EQ(ptrMove2.ref_count(), 2);
ptrMove2.reset();
EXPECT_EQ(ptr.ref_count(), 1);
EXPECT_EQ(ptrMove.ref_count(), 0);
EXPECT_EQ(ptrMove2.ref_count(), 0);
}
TEST_F(CPointerTypeTest, CompareOperatorStaticPointer)
{
// Empty pointer
sdv::pointer<uint32_t, 10> ptrLeft;
sdv::pointer<uint32_t, 15> ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Resize one pointer and fill with counter
ptrLeft.resize(10);
for (size_t nIndex = 0; nIndex < ptrLeft.size(); nIndex++)
ptrLeft[nIndex] = static_cast<uint32_t>(nIndex);
EXPECT_EQ(ptrLeft.size(), 10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
}
TEST_F(CPointerTypeTest, CompareOperatorDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptrLeft, ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Allocate one pointer
ptrLeft = sdv::make_ptr<uint32_t>(10);
EXPECT_TRUE(ptrLeft);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
// Reallocate left allocation
ptrLeft = sdv::make_ptr<uint32_t>(10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
}
TEST_F(CPointerTypeTest, CompareOperatorMixedPointer)
{
// Empty pointer
sdv::pointer<uint32_t, 10> ptrLeft;
sdv::pointer<uint32_t> ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Resize one pointer and fill with counter
ptrLeft.resize(10);
for (size_t nIndex = 0; nIndex < ptrLeft.size(); nIndex++)
ptrLeft[nIndex] = static_cast<uint32_t>(nIndex);
EXPECT_EQ(ptrLeft.size(), 10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
}
TEST_F(CPointerTypeTest, CompareNullOperatorDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptr;
EXPECT_TRUE(ptr == nullptr);
EXPECT_TRUE(nullptr == ptr);
EXPECT_FALSE(ptr != nullptr);
EXPECT_FALSE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_FALSE(nullptr < ptr);
EXPECT_TRUE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_FALSE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_TRUE(nullptr >= ptr);
// Allocate one pointer
ptr = sdv::make_ptr<uint32_t>(10);
EXPECT_TRUE(ptr);
EXPECT_FALSE(ptr == nullptr);
EXPECT_FALSE(nullptr == ptr);
EXPECT_TRUE(ptr != nullptr);
EXPECT_TRUE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_TRUE(nullptr < ptr);
EXPECT_FALSE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_TRUE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_FALSE(nullptr >= ptr);
// Free allocation
ptr.reset();
EXPECT_TRUE(ptr == nullptr);
EXPECT_TRUE(nullptr == ptr);
EXPECT_FALSE(ptr != nullptr);
EXPECT_FALSE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_FALSE(nullptr < ptr);
EXPECT_TRUE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_FALSE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_TRUE(nullptr >= ptr);
}
TEST_F(CPointerTypeTest, StreamOperatorStaticPointer)
{
// Stream one number
std::stringstream sstream;
sdv::pointer<uint32_t, 1> ptr;
ptr.resize(1);
*ptr = 100;
sstream << ptr;
EXPECT_EQ(sstream.str(), "100");
// Stream multiple numbers
std::stringstream sstream2;
sdv::pointer<uint32_t, 10> ptr2;
ptr2.resize(10);
for (uint32_t uiIndex = 0u; uiIndex < 10u; uiIndex++)
ptr2[uiIndex] = 100u + uiIndex;
sstream2 << ptr2;
EXPECT_EQ(sstream2.str(), "100101102103104105106107108109");
}
TEST_F(CPointerTypeTest, StreamOperatorDynamicPointer)
{
// Stream one number
std::stringstream sstream;
sdv::pointer<uint32_t> ptr;
ptr = sdv::make_ptr<uint32_t>();
*ptr = 100;
sstream << ptr;
EXPECT_EQ(sstream.str(), "100");
// Stream multiple numbers
std::stringstream sstream2;
ptr = sdv::make_ptr<uint32_t>(10);
for (uint32_t uiIndex = 0u; uiIndex < 10u; uiIndex++)
ptr[uiIndex] = 100u + uiIndex;
sstream2 << ptr;
EXPECT_EQ(sstream2.str(), "100101102103104105106107108109");
}
TEST_F(CPointerTypeTest, MakePointerFromStream)
{
std::stringstream sstream;
sstream << "Hello, this is a text which should be used to check the from-stream functionality!";
sdv::pointer<uint8_t> ptrData = sdv::from_stream(sstream.rdbuf());
ASSERT_EQ(ptrData.size(), sstream.str().size());
// NOTE: Since the C-string is zero base, it is not possible to do a simple string compare.
EXPECT_EQ(memcmp(sstream.str().c_str(), ptrData.get(), ptrData.size()), 0);
}
TEST_F(CPointerTypeTest, StorePointerIntoStream)
{
char sz[] = "Hello, this is a text which should be used to check the to-stream functionality!";
sdv::pointer<uint8_t> ptrData;
ptrData.resize(sizeof(sz));
ASSERT_EQ(ptrData.size(), sizeof(sz));
std::copy(std::begin(sz), std::end(sz), ptrData.get());
std::stringstream sstream;
sdv::to_stream(ptrData, sstream.rdbuf());
// NOTE: Since the C-string is zero base, it is not possible to do a simple string compare.
EXPECT_EQ(memcmp(sstream.str().c_str(), sz, ptrData.size()), 0);
}
TEST_F(CPointerTypeTest, CastFromPointer)
{
struct STest
{
int32_t i32 = 10;
uint16_t ui16 = 99;
char sz[2] = { 'a', 'b' };
int64_t i64 = -98765432;
uint64_t ui64 = 123456789;
} test;
// Test for exact size
sdv::pointer<uint8_t> ptrNoOffset;
ptrNoOffset.resize(sizeof(test));
ASSERT_EQ(ptrNoOffset.size(), sizeof(test));
std::memcpy(ptrNoOffset.get(), &test, sizeof(STest));
STest* pTest = sdv::cast<STest>(ptrNoOffset);
EXPECT_NE(pTest, nullptr);
EXPECT_EQ(std::memcmp(&test, pTest, sizeof(STest)), 0);
// Test for smaller size
sdv::pointer<uint8_t> ptrSmaller;
ptrSmaller.resize(sizeof(test));
ASSERT_EQ(ptrSmaller.size(), sizeof(test));
std::memcpy(ptrSmaller.get(), &test, sizeof(STest));
ptrSmaller.resize(sizeof(STest) - 1);
pTest = sdv::cast<STest>(ptrSmaller);
EXPECT_EQ(pTest, nullptr);
// Test for larger size
sdv::pointer<uint8_t> ptrLarger;
ptrLarger.resize(sizeof(test) + 100);
ASSERT_GT(ptrLarger.size(), sizeof(test));
std::memcpy(ptrLarger.get(), &test, sizeof(STest));
pTest = sdv::cast<STest>(ptrLarger);
EXPECT_NE(pTest, nullptr);
EXPECT_EQ(std::memcmp(&test, pTest, sizeof(STest)), 0);
// Test with offset
sdv::pointer<uint8_t> ptrOffset;
ptrOffset.resize(sizeof(test) + 100);
ASSERT_GT(ptrOffset.size(), sizeof(test));
std::memcpy(ptrOffset.get() + 100, &test, sizeof(STest));
pTest = sdv::cast<STest>(ptrOffset, 100);
EXPECT_NE(pTest, nullptr);
EXPECT_EQ(std::memcmp(&test, pTest, sizeof(STest)), 0);
// Test with offset, beyond size
sdv::pointer<uint8_t> ptrOffsetBeyond;
ptrOffsetBeyond.resize(sizeof(test) + 100);
ASSERT_GT(ptrOffsetBeyond.size(), sizeof(test));
std::memcpy(ptrOffsetBeyond.get() + 100, &test, sizeof(STest));
pTest = sdv::cast<STest>(ptrOffsetBeyond, 101);
EXPECT_EQ(pTest, nullptr);
}
TEST_F(CPointerTypeTest, ConstCastFromPointer)
{
struct STest
{
int32_t i32 = 10;
uint16_t ui16 = 99;
char sz[2] = { 'a', 'b' };
int64_t i64 = -98765432;
uint64_t ui64 = 123456789;
} test;
// Test for exact size
sdv::pointer<uint8_t> ptrNoOffset;
ptrNoOffset.resize(sizeof(test));
ASSERT_EQ(ptrNoOffset.size(), sizeof(test));
std::memcpy(ptrNoOffset.get(), &test, sizeof(STest));
const STest* pTest = sdv::cast<STest>(static_cast<const sdv::pointer<uint8_t>&>(ptrNoOffset));
EXPECT_NE(pTest, nullptr);
EXPECT_EQ(std::memcmp(&test, pTest, sizeof(STest)), 0);
// Test for smaller size
sdv::pointer<uint8_t> ptrSmaller;
ptrSmaller.resize(sizeof(test));
ASSERT_EQ(ptrSmaller.size(), sizeof(test));
std::memcpy(ptrSmaller.get(), &test, sizeof(STest));
ptrSmaller.resize(sizeof(STest) - 1);
pTest = sdv::cast<STest>(static_cast<const sdv::pointer<uint8_t>&>(ptrSmaller));
EXPECT_EQ(pTest, nullptr);
// Test for larger size
sdv::pointer<uint8_t> ptrLarger;
ptrLarger.resize(sizeof(test) + 100);
ASSERT_GT(ptrLarger.size(), sizeof(test));
std::memcpy(ptrLarger.get(), &test, sizeof(STest));
pTest = sdv::cast<STest>(static_cast<const sdv::pointer<uint8_t>&>(ptrLarger));
EXPECT_NE(pTest, nullptr);
EXPECT_EQ(std::memcmp(&test, pTest, sizeof(STest)), 0);
// Test with offset
sdv::pointer<uint8_t> ptrOffset;
ptrOffset.resize(sizeof(test) + 100);
ASSERT_GT(ptrOffset.size(), sizeof(test));
std::memcpy(ptrOffset.get() + 100, &test, sizeof(STest));
pTest = sdv::cast<STest>(static_cast<const sdv::pointer<uint8_t>&>(ptrOffset), 100);
EXPECT_NE(pTest, nullptr);
EXPECT_EQ(std::memcmp(&test, pTest, sizeof(STest)), 0);
// Test with offset, beyond size
sdv::pointer<uint8_t> ptrOffsetBeyond;
ptrOffsetBeyond.resize(sizeof(test) + 100);
ASSERT_GT(ptrOffsetBeyond.size(), sizeof(test));
std::memcpy(ptrOffsetBeyond.get() + 100, &test, sizeof(STest));
pTest = sdv::cast<STest>(static_cast<const sdv::pointer<uint8_t>&>(ptrOffsetBeyond), 101);
EXPECT_EQ(pTest, nullptr);
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

View File

@@ -0,0 +1,869 @@
#include <sstream>
#include <support/pointer.h>
#include "basic_types_test.h"
using CPointerComplexTypeTest = CBasicTypesTest;
struct SComplexStruct
{
sdv::string ssHello = {"Hello"};
uint8_t ui8 = 8u;
uint32_t ui32 = 32u;
std::vector<std::string> vecHello = {"Hello1", "Hello2", "Hello3", "Hello4"};
};
bool operator==(const SComplexStruct& rsLeft, const SComplexStruct& rsRight)
{
return rsLeft.ssHello == rsRight.ssHello && rsLeft.ui8 == rsRight.ui8 && rsLeft.ui32 == rsRight.ui32
&& rsLeft.vecHello == rsRight.vecHello;
}
bool operator<(const SComplexStruct& rsLeft, const SComplexStruct& rsRight)
{
if (rsLeft.ssHello < rsRight.ssHello) return true;
if (rsLeft.ssHello > rsRight.ssHello) return false;
if (rsLeft.ui8 < rsRight.ui8) return true;
if (rsLeft.ui8 > rsRight.ui8) return false;
if (rsLeft.ui32 < rsRight.ui32) return true;
if (rsLeft.ui32 > rsRight.ui32) return false;
if (rsLeft.vecHello < rsRight.vecHello) return true;
if (rsLeft.vecHello > rsRight.vecHello) return false;
return false;
}
template <class U, class V>
inline std::basic_ostream<U, V>& operator<<(std::basic_ostream<U, V>& rstream, const SComplexStruct& rsComplex)
{
rstream << "{" << rsComplex.ssHello << ", " << rsComplex.ui8 << ", " << rsComplex.ui32 << "{";
bool bInitial = true;
for (const std::string& rss : rsComplex.vecHello)
{
if (!bInitial) rstream << ", ";
bInitial = false;
rstream << rss;
}
rstream << "}}";
return rstream;
}
namespace std
{
template <>
struct less<SComplexStruct>
{
bool operator()(const SComplexStruct& rsLeft, const SComplexStruct& rsRight) const
{
if (rsLeft.ssHello < rsRight.ssHello) return true;
if (rsLeft.ssHello > rsRight.ssHello) return false;
if (rsLeft.ui8 < rsRight.ui8) return true;
if (rsLeft.ui8 > rsRight.ui8) return false;
if (rsLeft.ui32 < rsRight.ui32) return true;
if (rsLeft.ui32 > rsRight.ui32) return false;
if (rsLeft.vecHello < rsRight.vecHello) return true;
if (rsLeft.vecHello > rsRight.vecHello) return false;
return false;
}
};
}
TEST_F(CPointerComplexTypeTest, MakeFixedPointer)
{
sdv::pointer<SComplexStruct, 1> ptr0;
EXPECT_TRUE(ptr0);
}
TEST_F(CPointerComplexTypeTest, MakeDynamicPointer)
{
sdv::pointer<SComplexStruct> ptr0 = sdv::make_ptr<SComplexStruct>(0);
EXPECT_TRUE(ptr0);
sdv::pointer<SComplexStruct> ptr1 = sdv::make_ptr<SComplexStruct>();
EXPECT_TRUE(ptr1);
sdv::pointer<SComplexStruct> ptr2 = sdv::make_ptr<SComplexStruct>(2);
EXPECT_TRUE(ptr2);
}
TEST_F(CPointerComplexTypeTest, ConstructorDynamicPointer)
{
// Default constructor
sdv::pointer<SComplexStruct> ptr;
EXPECT_FALSE(ptr);
// Allocate
ptr = sdv::make_ptr<SComplexStruct>();
EXPECT_TRUE(ptr);
// Copy constructor
sdv::pointer<SComplexStruct> ptrCopy(ptr);
EXPECT_TRUE(ptrCopy);
// Move constructor
sdv::pointer<SComplexStruct> ptrMove(std::move(ptr));
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrMove);
// Destructor
GetMemMgr().ResetPtrSet();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
sdv::pointer<SComplexStruct>* pptr = new sdv::pointer<SComplexStruct>(sdv::make_ptr<SComplexStruct>());
EXPECT_NE(pptr, nullptr);
EXPECT_NE(GetMemMgr().GetPtrCount(), 0);
delete pptr;
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
}
TEST_F(CPointerComplexTypeTest, ConstructorFixedPointer)
{
// Default constructor
sdv::pointer<SComplexStruct, 1> ptr;
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0u);
// Copy constructor
sdv::pointer<SComplexStruct, 1> ptrCopy1(ptr);
EXPECT_TRUE(ptrCopy1);
EXPECT_EQ(ptrCopy1.size(), 0u);
sdv::pointer<SComplexStruct, 10> ptrCopy10(ptr);
EXPECT_TRUE(ptrCopy10);
EXPECT_EQ(ptrCopy10.size(), 0u);
using TCopy2 = sdv::pointer<SComplexStruct, 2>;
EXPECT_NO_THROW(TCopy2 ptrCopy2(ptrCopy10));
ptrCopy10.resize(5);
EXPECT_EQ(ptrCopy10.size(), 5u);
using TCopy3 = sdv::pointer<SComplexStruct, 3>;
EXPECT_THROW(TCopy3 ptrCopy3(ptrCopy10), sdv::XBufferTooSmall);
// Move constructor
ptr.resize(1);
EXPECT_EQ(ptr.size(), 1u);
sdv::pointer<SComplexStruct, 1> ptrMove(std::move(ptr));
EXPECT_TRUE(ptr);
EXPECT_TRUE(ptrMove);
EXPECT_EQ(ptr.size(), 0u);
EXPECT_EQ(ptrMove.size(), 1u);
}
TEST_F(CPointerComplexTypeTest, ConstructorMixedPointer)
{
// Default constructor
sdv::pointer<SComplexStruct> ptr0;
sdv::pointer<SComplexStruct, 1> ptr1;
sdv::pointer<SComplexStruct, 5> ptr5;
EXPECT_FALSE(ptr0);
EXPECT_TRUE(ptr1);
EXPECT_TRUE(ptr5);
// Copy constructor
sdv::pointer<SComplexStruct> ptrCopy0a(ptr0);
EXPECT_FALSE(ptrCopy0a);
EXPECT_EQ(ptrCopy0a.size(), 0u);
sdv::pointer<SComplexStruct> ptrCopy0b(ptr1);
EXPECT_TRUE(ptrCopy0b);
EXPECT_EQ(ptrCopy0b.size(), 0u);
sdv::pointer<SComplexStruct> ptrCopy0c(ptr5);
EXPECT_TRUE(ptrCopy0c);
EXPECT_EQ(ptrCopy0c.size(), 0u);
sdv::pointer<SComplexStruct, 1> ptrCopy1a(ptr0);
EXPECT_TRUE(ptrCopy1a);
EXPECT_EQ(ptrCopy1a.size(), 0u);
sdv::pointer<SComplexStruct, 1> ptrCopy1b(ptr1);
EXPECT_TRUE(ptrCopy1b);
EXPECT_EQ(ptrCopy1b.size(), 0u);
sdv::pointer<SComplexStruct, 1> ptrCopy1c(ptr5);
EXPECT_TRUE(ptrCopy1c);
EXPECT_EQ(ptrCopy1c.size(), 0u);
ptr0.resize(3);
ptr1.resize(1);
ptr5.resize(3);
using TCopy2 = sdv::pointer<SComplexStruct, 2>;
EXPECT_THROW(TCopy2 ptrCopy2a(ptr5), sdv::XBufferTooSmall);
sdv::pointer<SComplexStruct, 2> ptrCopy2b(ptr1);
EXPECT_TRUE(ptrCopy2b);
EXPECT_EQ(ptrCopy2b.size(), 1u);
EXPECT_THROW(TCopy2 ptrCopy2c(ptr5), sdv::XBufferTooSmall);
sdv::pointer<SComplexStruct, 3> ptrCopy3a(ptr0);
EXPECT_TRUE(ptrCopy3a);
EXPECT_EQ(ptrCopy3a.size(), 3u);
sdv::pointer<SComplexStruct, 3> ptrCopy3b(ptr1);
EXPECT_TRUE(ptrCopy3b);
EXPECT_EQ(ptrCopy3b.size(), 1u);
sdv::pointer<SComplexStruct, 3> ptrCopy3c(ptr5);
EXPECT_TRUE(ptrCopy3c);
EXPECT_EQ(ptrCopy3c.size(), 3u);
}
TEST_F(CPointerComplexTypeTest, AssignmentOperatorsDynamicPointer)
{
// Create pointer
sdv::pointer<SComplexStruct> ptr = sdv::make_ptr<SComplexStruct>();
EXPECT_TRUE(ptr);
// Copy assignment
sdv::pointer<SComplexStruct> ptrCopy;
EXPECT_FALSE(ptrCopy);
ptrCopy = ptr;
EXPECT_TRUE(ptrCopy);
// Move assignment
sdv::pointer<SComplexStruct> ptrMove;
EXPECT_FALSE(ptrMove);
ptrMove = std::move(ptr);
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrMove);
}
TEST_F(CPointerComplexTypeTest, AssignmentOperatorsFixedPointer)
{
// Copy assignment
sdv::pointer<SComplexStruct, 3> ptr;
sdv::pointer<SComplexStruct, 1> ptrCopy;
EXPECT_TRUE(ptrCopy);
ptrCopy = ptr;
EXPECT_TRUE(ptrCopy);
ptr.resize(1);
EXPECT_EQ(ptr.size(), 1u);
ptrCopy = ptr;
EXPECT_EQ(ptrCopy.size(), 1u);
ptr.resize(2);
EXPECT_EQ(ptr.size(), 2u);
EXPECT_THROW(ptrCopy = ptr, sdv::XBufferTooSmall);
// Move assignment
sdv::pointer<SComplexStruct, 3> ptrMove;
EXPECT_TRUE(ptrMove);
ptrMove = std::move(ptr);
EXPECT_TRUE(ptr);
EXPECT_TRUE(ptrMove);
}
TEST_F(CPointerComplexTypeTest, AssignmentOperatorsMixedPointer)
{
sdv::pointer<SComplexStruct> ptr0;
sdv::pointer<SComplexStruct, 1> ptr1;
sdv::pointer<SComplexStruct, 5> ptr5;
EXPECT_FALSE(ptr0);
EXPECT_TRUE(ptr1);
EXPECT_TRUE(ptr5);
// Copy constructor
sdv::pointer<SComplexStruct> ptrCopy0a;
EXPECT_FALSE(ptrCopy0a);
ptrCopy0a = ptr0;
EXPECT_FALSE(ptrCopy0a);
EXPECT_EQ(ptrCopy0a.size(), 0u);
sdv::pointer<SComplexStruct> ptrCopy0b;
EXPECT_FALSE(ptrCopy0b);
ptrCopy0b = ptr1;
EXPECT_TRUE(ptrCopy0b);
EXPECT_EQ(ptrCopy0b.size(), 0u);
sdv::pointer<SComplexStruct> ptrCopy0c;
EXPECT_FALSE(ptrCopy0c);
ptrCopy0c = ptr5;
EXPECT_TRUE(ptrCopy0c);
EXPECT_EQ(ptrCopy0c.size(), 0u);
sdv::pointer<SComplexStruct, 1> ptrCopy1a;
EXPECT_TRUE(ptrCopy1a);
ptrCopy1a = ptr0;
EXPECT_TRUE(ptrCopy1a);
EXPECT_EQ(ptrCopy1a.size(), 0u);
sdv::pointer<SComplexStruct, 1> ptrCopy1b;
EXPECT_TRUE(ptrCopy1b);
ptrCopy1b = ptr1;
EXPECT_TRUE(ptrCopy1b);
EXPECT_EQ(ptrCopy1b.size(), 0u);
sdv::pointer<SComplexStruct, 1> ptrCopy1c;
EXPECT_TRUE(ptrCopy1c);
ptrCopy1c = ptr5;
EXPECT_TRUE(ptrCopy1c);
EXPECT_EQ(ptrCopy1c.size(), 0u);
ptr0.resize(3);
ptr1.resize(1);
ptr5.resize(3);
sdv::pointer<SComplexStruct, 2> ptrCopy2a;
EXPECT_TRUE(ptrCopy2a);
EXPECT_THROW(ptrCopy2a = ptr5, sdv::XBufferTooSmall);
sdv::pointer<SComplexStruct, 2> ptrCopy2b;
EXPECT_TRUE(ptrCopy2b);
ptrCopy2b = ptr1;
EXPECT_TRUE(ptrCopy2b);
EXPECT_EQ(ptrCopy2b.size(), 1u);
sdv::pointer<SComplexStruct, 2> ptrCopy2c;
EXPECT_TRUE(ptrCopy2c);
EXPECT_THROW(ptrCopy2c = ptr5, sdv::XBufferTooSmall);
sdv::pointer<SComplexStruct, 3> ptrCopy3a;
EXPECT_TRUE(ptrCopy3a);
ptrCopy3a = ptr0;
EXPECT_TRUE(ptrCopy3a);
EXPECT_EQ(ptrCopy3a.size(), 3u);
sdv::pointer<SComplexStruct, 3> ptrCopy3b;
EXPECT_TRUE(ptrCopy3b);
ptrCopy3b = ptr1;
EXPECT_TRUE(ptrCopy3b);
EXPECT_EQ(ptrCopy3b.size(), 1u);
sdv::pointer<SComplexStruct, 3> ptrCopy3c;
EXPECT_TRUE(ptrCopy3c);
ptrCopy3c = ptr5;
EXPECT_TRUE(ptrCopy3c);
EXPECT_EQ(ptrCopy3c.size(), 3u);
}
/**
* @brief Helper class to access attach and detach functions.
* @tparam T Type of the variable to store.
*/
template <typename T>
class CPointerHelper : public sdv::pointer<T>
{
public:
/**
* @brief Attach a uint8_t buffer.
* @param[in] rptrBuffer Reference to the pointer to attach.
*/
void attach(sdv::pointer<uint8_t>&& rptrBuffer)
{
sdv::pointer<T>::attach(std::move(rptrBuffer));
}
/**
* @brief Detach the uint8_t buffer.
* @return Reference to the pointer to detach.
*/
sdv::pointer<uint8_t>&& detach()
{
return std::move(sdv::pointer<T>::detach());
}
};
TEST_F(CPointerComplexTypeTest, AttachmentDynamicPointer)
{
// Create the buffer
sdv::pointer<uint8_t> ptrBuffer = sdv::make_ptr<uint8_t>(25 * sizeof(SComplexStruct));
EXPECT_TRUE(ptrBuffer);
EXPECT_EQ(ptrBuffer.size(), 25 * sizeof(SComplexStruct));
EXPECT_EQ(ptrBuffer.ref_count(), 1);
// Attach
CPointerHelper<SComplexStruct> ptr;
EXPECT_FALSE(ptr);
ptr.attach(std::move(ptrBuffer));
EXPECT_FALSE(ptrBuffer);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 25u);
EXPECT_EQ(ptr.ref_count(), 1);
// Detach
ptrBuffer = ptr.detach();
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrBuffer);
EXPECT_EQ(ptrBuffer.size(), 25 * sizeof(SComplexStruct));
EXPECT_EQ(ptrBuffer.ref_count(), 1);
}
TEST_F(CPointerComplexTypeTest, ResetFunctionStaticPointer)
{
// Create pointer
sdv::pointer<SComplexStruct, 10> ptr;
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10u);
ptr.reset();
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0u);
}
TEST_F(CPointerComplexTypeTest, ResetFunction)
{
// Create pointer
GetMemMgr().ResetPtrSet();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
sdv::pointer<SComplexStruct> ptr = sdv::make_ptr<SComplexStruct>();
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10u);
EXPECT_NE(GetMemMgr().GetPtrCount(), 0);
ptr.reset();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
EXPECT_EQ(ptr.size(), 0u);
}
TEST_F(CPointerComplexTypeTest, SwapFunctionStaticPointer)
{
// Allocate
sdv::pointer<SComplexStruct, 250> ptr1;
EXPECT_TRUE(ptr1);
ptr1.resize(100);
EXPECT_EQ(ptr1.size(), 100u);
sdv::pointer<SComplexStruct, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200u);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200u);
EXPECT_EQ(ptr2.size(), 100u);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100u);
EXPECT_EQ(ptr2.size(), 200u);
// Swap with empty pointer
sdv::pointer<SComplexStruct, 150> ptr3;
ptr3.swap(ptr1);
EXPECT_TRUE(ptr3);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr3.size(), 100u);
EXPECT_EQ(ptr1.size(), 0u);
sdv::pointer<SComplexStruct, 150> ptr4;
EXPECT_THROW(sdv::swap(ptr4, ptr2), sdv::XBufferTooSmall);
}
TEST_F(CPointerComplexTypeTest, SwapFunctionDynamicPointer)
{
// Allocate
sdv::pointer<SComplexStruct> ptr1 = sdv::make_ptr<SComplexStruct>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100u);
sdv::pointer<SComplexStruct> ptr2 = sdv::make_ptr<SComplexStruct>(200);
EXPECT_TRUE(ptr2);
EXPECT_EQ(ptr2.size(), 200u);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200u);
EXPECT_EQ(ptr2.size(), 100u);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100u);
EXPECT_EQ(ptr2.size(), 200u);
// Swap with empty pointer
sdv::pointer<SComplexStruct> ptr3;
ptr3.swap(ptr1);
EXPECT_TRUE(ptr3);
EXPECT_FALSE(ptr1);
sdv::swap(ptr3, ptr1);
EXPECT_FALSE(ptr3);
EXPECT_TRUE(ptr1);
}
TEST_F(CPointerComplexTypeTest, SwapFunctionMixedPointer)
{
// Allocate
sdv::pointer<SComplexStruct> ptr1 = sdv::make_ptr<SComplexStruct>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100u);
sdv::pointer<SComplexStruct, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200u);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200u);
EXPECT_EQ(ptr2.size(), 100u);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100u);
EXPECT_EQ(ptr2.size(), 200u);
}
TEST_F(CPointerComplexTypeTest, AccessFunctions)
{
// Empty pointer
sdv::pointer<SComplexStruct> ptr;
EXPECT_FALSE(ptr);
// Get
EXPECT_EQ(ptr.get(), nullptr);
EXPECT_THROW(*ptr, sdv::XNullPointer);
EXPECT_THROW(ptr->ssHello, sdv::XNullPointer);
// Allocate
ptr = sdv::make_ptr<SComplexStruct>(100);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 100u);
// Get function
EXPECT_NE(ptr.get(), nullptr);
// Assign the value to the array
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
{
EXPECT_EQ(ptr.get()[uiIndex].ssHello, "Hello");
EXPECT_EQ(ptr.get()[uiIndex].ui8, 8u);
EXPECT_EQ(ptr.get()[uiIndex].ui32, 32u);
EXPECT_EQ(ptr.get()[uiIndex].vecHello.size(), 4u);
ptr.get()[uiIndex].ssHello = "Hi" + std::to_string(uiIndex);
ptr.get()[uiIndex].ui8 = 9u + static_cast<uint8_t>(uiIndex);
ptr.get()[uiIndex].ui32 = 33u + uiIndex;
ptr.get()[uiIndex].vecHello = {std::string("Hi1") + std::to_string(uiIndex), std::string("Hi2") + std::to_string(uiIndex)};
}
// Reference functions (getter)
EXPECT_EQ((*ptr).ssHello, "Hi0");
EXPECT_EQ((*ptr).ui8, 9u);
EXPECT_EQ((*ptr).ui32, 33u);
EXPECT_EQ((*ptr).vecHello.size(), 2u);
// Indexed values (getter)
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
{
EXPECT_EQ(ptr[uiIndex].ssHello, std::string("Hi") + std::to_string(uiIndex));
EXPECT_EQ(ptr[uiIndex].ui8, 9u + static_cast<uint8_t>(uiIndex));
EXPECT_EQ(ptr[uiIndex].ui32, 33u + uiIndex);
EXPECT_EQ(ptr[uiIndex].vecHello.size(), 2u);
}
// Reference functions (setter)
(*ptr).ssHello = "Hello mio";
(*ptr).ui8 = 255u;
(*ptr).ui32 = 255u;
(*ptr).vecHello = {"Hello mio1", "Hello mio2", "Hello mio3"};
EXPECT_EQ(ptr.get()->ssHello, "Hello mio");
EXPECT_EQ(ptr.get()->ui8, 255u);
EXPECT_EQ(ptr.get()->ui32, 255u);
EXPECT_EQ(ptr.get()->vecHello.size(), 3u);
// Indexed values (setter)
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
{
ptr[uiIndex].ssHello= "Hi miomio" + std::to_string(uiIndex);
ptr[uiIndex].ui8 = 109u + static_cast<uint8_t>(uiIndex);
ptr[uiIndex].ui32 = 133u + uiIndex;
ptr[uiIndex].vecHello = {std::string("Hi miomio1") + std::to_string(uiIndex),
std::string("Hi miomio2") + std::to_string(uiIndex),
std::string("Hi miomio3") + std::to_string(uiIndex),
std::string("Hi miomio4") + std::to_string(uiIndex),
std::string("Hi miomio5") + std::to_string(uiIndex)};
EXPECT_EQ(ptr.get()[uiIndex].ssHello, std::string("Hi miomio") + std::to_string(uiIndex));
EXPECT_EQ(ptr.get()[uiIndex].ui8, 109u + static_cast<uint8_t>(uiIndex));
EXPECT_EQ(ptr.get()[uiIndex].ui32, 133u + uiIndex);
EXPECT_EQ(ptr.get()[uiIndex].vecHello.size(), 5u);
}
// Resizing to 0 and then back to 100 should reset all elements to the default value.
ptr.resize(0);
EXPECT_TRUE(ptr);
ptr.resize(100);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 100u);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
{
EXPECT_EQ(ptr.get()[uiIndex].ssHello, "Hello");
EXPECT_EQ(ptr.get()[uiIndex].ui8, 8u);
EXPECT_EQ(ptr.get()[uiIndex].ui32, 32u);
EXPECT_EQ(ptr.get()[uiIndex].vecHello.size(), 4u);
}
}
TEST_F(CPointerComplexTypeTest, SizeFunctionsStaticPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct, 150> ptr;
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0u);
EXPECT_EQ(ptr.capacity(), 150);
EXPECT_NO_THROW(ptr.resize(100));
EXPECT_EQ(ptr.size(), 100u);
EXPECT_EQ(ptr.capacity(), 150);
// Resize to many
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex].ui32 = uiIndex + 1000;
EXPECT_THROW(ptr[101], sdv::XIndexOutOfRange);
// Resize smaller
ptr.resize(50);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 50u);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex].ui32, uiIndex + 1000);
EXPECT_THROW(ptr[51], sdv::XIndexOutOfRange);
// Resize larger (the first 50 should still be valid)
ptr.resize(150);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 150u);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex].ui32, uiIndex + 1000);
EXPECT_THROW(ptr[151], sdv::XIndexOutOfRange);
// Exceed buffer capacity
EXPECT_THROW(ptr.resize(151), sdv::XBufferTooSmall);
}
TEST_F(CPointerComplexTypeTest, SizeFunctionsDynamicPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct> ptr;
EXPECT_FALSE(ptr);
EXPECT_EQ(ptr.size(), 0u);
EXPECT_NO_THROW(ptr.resize(100));
EXPECT_EQ(ptr.size(), 100u);
EXPECT_EQ(ptr.capacity(), 100);
// Allocate zero
ptr = sdv::make_ptr<SComplexStruct>(0);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0u);
EXPECT_EQ(ptr.capacity(), 0);
// Resize to many
ptr.resize(100);
EXPECT_EQ(ptr.size(), 100u);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex].ui32 = uiIndex + 1000;
EXPECT_THROW(ptr[101], sdv::XIndexOutOfRange);
// Resize smaller
ptr.resize(50);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 50u);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex].ui32, uiIndex + 1000);
EXPECT_THROW(ptr[51], sdv::XIndexOutOfRange);
// Resize larger (the first 50 should still be valid)
ptr.resize(150);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 150u);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex].ui32, uiIndex + 1000);
EXPECT_THROW(ptr[151], sdv::XIndexOutOfRange);
// Copy the pointer an resize to giant; both pointers should still be valid.
sdv::pointer<SComplexStruct> ptrGiant(ptr);
EXPECT_EQ(ptr, ptrGiant);
ptrGiant.resize(1024 * 8);
EXPECT_EQ(ptr, ptrGiant);
}
TEST_F(CPointerComplexTypeTest, RefCountFunctionDynamicPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct> ptr;
EXPECT_EQ(ptr.ref_count(), 0);
// Allocate
ptr = sdv::make_ptr<SComplexStruct>();
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.ref_count(), 1);
// Copy
sdv::pointer<SComplexStruct> ptrCopy(ptr);
EXPECT_TRUE(ptrCopy);
EXPECT_EQ(ptr.ref_count(), 2);
EXPECT_EQ(ptrCopy.ref_count(), 2);
sdv::pointer<SComplexStruct> ptrCopy2;
EXPECT_FALSE(ptrCopy2);
ptrCopy2 = ptrCopy;
EXPECT_TRUE(ptrCopy2);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 3);
EXPECT_EQ(ptrCopy2.ref_count(), 3);
// Move
sdv::pointer<SComplexStruct> ptrMove(std::move(ptrCopy));
EXPECT_TRUE(ptrMove);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 0);
EXPECT_EQ(ptrCopy2.ref_count(), 3);
EXPECT_EQ(ptrMove.ref_count(), 3);
sdv::pointer<SComplexStruct> ptrMove2;
EXPECT_FALSE(ptrMove2);
ptrMove2 = std::move(ptrCopy2);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 0);
EXPECT_EQ(ptrCopy2.ref_count(), 0);
EXPECT_EQ(ptrMove.ref_count(), 3);
EXPECT_EQ(ptrMove2.ref_count(), 3);
// Reset
ptrMove.reset();
EXPECT_EQ(ptr.ref_count(), 2);
EXPECT_EQ(ptrMove.ref_count(), 0);
EXPECT_EQ(ptrMove2.ref_count(), 2);
ptrMove2.reset();
EXPECT_EQ(ptr.ref_count(), 1);
EXPECT_EQ(ptrMove.ref_count(), 0);
EXPECT_EQ(ptrMove2.ref_count(), 0);
}
TEST_F(CPointerComplexTypeTest, CompareOperatorStaticPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct, 10> ptrLeft;
sdv::pointer<SComplexStruct, 15> ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Resize one pointer and fill with counter
ptrLeft.resize(10);
for (size_t nIndex = 0; nIndex < ptrLeft.size(); nIndex++)
ptrLeft[nIndex].ui32 = static_cast<uint32_t>(nIndex);
EXPECT_EQ(ptrLeft.size(), 10u);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
}
TEST_F(CPointerComplexTypeTest, CompareOperatorDynamicPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct> ptrLeft, ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Allocate one pointer
ptrLeft = sdv::make_ptr<SComplexStruct>(10);
EXPECT_TRUE(ptrLeft);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
// Reallocate left allocation
ptrLeft = sdv::make_ptr<SComplexStruct>(10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
}
TEST_F(CPointerComplexTypeTest, CompareOperatorMixedPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct, 10> ptrLeft;
sdv::pointer<SComplexStruct> ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Resize one pointer and fill with counter
ptrLeft.resize(10);
for (size_t nIndex = 0; nIndex < ptrLeft.size(); nIndex++)
ptrLeft[nIndex].ui32 = static_cast<uint32_t>(nIndex);
EXPECT_EQ(ptrLeft.size(), 10u);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
}
TEST_F(CPointerComplexTypeTest, CompareNullOperatorDynamicPointer)
{
// Empty pointer
sdv::pointer<SComplexStruct> ptr;
EXPECT_TRUE(ptr == nullptr);
EXPECT_TRUE(nullptr == ptr);
EXPECT_FALSE(ptr != nullptr);
EXPECT_FALSE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_FALSE(nullptr < ptr);
EXPECT_TRUE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_FALSE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_TRUE(nullptr >= ptr);
// Allocate one pointer
ptr = sdv::make_ptr<SComplexStruct>(10);
EXPECT_TRUE(ptr);
EXPECT_FALSE(ptr == nullptr);
EXPECT_FALSE(nullptr == ptr);
EXPECT_TRUE(ptr != nullptr);
EXPECT_TRUE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_TRUE(nullptr < ptr);
EXPECT_FALSE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_TRUE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_FALSE(nullptr >= ptr);
// Free allocation
ptr.reset();
EXPECT_TRUE(ptr == nullptr);
EXPECT_TRUE(nullptr == ptr);
EXPECT_FALSE(ptr != nullptr);
EXPECT_FALSE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_FALSE(nullptr < ptr);
EXPECT_TRUE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_FALSE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_TRUE(nullptr >= ptr);
}

View File

@@ -0,0 +1,916 @@
#include <sstream>
#include <support/pointer.h>
#include "basic_types_test.h"
using CPointerSimpleTypeTest = CBasicTypesTest;
TEST_F(CPointerSimpleTypeTest, MakeFixedPointer)
{
sdv::pointer<uint32_t, 1> ptr0;
EXPECT_TRUE(ptr0);
}
TEST_F(CPointerSimpleTypeTest, MakeDynamicPointer)
{
sdv::pointer<uint32_t> ptr0 = sdv::make_ptr<uint32_t>(0);
EXPECT_TRUE(ptr0);
sdv::pointer<uint32_t> ptr1 = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr1);
sdv::pointer<uint32_t> ptr2 = sdv::make_ptr<uint32_t>(2);
EXPECT_TRUE(ptr2);
}
TEST_F(CPointerSimpleTypeTest, ConstructorDynamicPointer)
{
// Default constructor
sdv::pointer<uint32_t> ptr;
EXPECT_FALSE(ptr);
// Allocate
ptr = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr);
// Copy constructor
sdv::pointer<uint32_t> ptrCopy(ptr);
EXPECT_TRUE(ptrCopy);
// Move constructor
sdv::pointer<uint32_t> ptrMove(std::move(ptr));
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrMove);
// Destructor
GetMemMgr().ResetPtrSet();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
sdv::pointer<uint32_t>* pptr = new sdv::pointer<uint32_t>(sdv::make_ptr<uint32_t>());
EXPECT_NE(pptr, nullptr);
EXPECT_NE(GetMemMgr().GetPtrCount(), 0);
delete pptr;
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
}
TEST_F(CPointerSimpleTypeTest, ConstructorFixedPointer)
{
// Default constructor
sdv::pointer<uint32_t, 1> ptr;
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
// Copy constructor
sdv::pointer<uint32_t, 1> ptrCopy1(ptr);
EXPECT_TRUE(ptrCopy1);
EXPECT_EQ(ptrCopy1.size(), 0);
sdv::pointer<uint32_t, 10> ptrCopy10(ptr);
EXPECT_TRUE(ptrCopy10);
EXPECT_EQ(ptrCopy10.size(), 0);
using TCopy2 = sdv::pointer<uint32_t, 2>;
EXPECT_NO_THROW(TCopy2 ptrCopy2(ptrCopy10));
ptrCopy10.resize(5);
EXPECT_EQ(ptrCopy10.size(), 5);
using TCopy3 = sdv::pointer<uint32_t, 3>;
EXPECT_THROW(TCopy3 ptrCopy3(ptrCopy10), sdv::XBufferTooSmall);
// Move constructor
ptr.resize(1);
EXPECT_EQ(ptr.size(), 1);
sdv::pointer<uint32_t, 1> ptrMove(std::move(ptr));
EXPECT_TRUE(ptr);
EXPECT_TRUE(ptrMove);
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(ptrMove.size(), 1);
}
TEST_F(CPointerSimpleTypeTest, ConstructorMixedPointer)
{
// Default constructor
sdv::pointer<uint32_t> ptr0;
sdv::pointer<uint32_t, 1> ptr1;
sdv::pointer<uint32_t, 5> ptr5;
EXPECT_FALSE(ptr0);
EXPECT_TRUE(ptr1);
EXPECT_TRUE(ptr5);
// Copy constructor
sdv::pointer<uint32_t> ptrCopy0a(ptr0);
EXPECT_FALSE(ptrCopy0a);
EXPECT_EQ(ptrCopy0a.size(), 0);
sdv::pointer<uint32_t> ptrCopy0b(ptr1);
EXPECT_TRUE(ptrCopy0b);
EXPECT_EQ(ptrCopy0b.size(), 0);
sdv::pointer<uint32_t> ptrCopy0c(ptr5);
EXPECT_TRUE(ptrCopy0c);
EXPECT_EQ(ptrCopy0c.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1a(ptr0);
EXPECT_TRUE(ptrCopy1a);
EXPECT_EQ(ptrCopy1a.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1b(ptr1);
EXPECT_TRUE(ptrCopy1b);
EXPECT_EQ(ptrCopy1b.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1c(ptr5);
EXPECT_TRUE(ptrCopy1c);
EXPECT_EQ(ptrCopy1c.size(), 0);
ptr0.resize(3);
ptr1.resize(1);
ptr5.resize(3);
using TCopy2 = sdv::pointer<uint32_t, 2>;
EXPECT_THROW(TCopy2 ptrCopy2a(ptr5), sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 2> ptrCopy2b(ptr1);
EXPECT_TRUE(ptrCopy2b);
EXPECT_EQ(ptrCopy2b.size(), 1);
EXPECT_THROW(TCopy2 ptrCopy2c(ptr5), sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 3> ptrCopy3a(ptr0);
EXPECT_TRUE(ptrCopy3a);
EXPECT_EQ(ptrCopy3a.size(), 3);
sdv::pointer<uint32_t, 3> ptrCopy3b(ptr1);
EXPECT_TRUE(ptrCopy3b);
EXPECT_EQ(ptrCopy3b.size(), 1);
sdv::pointer<uint32_t, 3> ptrCopy3c(ptr5);
EXPECT_TRUE(ptrCopy3c);
EXPECT_EQ(ptrCopy3c.size(), 3);
}
TEST_F(CPointerSimpleTypeTest, AssignmentOperatorsDynamicPointer)
{
// Create pointer
sdv::pointer<uint32_t> ptr = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr);
// Copy assignment
sdv::pointer<uint32_t> ptrCopy;
EXPECT_FALSE(ptrCopy);
ptrCopy = ptr;
EXPECT_TRUE(ptrCopy);
// Move assignment
sdv::pointer<uint32_t> ptrMove;
EXPECT_FALSE(ptrMove);
ptrMove = std::move(ptr);
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrMove);
}
TEST_F(CPointerSimpleTypeTest, AssignmentOperatorsFixedPointer)
{
// Copy assignment
sdv::pointer<uint32_t, 3> ptr;
sdv::pointer<uint32_t, 1> ptrCopy;
EXPECT_TRUE(ptrCopy);
ptrCopy = ptr;
EXPECT_TRUE(ptrCopy);
ptr.resize(1);
EXPECT_EQ(ptr.size(), 1);
ptrCopy = ptr;
EXPECT_EQ(ptrCopy.size(), 1);
ptr.resize(2);
EXPECT_EQ(ptr.size(), 2);
EXPECT_THROW(ptrCopy = ptr, sdv::XBufferTooSmall);
// Move assignment
sdv::pointer<uint32_t, 3> ptrMove;
EXPECT_TRUE(ptrMove);
ptrMove = std::move(ptr);
EXPECT_TRUE(ptr);
EXPECT_TRUE(ptrMove);
}
TEST_F(CPointerSimpleTypeTest, AssignmentOperatorsMixedPointer)
{
sdv::pointer<uint32_t> ptr0;
sdv::pointer<uint32_t, 1> ptr1;
sdv::pointer<uint32_t, 5> ptr5;
EXPECT_FALSE(ptr0);
EXPECT_TRUE(ptr1);
EXPECT_TRUE(ptr5);
// Copy constructor
sdv::pointer<uint32_t> ptrCopy0a;
EXPECT_FALSE(ptrCopy0a);
ptrCopy0a = ptr0;
EXPECT_FALSE(ptrCopy0a);
EXPECT_EQ(ptrCopy0a.size(), 0);
sdv::pointer<uint32_t> ptrCopy0b;
EXPECT_FALSE(ptrCopy0b);
ptrCopy0b = ptr1;
EXPECT_TRUE(ptrCopy0b);
EXPECT_EQ(ptrCopy0b.size(), 0);
sdv::pointer<uint32_t> ptrCopy0c;
EXPECT_FALSE(ptrCopy0c);
ptrCopy0c = ptr5;
EXPECT_TRUE(ptrCopy0c);
EXPECT_EQ(ptrCopy0c.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1a;
EXPECT_TRUE(ptrCopy1a);
ptrCopy1a = ptr0;
EXPECT_TRUE(ptrCopy1a);
EXPECT_EQ(ptrCopy1a.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1b;
EXPECT_TRUE(ptrCopy1b);
ptrCopy1b = ptr1;
EXPECT_TRUE(ptrCopy1b);
EXPECT_EQ(ptrCopy1b.size(), 0);
sdv::pointer<uint32_t, 1> ptrCopy1c;
EXPECT_TRUE(ptrCopy1c);
ptrCopy1c = ptr5;
EXPECT_TRUE(ptrCopy1c);
EXPECT_EQ(ptrCopy1c.size(), 0);
ptr0.resize(3);
ptr1.resize(1);
ptr5.resize(3);
sdv::pointer<uint32_t, 2> ptrCopy2a;
EXPECT_TRUE(ptrCopy2a);
EXPECT_THROW(ptrCopy2a = ptr5, sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 2> ptrCopy2b;
EXPECT_TRUE(ptrCopy2b);
ptrCopy2b = ptr1;
EXPECT_TRUE(ptrCopy2b);
EXPECT_EQ(ptrCopy2b.size(), 1);
sdv::pointer<uint32_t, 2> ptrCopy2c;
EXPECT_TRUE(ptrCopy2c);
EXPECT_THROW(ptrCopy2c = ptr5, sdv::XBufferTooSmall);
sdv::pointer<uint32_t, 3> ptrCopy3a;
EXPECT_TRUE(ptrCopy3a);
ptrCopy3a = ptr0;
EXPECT_TRUE(ptrCopy3a);
EXPECT_EQ(ptrCopy3a.size(), 3);
sdv::pointer<uint32_t, 3> ptrCopy3b;
EXPECT_TRUE(ptrCopy3b);
ptrCopy3b = ptr1;
EXPECT_TRUE(ptrCopy3b);
EXPECT_EQ(ptrCopy3b.size(), 1);
sdv::pointer<uint32_t, 3> ptrCopy3c;
EXPECT_TRUE(ptrCopy3c);
ptrCopy3c = ptr5;
EXPECT_TRUE(ptrCopy3c);
EXPECT_EQ(ptrCopy3c.size(), 3);
}
/**
* @brief Helper class to access attach and detach functions.
* @tparam T Type of the variable to store.
*/
template <typename T>
class CPointerHelper : public sdv::pointer<T>
{
public:
/**
* @brief Attach a uint8_t buffer.
* @param[in] rptrBuffer Reference to the pointer to attach.
*/
void attach(sdv::pointer<uint8_t>&& rptrBuffer)
{
sdv::pointer<T>::attach(std::move(rptrBuffer));
}
/**
* @brief Detach the uint8_t buffer.
* @return Reference to the pointer to detach.
*/
sdv::pointer<uint8_t>&& detach()
{
return std::move(sdv::pointer<T>::detach());
}
};
TEST_F(CPointerSimpleTypeTest, AttachmentDynamicPointer)
{
// Create the buffer
sdv::pointer<uint8_t> ptrBuffer = sdv::make_ptr<uint8_t>(101);
EXPECT_TRUE(ptrBuffer);
EXPECT_EQ(ptrBuffer.size(), 101);
EXPECT_EQ(ptrBuffer.ref_count(), 1);
// Attach
CPointerHelper<uint32_t> ptr;
EXPECT_FALSE(ptr);
ptr.attach(std::move(ptrBuffer));
EXPECT_FALSE(ptrBuffer);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 25);
EXPECT_EQ(ptr.ref_count(), 1);
// Detach
ptrBuffer = ptr.detach();
EXPECT_FALSE(ptr);
EXPECT_TRUE(ptrBuffer);
EXPECT_EQ(ptrBuffer.size(), 101);
EXPECT_EQ(ptrBuffer.ref_count(), 1);
}
TEST_F(CPointerSimpleTypeTest, ResetFunctionStaticPointer)
{
// Create pointer
sdv::pointer<uint32_t, 10> ptr;
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10);
ptr.reset();
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
}
TEST_F(CPointerSimpleTypeTest, ResetFunction)
{
// Create pointer
GetMemMgr().ResetPtrSet();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
sdv::pointer<uint32_t> ptr = sdv::make_ptr<uint32_t>();
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10);
EXPECT_NE(GetMemMgr().GetPtrCount(), 0);
ptr.reset();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
EXPECT_EQ(ptr.size(), 0);
}
TEST_F(CPointerSimpleTypeTest, SwapFunctionStaticPointer)
{
// Allocate
sdv::pointer<uint32_t, 250> ptr1;
EXPECT_TRUE(ptr1);
ptr1.resize(100);
EXPECT_EQ(ptr1.size(), 100);
sdv::pointer<uint32_t, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200);
EXPECT_EQ(ptr2.size(), 100);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100);
EXPECT_EQ(ptr2.size(), 200);
// Swap with empty pointer
sdv::pointer<uint32_t, 150> ptr3;
ptr3.swap(ptr1);
EXPECT_TRUE(ptr3);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr3.size(), 100);
EXPECT_EQ(ptr1.size(), 0);
sdv::pointer<uint32_t, 150> ptr4;
EXPECT_THROW(sdv::swap(ptr4, ptr2), sdv::XBufferTooSmall);
}
TEST_F(CPointerSimpleTypeTest, SwapFunctionDynamicPointer)
{
// Allocate
sdv::pointer<uint32_t> ptr1 = sdv::make_ptr<uint32_t>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100);
sdv::pointer<uint32_t> ptr2 = sdv::make_ptr<uint32_t>(200);
EXPECT_TRUE(ptr2);
EXPECT_EQ(ptr2.size(), 200);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200);
EXPECT_EQ(ptr2.size(), 100);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100);
EXPECT_EQ(ptr2.size(), 200);
// Swap with empty pointer
sdv::pointer<uint32_t> ptr3;
ptr3.swap(ptr1);
EXPECT_TRUE(ptr3);
EXPECT_FALSE(ptr1);
sdv::swap(ptr3, ptr1);
EXPECT_FALSE(ptr3);
EXPECT_TRUE(ptr1);
}
TEST_F(CPointerSimpleTypeTest, SwapFunctionMixedPointer)
{
// Allocate
sdv::pointer<uint32_t> ptr1 = sdv::make_ptr<uint32_t>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100);
sdv::pointer<uint32_t, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200);
EXPECT_EQ(ptr2.size(), 100);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100);
EXPECT_EQ(ptr2.size(), 200);
}
TEST_F(CPointerSimpleTypeTest, AccessFunctions)
{
struct STest
{
uint32_t uiValue;
};
// Empty pointer
sdv::pointer<STest> ptr;
EXPECT_FALSE(ptr);
// Get
EXPECT_EQ(ptr.get(), nullptr);
EXPECT_THROW(*ptr, sdv::XNullPointer);
EXPECT_THROW(ptr->uiValue, sdv::XNullPointer);
// Allocate
ptr = sdv::make_ptr<STest>(100);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 100);
// Get function
EXPECT_NE(ptr.get(), nullptr);
// Assign the value to the array
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr.get()[uiIndex].uiValue = uiIndex;
// Reference functions
EXPECT_EQ((*ptr).uiValue, 0u);
*ptr = STest{101u};
EXPECT_EQ(ptr->uiValue, 101u);
EXPECT_EQ((*ptr.get()).uiValue, 101u);
ptr->uiValue = 0;
EXPECT_EQ((*ptr).uiValue, 0u);
EXPECT_EQ((*ptr.get()).uiValue, 0u);
// Indexed values
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex] = STest{uiIndex + 200u};
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
EXPECT_EQ(ptr.get()[uiIndex].uiValue, uiIndex + 200u);
EXPECT_THROW(ptr[100], sdv::XIndexOutOfRange);
}
TEST_F(CPointerSimpleTypeTest, SizeFunctionsStaticPointer)
{
// Empty pointer
sdv::pointer<uint32_t, 150> ptr;
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(ptr.capacity(), 150);
EXPECT_NO_THROW(ptr.resize(100));
EXPECT_EQ(ptr.size(), 100);
EXPECT_EQ(ptr.capacity(), 150);
// Resize to many
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex] = uiIndex + 1000;
EXPECT_THROW(ptr[101], sdv::XIndexOutOfRange);
// Resize smaller
ptr.resize(50);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 50);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[51], sdv::XIndexOutOfRange);
// Resize larger (the first 50 should still be valid)
ptr.resize(150);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 150);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[151], sdv::XIndexOutOfRange);
// Exceed buffer capacity
EXPECT_THROW(ptr.resize(151), sdv::XBufferTooSmall);
}
TEST_F(CPointerSimpleTypeTest, SizeFunctionsDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptr;
EXPECT_FALSE(ptr);
EXPECT_EQ(ptr.size(), 0);
EXPECT_NO_THROW(ptr.resize(100));
EXPECT_EQ(ptr.size(), 100);
EXPECT_EQ(ptr.capacity(), 100);
// Allocate zero
ptr = sdv::make_ptr<uint32_t>(0);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(ptr.capacity(), 0);
// Resize to many
ptr.resize(100);
EXPECT_EQ(ptr.size(), 100);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 100; uiIndex++)
ptr[uiIndex] = uiIndex + 1000;
EXPECT_THROW(ptr[101], sdv::XIndexOutOfRange);
// Resize smaller
ptr.resize(50);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 50);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[51], sdv::XIndexOutOfRange);
// Resize larger (the first 50 should still be valid)
ptr.resize(150);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 150);
for (uint32_t uiIndex = 0; ptr.get() && uiIndex < 50; uiIndex++)
EXPECT_EQ(ptr[uiIndex], uiIndex + 1000);
EXPECT_THROW(ptr[151], sdv::XIndexOutOfRange);
// Copy the pointer an resize to giant; both pointers should still be valid.
sdv::pointer<uint32_t> ptrGiant(ptr);
EXPECT_EQ(ptr, ptrGiant);
ptrGiant.resize(1024 * 1024 * 8);
EXPECT_EQ(ptr, ptrGiant);
}
/**
* @brief Count class increasing the count on construction and descreasing on destruction.
*/
class CCountLifetime
{
public:
/**
* @brief Constructor increasing the counter.
*/
CCountLifetime()
{
m_nCount++;
}
/**
* @brief Copy constructor increasing the counter.
*/
CCountLifetime(const CCountLifetime&)
{
m_nCount++;
}
/**
* @brief Copy constructor increasing the counter.
*/
CCountLifetime(CCountLifetime&)
{
m_nCount++;
}
/**
* @brief Move constructor not increasing the counter.
*/
CCountLifetime(CCountLifetime&&)
{}
/**
* @brief Destructor descreasing the counter.
*/
~CCountLifetime()
{
m_nCount--;
}
/**
* @brief Assignment operator
* @return Reference to this class.
*/
CCountLifetime& operator=(const CCountLifetime&)
{
return *this;
}
/**
* @brief Move operator
* @return Reference to this class.
*/
CCountLifetime& operator=(CCountLifetime&&)
{
return *this;
}
static int m_nCount; ///< Global lifetime counter.
};
int CCountLifetime::m_nCount = 0;
TEST_F(CPointerSimpleTypeTest, LifetimeSizeFunctionsStaticPointer)
{
CCountLifetime::m_nCount = 0;
// Create local scope to test destructor
{
sdv::pointer<CCountLifetime, 1000> ptr;
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(CCountLifetime::m_nCount, 1000);
ptr.resize(100);
EXPECT_EQ(ptr.size(), 100);
EXPECT_EQ(CCountLifetime::m_nCount, 1000);
ptr.resize(20);
EXPECT_EQ(ptr.size(), 20);
EXPECT_EQ(CCountLifetime::m_nCount, 1000);
ptr.resize(500);
EXPECT_EQ(ptr.size(), 500);
EXPECT_EQ(CCountLifetime::m_nCount, 1000);
ptr.reset();
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(CCountLifetime::m_nCount, 1000);
ptr.resize(750);
EXPECT_EQ(ptr.size(), 750);
EXPECT_EQ(CCountLifetime::m_nCount, 1000);
}
EXPECT_EQ(CCountLifetime::m_nCount, 0);
}
TEST_F(CPointerSimpleTypeTest, LifetimeSizeFunctionsDynamicPointer)
{
CCountLifetime::m_nCount = 0;
// Create local scope to test destructor
{
sdv::pointer<CCountLifetime> ptr;
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(CCountLifetime::m_nCount, 0);
ptr.resize(100);
EXPECT_EQ(ptr.size(), 100);
EXPECT_EQ(CCountLifetime::m_nCount, 100);
ptr.resize(20);
EXPECT_EQ(ptr.size(), 20);
EXPECT_EQ(CCountLifetime::m_nCount, 20);
ptr.resize(500);
EXPECT_EQ(ptr.size(), 500);
EXPECT_EQ(CCountLifetime::m_nCount, 500);
ptr.reset();
EXPECT_EQ(ptr.size(), 0);
EXPECT_EQ(CCountLifetime::m_nCount, 0);
ptr.resize(750);
EXPECT_EQ(ptr.size(), 750);
EXPECT_EQ(CCountLifetime::m_nCount, 750);
}
EXPECT_EQ(CCountLifetime::m_nCount, 0);
// Create pointer
CCountLifetime::m_nCount = 0;
sdv::pointer<CCountLifetime> ptr = sdv::make_ptr<CCountLifetime>();
ptr.resize(10);
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.size(), 10u);
EXPECT_EQ(CCountLifetime::m_nCount, 10);
ptr.reset();
EXPECT_EQ(GetMemMgr().GetPtrCount(), 0);
EXPECT_EQ(ptr.size(), 0u);
EXPECT_EQ(CCountLifetime::m_nCount, 0);
// Allocate
sdv::pointer<CCountLifetime> ptr1 = sdv::make_ptr<CCountLifetime>(100);
EXPECT_TRUE(ptr1);
EXPECT_EQ(ptr1.size(), 100u);
sdv::pointer<CCountLifetime, 200> ptr2;
EXPECT_TRUE(ptr2);
ptr2.resize(200);
EXPECT_EQ(ptr2.size(), 200u);
// Swap two pointers
ptr1.swap(ptr2);
EXPECT_EQ(ptr1.size(), 200u);
EXPECT_EQ(ptr2.size(), 100u);
sdv::swap(ptr1, ptr2);
EXPECT_EQ(ptr1.size(), 100u);
EXPECT_EQ(ptr2.size(), 200u);
}
TEST_F(CPointerSimpleTypeTest, RefCountFunctionDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptr;
EXPECT_EQ(ptr.ref_count(), 0);
// Allocate
ptr = sdv::make_ptr<uint32_t>();
EXPECT_TRUE(ptr);
EXPECT_EQ(ptr.ref_count(), 1);
// Copy
sdv::pointer<uint32_t> ptrCopy(ptr);
EXPECT_TRUE(ptrCopy);
EXPECT_EQ(ptr.ref_count(), 2);
EXPECT_EQ(ptrCopy.ref_count(), 2);
sdv::pointer<uint32_t> ptrCopy2;
EXPECT_FALSE(ptrCopy2);
ptrCopy2 = ptrCopy;
EXPECT_TRUE(ptrCopy2);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 3);
EXPECT_EQ(ptrCopy2.ref_count(), 3);
// Move
sdv::pointer<uint32_t> ptrMove(std::move(ptrCopy));
EXPECT_TRUE(ptrMove);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 0);
EXPECT_EQ(ptrCopy2.ref_count(), 3);
EXPECT_EQ(ptrMove.ref_count(), 3);
sdv::pointer<uint32_t> ptrMove2;
EXPECT_FALSE(ptrMove2);
ptrMove2 = std::move(ptrCopy2);
EXPECT_EQ(ptr.ref_count(), 3);
EXPECT_EQ(ptrCopy.ref_count(), 0);
EXPECT_EQ(ptrCopy2.ref_count(), 0);
EXPECT_EQ(ptrMove.ref_count(), 3);
EXPECT_EQ(ptrMove2.ref_count(), 3);
// Reset
ptrMove.reset();
EXPECT_EQ(ptr.ref_count(), 2);
EXPECT_EQ(ptrMove.ref_count(), 0);
EXPECT_EQ(ptrMove2.ref_count(), 2);
ptrMove2.reset();
EXPECT_EQ(ptr.ref_count(), 1);
EXPECT_EQ(ptrMove.ref_count(), 0);
EXPECT_EQ(ptrMove2.ref_count(), 0);
}
TEST_F(CPointerSimpleTypeTest, CompareOperatorStaticPointer)
{
// Empty pointer
sdv::pointer<uint32_t, 10> ptrLeft;
sdv::pointer<uint32_t, 15> ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Resize one pointer and fill with counter
ptrLeft.resize(10);
for (size_t nIndex = 0; nIndex < ptrLeft.size(); nIndex++)
ptrLeft[nIndex] = static_cast<uint32_t>(nIndex);
EXPECT_EQ(ptrLeft.size(), 10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
}
TEST_F(CPointerSimpleTypeTest, CompareOperatorDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptrLeft, ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Allocate one pointer
ptrLeft = sdv::make_ptr<uint32_t>(10);
EXPECT_TRUE(ptrLeft);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
// Reallocate left allocation
ptrLeft = sdv::make_ptr<uint32_t>(10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
}
TEST_F(CPointerSimpleTypeTest, CompareOperatorMixedPointer)
{
// Empty pointer
sdv::pointer<uint32_t, 10> ptrLeft;
sdv::pointer<uint32_t> ptrRight;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Resize one pointer and fill with counter
ptrLeft.resize(10);
for (size_t nIndex = 0; nIndex < ptrLeft.size(); nIndex++)
ptrLeft[nIndex] = static_cast<uint32_t>(nIndex);
EXPECT_EQ(ptrLeft.size(), 10);
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_FALSE(ptrLeft <= ptrRight);
EXPECT_TRUE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Copy the allocation
ptrRight = ptrLeft;
EXPECT_TRUE(ptrLeft == ptrRight);
EXPECT_FALSE(ptrLeft != ptrRight);
EXPECT_FALSE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_TRUE(ptrLeft >= ptrRight);
// Free left allocation
ptrLeft.reset();
EXPECT_FALSE(ptrLeft == ptrRight);
EXPECT_TRUE(ptrLeft != ptrRight);
EXPECT_TRUE(ptrLeft < ptrRight);
EXPECT_TRUE(ptrLeft <= ptrRight);
EXPECT_FALSE(ptrLeft > ptrRight);
EXPECT_FALSE(ptrLeft >= ptrRight);
}
TEST_F(CPointerSimpleTypeTest, CompareNullOperatorDynamicPointer)
{
// Empty pointer
sdv::pointer<uint32_t> ptr;
EXPECT_TRUE(ptr == nullptr);
EXPECT_TRUE(nullptr == ptr);
EXPECT_FALSE(ptr != nullptr);
EXPECT_FALSE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_FALSE(nullptr < ptr);
EXPECT_TRUE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_FALSE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_TRUE(nullptr >= ptr);
// Allocate one pointer
ptr = sdv::make_ptr<uint32_t>(10);
EXPECT_TRUE(ptr);
EXPECT_FALSE(ptr == nullptr);
EXPECT_FALSE(nullptr == ptr);
EXPECT_TRUE(ptr != nullptr);
EXPECT_TRUE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_TRUE(nullptr < ptr);
EXPECT_FALSE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_TRUE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_FALSE(nullptr >= ptr);
// Free allocation
ptr.reset();
EXPECT_TRUE(ptr == nullptr);
EXPECT_TRUE(nullptr == ptr);
EXPECT_FALSE(ptr != nullptr);
EXPECT_FALSE(nullptr != ptr);
EXPECT_FALSE(ptr < nullptr);
EXPECT_FALSE(nullptr < ptr);
EXPECT_TRUE(ptr <= nullptr);
EXPECT_TRUE(nullptr <= ptr);
EXPECT_FALSE(ptr > nullptr);
EXPECT_FALSE(nullptr > ptr);
EXPECT_TRUE(ptr >= nullptr);
EXPECT_TRUE(nullptr >= ptr);
}

View File

@@ -0,0 +1,959 @@
#include <sstream>
#include <support/sequence.h>
#include "basic_types_test.h"
using CComplexSequenceTypeTest = CBasicTypesTest;
struct SComplexNumber
{
uint32_t uiIm;
uint32_t uiRe;
};
inline bool operator==(SComplexNumber s1, SComplexNumber s2)
{
return s1.uiIm == s2.uiIm && s1.uiRe == s2.uiRe;
}
inline bool operator!=(SComplexNumber s1, SComplexNumber s2)
{
return !operator==(s1, s2);
}
inline bool operator<(SComplexNumber s1, SComplexNumber s2)
{
if (s1.uiIm < s2.uiIm)
return true;
if (s1.uiIm != s2.uiIm)
return false;
return s1.uiRe < s2.uiRe;
}
inline bool operator<=(SComplexNumber s1, SComplexNumber s2)
{
if (s1.uiIm < s2.uiIm)
return true;
if (s1.uiIm != s2.uiIm)
return false;
return s1.uiRe <= s2.uiRe;
}
inline bool operator>(SComplexNumber s1, SComplexNumber s2)
{
if (s1.uiIm > s2.uiIm)
return true;
if (s1.uiIm != s2.uiIm)
return false;
return s1.uiRe > s2.uiRe;
}
inline bool operator>=(SComplexNumber s1, SComplexNumber s2)
{
if (s1.uiIm > s2.uiIm)
return true;
if (s1.uiIm != s2.uiIm)
return false;
return s1.uiRe >= s2.uiRe;
}
TEST_F(CComplexSequenceTypeTest, ConstructorStatic)
{
// Empty sequence
sdv::sequence<SComplexNumber> seqEmpty;
EXPECT_TRUE(seqEmpty.empty());
// Fill constructor
SComplexNumber sVal = {100u, 200u};
sdv::sequence<SComplexNumber, 10> seqFill(5, sVal);
EXPECT_FALSE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 5);
EXPECT_EQ(seqFill[0], sVal);
EXPECT_EQ(seqFill[1], sVal);
EXPECT_EQ(seqFill[2], sVal);
EXPECT_EQ(seqFill[3], sVal);
EXPECT_EQ(seqFill[4], sVal);
// Reserve constructor
sdv::sequence<SComplexNumber, 10> seqReserve(10);
EXPECT_FALSE(seqReserve.empty());
EXPECT_EQ(seqReserve.size(), 10);
// Iterator constructor
sdv::sequence<SComplexNumber, 15> seqIterator(seqFill.begin(), seqFill.end());
EXPECT_FALSE(seqIterator.empty());
EXPECT_EQ(seqIterator.size(), 5);
EXPECT_EQ(seqIterator[0], sVal);
EXPECT_EQ(seqIterator[1], sVal);
EXPECT_EQ(seqIterator[2], sVal);
EXPECT_EQ(seqIterator[3], sVal);
EXPECT_EQ(seqIterator[4], sVal);
// Copy constructor
sdv::sequence<SComplexNumber, 12> seqCopy(seqFill);
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 5);
EXPECT_EQ(seqCopy[0], sVal);
EXPECT_EQ(seqCopy[1], sVal);
EXPECT_EQ(seqCopy[2], sVal);
EXPECT_EQ(seqCopy[3], sVal);
EXPECT_EQ(seqCopy[4], sVal);
// Move constructor
sdv::sequence<SComplexNumber, 10> seqMove(std::move(seqFill));
EXPECT_TRUE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 5);
// C++ vector constructor
std::vector<SComplexNumber> vec = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u};
sdv::sequence<SComplexNumber, 5> seqVector(vec);
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], sVal10);
EXPECT_EQ(seqVector[1], sVal20);
EXPECT_EQ(seqVector[2], sVal30);
// Initializer list constructor
sdv::sequence<SComplexNumber, 5> seqIList = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], sVal10);
EXPECT_EQ(seqIList[1], sVal20);
EXPECT_EQ(seqIList[2], sVal30);
}
TEST_F(CComplexSequenceTypeTest, ConstructorDynamic)
{
// Empty sequence
sdv::sequence<SComplexNumber> seqEmpty;
EXPECT_TRUE(seqEmpty.empty());
// Fill constructor
SComplexNumber sVal = {100u, 200u};
sdv::sequence<SComplexNumber> seqFill(5, sVal);
EXPECT_FALSE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 5);
EXPECT_EQ(seqFill[0], sVal);
EXPECT_EQ(seqFill[1], sVal);
EXPECT_EQ(seqFill[2], sVal);
EXPECT_EQ(seqFill[3], sVal);
EXPECT_EQ(seqFill[4], sVal);
// Reserve constructor
sdv::sequence<SComplexNumber> seqReserve(10);
EXPECT_FALSE(seqReserve.empty());
EXPECT_EQ(seqReserve.size(), 10);
// Iterator constructor
sdv::sequence<SComplexNumber> seqIterator(seqFill.begin(), seqFill.end());
EXPECT_FALSE(seqIterator.empty());
EXPECT_EQ(seqIterator.size(), 5);
EXPECT_EQ(seqIterator[0], sVal);
EXPECT_EQ(seqIterator[1], sVal);
EXPECT_EQ(seqIterator[2], sVal);
EXPECT_EQ(seqIterator[3], sVal);
EXPECT_EQ(seqIterator[4], sVal);
// Copy constructor
sdv::sequence<SComplexNumber> seqCopy(seqFill);
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 5);
EXPECT_EQ(seqCopy[0], sVal);
EXPECT_EQ(seqCopy[1], sVal);
EXPECT_EQ(seqCopy[2], sVal);
EXPECT_EQ(seqCopy[3], sVal);
EXPECT_EQ(seqCopy[4], sVal);
// Move constructor
sdv::sequence<SComplexNumber> seqMove(std::move(seqFill));
EXPECT_TRUE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 5);
// C++ vector constructor
std::vector<SComplexNumber> vec = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u};
sdv::sequence<SComplexNumber> seqVector(vec);
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], sVal10);
EXPECT_EQ(seqVector[1], sVal20);
EXPECT_EQ(seqVector[2], sVal30);
// Initializer list constructor
sdv::sequence<SComplexNumber> seqIList = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], sVal10);
EXPECT_EQ(seqIList[1], sVal20);
EXPECT_EQ(seqIList[2], sVal30);
}
TEST_F(CComplexSequenceTypeTest, AssignmentOperatorStatic)
{
sdv::sequence<SComplexNumber, 5> seq = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 3);
EXPECT_EQ(seq[0], sVal10);
EXPECT_EQ(seq[1], sVal20);
EXPECT_EQ(seq[2], sVal30);
// Copy assignment
sdv::sequence<SComplexNumber, 7> seqCopy;
EXPECT_TRUE(seqCopy.empty());
seqCopy = seq;
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 3);
EXPECT_EQ(seqCopy[0], sVal10);
EXPECT_EQ(seqCopy[1], sVal20);
EXPECT_EQ(seqCopy[2], sVal30);
// Move assignment
sdv::sequence<SComplexNumber, 3> seqMove;
EXPECT_TRUE(seqMove.empty());
seqMove = std::move(seq);
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 3);
// C++ vector assignment
std::vector<SComplexNumber> vec = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
sdv::sequence<SComplexNumber, 5> seqVector;
EXPECT_TRUE(seqVector.empty());
seqVector = vec;
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], sVal10);
EXPECT_EQ(seqVector[1], sVal20);
EXPECT_EQ(seqVector[2], sVal30);
// Initializer list assignment
sdv::sequence<SComplexNumber, 5> seqIList;
EXPECT_TRUE(seqIList.empty());
seqIList = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], sVal10);
EXPECT_EQ(seqIList[1], sVal20);
EXPECT_EQ(seqIList[2], sVal30);
}
TEST_F(CComplexSequenceTypeTest, AssignmentOperatorDynamic)
{
sdv::sequence<SComplexNumber> seq = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 3);
EXPECT_EQ(seq[0], sVal10);
EXPECT_EQ(seq[1], sVal20);
EXPECT_EQ(seq[2], sVal30);
// Copy assignment
sdv::sequence<SComplexNumber> seqCopy;
EXPECT_TRUE(seqCopy.empty());
seqCopy = seq;
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 3);
EXPECT_EQ(seqCopy[0], sVal10);
EXPECT_EQ(seqCopy[1], sVal20);
EXPECT_EQ(seqCopy[2], sVal30);
// Move assignment
sdv::sequence<SComplexNumber> seqMove;
EXPECT_TRUE(seqMove.empty());
seqMove = std::move(seq);
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 3);
// C++ vector assignment
std::vector<SComplexNumber> vec = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
sdv::sequence<SComplexNumber> seqVector;
EXPECT_TRUE(seqVector.empty());
seqVector = vec;
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], sVal10);
EXPECT_EQ(seqVector[1], sVal20);
EXPECT_EQ(seqVector[2], sVal30);
// Initializer list assignment
sdv::sequence<SComplexNumber> seqIList;
EXPECT_TRUE(seqIList.empty());
seqIList = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], sVal10);
EXPECT_EQ(seqIList[1], sVal20);
EXPECT_EQ(seqIList[2], sVal30);
}
TEST_F(CComplexSequenceTypeTest, AssignmentFunction)
{
// Fill assignment
sdv::sequence<SComplexNumber> seqFill;
SComplexNumber sVal = {100u, 200u};
seqFill.assign(5, sVal);
EXPECT_FALSE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 5);
EXPECT_EQ(seqFill[0], sVal);
EXPECT_EQ(seqFill[1], sVal);
EXPECT_EQ(seqFill[2], sVal);
EXPECT_EQ(seqFill[3], sVal);
EXPECT_EQ(seqFill[4], sVal);
// Iterator assignment
sdv::sequence<SComplexNumber> seqIterator;
seqIterator.assign(seqFill.begin(), seqFill.end());
EXPECT_FALSE(seqIterator.empty());
EXPECT_EQ(seqIterator.size(), 5);
EXPECT_EQ(seqIterator[0], sVal);
EXPECT_EQ(seqIterator[1], sVal);
EXPECT_EQ(seqIterator[2], sVal);
EXPECT_EQ(seqIterator[3], sVal);
EXPECT_EQ(seqIterator[4], sVal);
// Initializer list assignment
sdv::sequence<SComplexNumber> seqIList;
seqIList.assign({SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}});
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], sVal10);
EXPECT_EQ(seqIList[1], sVal20);
EXPECT_EQ(seqIList[2], sVal30);
}
TEST_F(CComplexSequenceTypeTest, PositionFunction)
{
// Position in the sequence
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u};
sdv::sequence<SComplexNumber> seq1{sVal10, sVal20, sVal30, sVal40, sVal50};
EXPECT_EQ(seq1.at(0), sVal10);
EXPECT_EQ(seq1[0], sVal10);
EXPECT_EQ(seq1.front(), sVal10);
EXPECT_EQ(seq1.at(4), sVal50);
EXPECT_EQ(seq1[4], sVal50);
EXPECT_EQ(seq1.back(), sVal50);
EXPECT_THROW(seq1.at(5), sdv::XIndexOutOfRange);
EXPECT_THROW(seq1[5], sdv::XIndexOutOfRange);
// Empty sequence
sdv::sequence<SComplexNumber> seq2;
EXPECT_THROW(seq2.at(0), sdv::XIndexOutOfRange);
EXPECT_THROW(seq2[0], sdv::XIndexOutOfRange);
EXPECT_THROW(seq2.front(), sdv::XIndexOutOfRange);
EXPECT_THROW(seq2.back(), sdv::XIndexOutOfRange);
// Assignment
SComplexNumber sVal110{110u, 210u};
seq1.at(0) = sVal110;
EXPECT_EQ(seq1[0], sVal110);
seq1[0] = sVal10;
EXPECT_EQ(seq1[0], sVal10);
seq1.front() = sVal110;
EXPECT_EQ(seq1[0], sVal110);
SComplexNumber sVal150{150u, 250u};
seq1.back() = sVal150;
EXPECT_EQ(seq1[4], sVal150);
}
TEST_F(CComplexSequenceTypeTest, CppVectorAccess)
{
// C++ cast operator
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u};
sdv::sequence<SComplexNumber> seq = {sVal10, sVal20, sVal30};
EXPECT_EQ(seq.size(), 3);
std::vector<SComplexNumber> vec;
EXPECT_TRUE(vec.empty());
vec = seq;
EXPECT_EQ(vec.size(), 3);
// Data access
EXPECT_EQ(memcmp(seq.data(), vec.data(), 3 * sizeof(uint32_t)), 0);
}
TEST_F(CComplexSequenceTypeTest, ForwardIteratorBasedAccess)
{
// Empty forward iterator
sdv::sequence<SComplexNumber>::iterator itEmpty;
EXPECT_NO_THROW(itEmpty++);
EXPECT_NO_THROW(itEmpty--);
EXPECT_NO_THROW(itEmpty += 2);
EXPECT_NO_THROW(itEmpty -= 2);
EXPECT_THROW(itEmpty[0], sdv::XIndexOutOfRange);
// Iterator assignment
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u};
sdv::sequence seq{sVal10, sVal20, sVal30, sVal40, sVal50};
EXPECT_NE(itEmpty, seq.begin());
sdv::sequence<SComplexNumber>::iterator itPos = seq.begin();
EXPECT_NE(itEmpty, itPos);
EXPECT_EQ(itPos, seq.begin());
sdv::sequence<SComplexNumber>::iterator itPosCopy;
EXPECT_NE(itPosCopy, itPos);
itPosCopy = itPos;
EXPECT_EQ(itPosCopy, itPos);
sdv::sequence<SComplexNumber>::iterator itPosNew;
EXPECT_NE(itPosNew, itPos);
itPosNew = std::move(itPosCopy);
EXPECT_EQ(itPosNew, itPos);
EXPECT_NE(itPosCopy, itPos);
// Iterator element access
EXPECT_EQ(*itPos, sVal10);
EXPECT_EQ(itPos[0], sVal10);
EXPECT_EQ(itPos[4], sVal50);
EXPECT_THROW(itPos[5], sdv::XIndexOutOfRange);
SComplexNumber sVal110{110u, 210u}, sVal150{150u, 250u};
*itPos = sVal110;
EXPECT_EQ(seq[0], sVal110);
itPos[4] = sVal150;
EXPECT_EQ(seq[4], sVal150);
seq[0] = sVal10;
seq[4] = sVal50;
// Iterator iteration
itPos++;
EXPECT_EQ(*itPos, sVal20);
itPos += 3;
EXPECT_EQ(*itPos, sVal50);
EXPECT_NO_THROW(itPos++); // Increases at the position following last
EXPECT_THROW(*itPos, sdv::XIndexOutOfRange);
EXPECT_EQ(itPos, seq.end());
EXPECT_NO_THROW(itPos++); // Will be ignored; doesn't increase even more
itPos--;
EXPECT_EQ(*itPos, sVal50);
itPos -= 4;
EXPECT_EQ(*itPos, sVal10);
EXPECT_NO_THROW(itPos--); // Will be ignored; doesn't decrease even more
EXPECT_EQ(*itPos, sVal10);
EXPECT_EQ(itPos, seq.begin());
// Const iterator
sdv::sequence<SComplexNumber>::const_iterator itPosConst = seq.cbegin();
EXPECT_EQ(itPos, itPosConst);
itPosConst++;
EXPECT_EQ(*itPosConst, sVal20);
EXPECT_NE(itPosConst, itPos);
itPos++;
EXPECT_EQ(itPosConst, itPos);
EXPECT_EQ(seq.cbegin(), seq.begin());
EXPECT_EQ(seq.begin(), seq.cbegin());
EXPECT_EQ(seq.cend(), seq.end());
EXPECT_EQ(seq.end(), seq.cend());
}
TEST_F(CComplexSequenceTypeTest, ReverseIteratorBasedAccess)
{
// Empty reverse iterator
sdv::sequence<SComplexNumber>::reverse_iterator itEmpty;
EXPECT_NO_THROW(itEmpty--);
EXPECT_NO_THROW(itEmpty++);
EXPECT_NO_THROW(itEmpty -= 2);
EXPECT_NO_THROW(itEmpty += 2);
EXPECT_THROW(itEmpty[0], sdv::XIndexOutOfRange);
// Iterator assignment
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u};
sdv::sequence seq{sVal10, sVal20, sVal30, sVal40, sVal50};
EXPECT_NE(itEmpty, seq.rbegin());
sdv::sequence<SComplexNumber>::reverse_iterator itPos = seq.rbegin();
EXPECT_NE(itEmpty, itPos);
EXPECT_EQ(itPos, seq.rbegin());
sdv::sequence<SComplexNumber>::reverse_iterator itPosCopy;
EXPECT_NE(itPosCopy, itPos);
itPosCopy = itPos;
EXPECT_EQ(itPosCopy, itPos);
sdv::sequence<SComplexNumber>::reverse_iterator itPosNew;
EXPECT_NE(itPosNew, itPos);
itPosNew = std::move(itPosCopy);
EXPECT_EQ(itPosNew, itPos);
EXPECT_NE(itPosCopy, itPos);
// Iterator element access
SComplexNumber sVal110{110u, 210u}, sVal150{150u, 250u};
EXPECT_EQ(*itPos, sVal50);
EXPECT_EQ(itPos[0], sVal50);
EXPECT_EQ(itPos[4], sVal10);
EXPECT_THROW(itPos[5], sdv::XIndexOutOfRange);
*itPos = sVal150;
EXPECT_EQ(seq[4], sVal150);
itPos[4] = sVal110;
EXPECT_EQ(seq[0], sVal110);
seq[0] = sVal10;
seq[4] = sVal50;
// Iterator iteration
itPos++;
EXPECT_EQ(*itPos, sVal40);
itPos += 3;
EXPECT_EQ(*itPos, sVal10);
EXPECT_NO_THROW(itPos++); // Increases at the position following last
EXPECT_THROW(*itPos, sdv::XIndexOutOfRange);
EXPECT_EQ(itPos, seq.rend());
EXPECT_NO_THROW(itPos++); // Will be ignored; doesn't increase even more
itPos--;
EXPECT_EQ(*itPos, sVal10);
itPos -= 4;
EXPECT_EQ(*itPos, sVal50);
EXPECT_NO_THROW(itPos--); // Will be ignored; doesn't decrease even more
EXPECT_EQ(*itPos, sVal50);
EXPECT_EQ(itPos, seq.rbegin());
// Const iterator
sdv::sequence<SComplexNumber>::const_reverse_iterator itPosConst = seq.crbegin();
EXPECT_EQ(itPos, itPosConst);
itPosConst++;
EXPECT_EQ(*itPosConst, sVal40);
EXPECT_NE(itPosConst, itPos);
itPos++;
EXPECT_EQ(itPosConst, itPos);
EXPECT_EQ(seq.crbegin(), seq.rbegin());
EXPECT_EQ(seq.rbegin(), seq.crbegin());
EXPECT_EQ(seq.crend(), seq.rend());
EXPECT_EQ(seq.rend(), seq.crend());
}
TEST_F(CComplexSequenceTypeTest, SequenceCapacityStatic)
{
// Empty string
sdv::sequence<SComplexNumber, 20> seq;
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 20);
// Filled string
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u}, sVal60{60u, 160u};
seq = {sVal10, sVal20, sVal30, sVal40, sVal50};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 20);
// Resize, reserve
seq.resize(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.resize(4);
EXPECT_EQ(seq.size(), 4);
EXPECT_EQ(seq.length(), 4);
EXPECT_EQ(seq.capacity(), 20);
seq.push_back(sVal50);
seq.resize(10, sVal60);
EXPECT_EQ(seq[4], sVal50);
EXPECT_EQ(seq[5], sVal60);
EXPECT_EQ(seq[6], sVal60);
EXPECT_EQ(seq[7], sVal60);
EXPECT_EQ(seq[8], sVal60);
EXPECT_EQ(seq[9], sVal60);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.resize(5);
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 20);
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.reserve(4);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.resize(5);
// Shrink to fit
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.shrink_to_fit();
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
// Clear
seq.clear();
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 20);
}
TEST_F(CComplexSequenceTypeTest, SequenceCapacityDynamic)
{
// Empty string
sdv::sequence<SComplexNumber> seq;
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 0);
// Filled string
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u}, sVal60{60u, 160u};
seq = {sVal10, sVal20, sVal30, sVal40, sVal50};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 5);
// Resize, reserve
seq.resize(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.resize(4);
EXPECT_EQ(seq.size(), 4);
EXPECT_EQ(seq.length(), 4);
EXPECT_EQ(seq.capacity(), 4);
seq.push_back(sVal50);
seq.resize(10, sVal60);
EXPECT_EQ(seq[4], sVal50);
EXPECT_EQ(seq[5], sVal60);
EXPECT_EQ(seq[6], sVal60);
EXPECT_EQ(seq[7], sVal60);
EXPECT_EQ(seq[8], sVal60);
EXPECT_EQ(seq[9], sVal60);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.resize(5);
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 5);
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.reserve(4);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.resize(5);
// Shrink to fit
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.shrink_to_fit();
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
// Clear
seq.clear();
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 0);
}
TEST_F(CComplexSequenceTypeTest, InsertFunction)
{
// Value assignment
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u};
sdv::sequence<SComplexNumber> seq1;
EXPECT_TRUE(seq1.empty());
seq1.insert(seq1.begin(), 3, sVal10);
EXPECT_EQ(seq1[0], sVal10);
EXPECT_EQ(seq1[1], sVal10);
EXPECT_EQ(seq1[2], sVal10);
seq1.insert(seq1.begin(), 2, sVal20);
EXPECT_EQ(seq1[0], sVal20);
EXPECT_EQ(seq1[1], sVal20);
EXPECT_EQ(seq1[2], sVal10);
seq1.insert(seq1.end(), 2, sVal30);
EXPECT_EQ(seq1[4], sVal10);
EXPECT_EQ(seq1[5], sVal30);
EXPECT_EQ(seq1[6], sVal30);
seq1.insert(seq1.begin() + 4, 2, sVal40);
EXPECT_EQ(seq1[0], sVal20);
EXPECT_EQ(seq1[1], sVal20);
EXPECT_EQ(seq1[2], sVal10);
EXPECT_EQ(seq1[3], sVal10);
EXPECT_EQ(seq1[4], sVal40);
EXPECT_EQ(seq1[5], sVal40);
EXPECT_EQ(seq1[6], sVal10);
EXPECT_EQ(seq1[7], sVal30);
EXPECT_EQ(seq1[8], sVal30);
// Iterator assignment
sdv::sequence<SComplexNumber> seq2;
sdv::sequence<SComplexNumber> seq({SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}});
EXPECT_TRUE(seq2.empty());
seq2.insert(seq2.begin(), seq.begin(), seq.end());
EXPECT_EQ(seq2[0], sVal10);
EXPECT_EQ(seq2[1], sVal20);
EXPECT_EQ(seq2[2], sVal30);
seq2.insert(seq2.begin(), seq.begin(), seq.end());
EXPECT_EQ(seq2[0], sVal10);
EXPECT_EQ(seq2[1], sVal20);
EXPECT_EQ(seq2[2], sVal30);
EXPECT_EQ(seq2[3], sVal10);
seq2.insert(seq2.end(), seq.begin(), seq.end());
EXPECT_EQ(seq2[5], sVal30);
EXPECT_EQ(seq2[6], sVal10);
EXPECT_EQ(seq2[7], sVal20);
EXPECT_EQ(seq2[8], sVal30);
seq2.insert(seq2.begin() + 4, seq.begin(), seq.end());
EXPECT_EQ(seq2[0], sVal10);
EXPECT_EQ(seq2[1], sVal20);
EXPECT_EQ(seq2[2], sVal30);
EXPECT_EQ(seq2[3], sVal10);
EXPECT_EQ(seq2[4], sVal10);
EXPECT_EQ(seq2[5], sVal20);
EXPECT_EQ(seq2[6], sVal30);
EXPECT_EQ(seq2[7], sVal20);
EXPECT_EQ(seq2[8], sVal30);
EXPECT_EQ(seq2[9], sVal10);
EXPECT_EQ(seq2[10], sVal20);
EXPECT_EQ(seq2[11], sVal30);
// Initializer list assignment
sdv::sequence<SComplexNumber> seq3;
EXPECT_TRUE(seq3.empty());
seq3.insert(seq3.begin(), {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}});
EXPECT_EQ(seq3[0], sVal10);
EXPECT_EQ(seq3[1], sVal20);
EXPECT_EQ(seq3[2], sVal30);
seq3.insert(seq3.begin(), {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}});
EXPECT_EQ(seq3[0], sVal10);
EXPECT_EQ(seq3[1], sVal20);
EXPECT_EQ(seq3[2], sVal30);
EXPECT_EQ(seq3[3], sVal10);
seq3.insert(seq3.end(), {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}});
EXPECT_EQ(seq3[5], sVal30);
EXPECT_EQ(seq3[6], sVal10);
EXPECT_EQ(seq3[7], sVal20);
EXPECT_EQ(seq3[8], sVal30);
seq3.insert(seq3.begin() + 4, {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}});
EXPECT_EQ(seq3[0], sVal10);
EXPECT_EQ(seq3[1], sVal20);
EXPECT_EQ(seq3[2], sVal30);
EXPECT_EQ(seq3[3], sVal10);
EXPECT_EQ(seq3[4], sVal10);
EXPECT_EQ(seq3[5], sVal20);
EXPECT_EQ(seq3[6], sVal30);
EXPECT_EQ(seq3[7], sVal20);
EXPECT_EQ(seq3[8], sVal30);
EXPECT_EQ(seq3[9], sVal10);
EXPECT_EQ(seq3[10], sVal20);
EXPECT_EQ(seq3[11], sVal30);
}
TEST_F(CComplexSequenceTypeTest, EraseFunction)
{
// Single element erasure
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u}, sVal60{60u, 160u},
sVal70{70u, 170u}, sVal80{80u, 180u}, sVal90{90u, 190u}, sVal100{100u, 200u};
sdv::sequence<SComplexNumber> seq({sVal10, sVal20, sVal30, sVal40, sVal50, sVal60, sVal70, sVal80, sVal90, sVal100});
sdv::sequence<SComplexNumber>::iterator it = seq.begin();
seq.erase(it);
EXPECT_EQ(seq[0], sVal20);
it = seq.end() - 1;
seq.erase(it);
EXPECT_EQ(seq[seq.size() - 1], sVal90);
it = seq.begin() + 4;
seq.erase(it);
EXPECT_EQ(seq[3], sVal50);
EXPECT_EQ(seq[4], sVal70);
seq = {sVal10, sVal20, sVal30, sVal40, sVal50, sVal60, sVal70, sVal80, sVal90, sVal100};
sdv::sequence<SComplexNumber>::const_iterator cit = seq.cbegin();
seq.erase(cit);
EXPECT_EQ(seq[0], sVal20);
cit = seq.cend() - 1;
seq.erase(cit);
EXPECT_EQ(seq[seq.size() - 1], sVal90);
cit = seq.begin() + 4;
seq.erase(cit);
EXPECT_EQ(seq[3], sVal50);
EXPECT_EQ(seq[4], sVal70);
// Element range erasure
seq = {sVal10, sVal20, sVal30, sVal40, sVal50, sVal60, sVal70, sVal80, sVal90, sVal100};
sdv::sequence<SComplexNumber>::iterator it1 = seq.begin();
sdv::sequence<SComplexNumber>::iterator it2 = it1 + 1;
seq.erase(it1, it2);
EXPECT_EQ(seq[0], sVal20);
it1 = seq.end() - 1;
it2 = seq.end();
seq.erase(it1, it2);
EXPECT_EQ(seq[seq.size() - 1], sVal90);
it1 = seq.begin() + 1;
it2 = it1 + 3;
seq.erase(it1, it2);
EXPECT_EQ(seq[0], sVal20);
EXPECT_EQ(seq[1], sVal60);
seq = {sVal10, sVal20, sVal30, sVal40, sVal50, sVal60, sVal70, sVal80, sVal90, sVal100};
sdv::sequence<SComplexNumber>::const_iterator cit1 = seq.cbegin();
sdv::sequence<SComplexNumber>::const_iterator cit2 = cit1 + 1;
seq.erase(cit1, cit2);
EXPECT_EQ(seq[0], sVal20);
cit1 = seq.end() - 1;
cit2 = seq.end();
seq.erase(cit1, cit2);
EXPECT_EQ(seq[seq.size() - 1], sVal90);
cit1 = seq.begin() + 1;
cit2 = cit1 + 3;
seq.erase(cit1, cit2);
EXPECT_EQ(seq[0], sVal20);
EXPECT_EQ(seq[1], sVal60);
}
TEST_F(CComplexSequenceTypeTest, PushPopFunctions)
{
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u};
sdv::sequence<SComplexNumber> seq;
seq.push_back(sVal10);
EXPECT_EQ(seq[0], sVal10);
EXPECT_EQ(seq.size(), 1);
seq.push_back(std::move(sVal20));
EXPECT_EQ(seq[1], sVal20);
EXPECT_EQ(seq.size(), 2);
seq.pop_back();
EXPECT_EQ(seq.size(), 1);
seq.pop_back();
EXPECT_TRUE(seq.empty());
EXPECT_NO_THROW(seq.pop_back());
}
TEST_F(CComplexSequenceTypeTest, SwapFunctionStatic)
{
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u}, sVal60{60u, 160u},
sVal70{70u, 170u};
sdv::sequence<SComplexNumber, 5> seq1 = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
sdv::sequence<SComplexNumber, 10> seq2 = {SComplexNumber{40u, 140u}, SComplexNumber{50u, 150u}, SComplexNumber{60u, 160u}, SComplexNumber{70u, 170u}};
seq1.swap(seq2);
EXPECT_EQ(seq1.size(), 4);
EXPECT_EQ(seq1[0], sVal40);
EXPECT_EQ(seq1[1], sVal50);
EXPECT_EQ(seq1[2], sVal60);
EXPECT_EQ(seq1[3], sVal70);
EXPECT_EQ(seq2.size(), 3);
EXPECT_EQ(seq2[0], sVal10);
EXPECT_EQ(seq2[1], sVal20);
EXPECT_EQ(seq2[2], sVal30);
sdv::swap(seq1, seq2);
EXPECT_EQ(seq1.size(), 3);
EXPECT_EQ(seq1[0], sVal10);
EXPECT_EQ(seq1[1], sVal20);
EXPECT_EQ(seq1[2], sVal30);
EXPECT_EQ(seq2.size(), 4);
EXPECT_EQ(seq2[0], sVal40);
EXPECT_EQ(seq2[1], sVal50);
EXPECT_EQ(seq2[2], sVal60);
EXPECT_EQ(seq2[3], sVal70);
}
TEST_F(CComplexSequenceTypeTest, SwapFunctionDynamic)
{
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u}, sVal60{60u, 160u},
sVal70{70u, 170u};
sdv::sequence<SComplexNumber> seq1 = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
sdv::sequence<SComplexNumber> seq2 = {SComplexNumber{40u, 140u}, SComplexNumber{50u, 150u}, SComplexNumber{60u, 160u}, SComplexNumber{70u, 170u}};
seq1.swap(seq2);
EXPECT_EQ(seq1.size(), 4);
EXPECT_EQ(seq1[0], sVal40);
EXPECT_EQ(seq1[1], sVal50);
EXPECT_EQ(seq1[2], sVal60);
EXPECT_EQ(seq1[3], sVal70);
EXPECT_EQ(seq2.size(), 3);
EXPECT_EQ(seq2[0], sVal10);
EXPECT_EQ(seq2[1], sVal20);
EXPECT_EQ(seq2[2], sVal30);
sdv::swap(seq1, seq2);
EXPECT_EQ(seq1.size(), 3);
EXPECT_EQ(seq1[0], sVal10);
EXPECT_EQ(seq1[1], sVal20);
EXPECT_EQ(seq1[2], sVal30);
EXPECT_EQ(seq2.size(), 4);
EXPECT_EQ(seq2[0], sVal40);
EXPECT_EQ(seq2[1], sVal50);
EXPECT_EQ(seq2[2], sVal60);
EXPECT_EQ(seq2[3], sVal70);
}
TEST_F(CComplexSequenceTypeTest, SwapFunctionMixed)
{
SComplexNumber sVal10{10u, 110u}, sVal20{20u, 120u}, sVal30{30u, 130u}, sVal40{40u, 140u}, sVal50{50u, 150u}, sVal60{60u, 160u},
sVal70{70u, 170u};
sdv::sequence<SComplexNumber, 5> seq1 = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
sdv::sequence<SComplexNumber> seq2 = {SComplexNumber{40u, 140u}, SComplexNumber{50u, 150u}, SComplexNumber{60u, 160u}, SComplexNumber{70u, 170u}};
seq1.swap(seq2);
EXPECT_EQ(seq1.size(), 4);
EXPECT_EQ(seq1[0], sVal40);
EXPECT_EQ(seq1[1], sVal50);
EXPECT_EQ(seq1[2], sVal60);
EXPECT_EQ(seq1[3], sVal70);
EXPECT_EQ(seq2.size(), 3);
EXPECT_EQ(seq2[0], sVal10);
EXPECT_EQ(seq2[1], sVal20);
EXPECT_EQ(seq2[2], sVal30);
sdv::swap(seq1, seq2);
EXPECT_EQ(seq1.size(), 3);
EXPECT_EQ(seq1[0], sVal10);
EXPECT_EQ(seq1[1], sVal20);
EXPECT_EQ(seq1[2], sVal30);
EXPECT_EQ(seq2.size(), 4);
EXPECT_EQ(seq2[0], sVal40);
EXPECT_EQ(seq2[1], sVal50);
EXPECT_EQ(seq2[2], sVal60);
EXPECT_EQ(seq2[3], sVal70);
}
TEST_F(CComplexSequenceTypeTest, CompareOperator)
{
sdv::sequence<SComplexNumber> seq1 = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
sdv::sequence<SComplexNumber> seq2;
EXPECT_FALSE(seq1 == seq2);
EXPECT_TRUE(seq1 != seq2);
EXPECT_FALSE(seq1 < seq2);
EXPECT_FALSE(seq1 <= seq2);
EXPECT_TRUE(seq1 > seq2);
EXPECT_TRUE(seq1 >= seq2);
seq2 = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
EXPECT_TRUE(seq1 == seq2);
EXPECT_FALSE(seq1 != seq2);
EXPECT_FALSE(seq1 < seq2);
EXPECT_TRUE(seq1 <= seq2);
EXPECT_FALSE(seq1 > seq2);
EXPECT_TRUE(seq1 >= seq2);
SComplexNumber sVal40{40u, 140u};
seq2.push_back(sVal40);
EXPECT_FALSE(seq1 == seq2);
EXPECT_TRUE(seq1 != seq2);
EXPECT_TRUE(seq1 < seq2);
EXPECT_TRUE(seq1 <= seq2);
EXPECT_FALSE(seq1 > seq2);
EXPECT_FALSE(seq1 >= seq2);
seq1.clear();
seq2.clear();
EXPECT_TRUE(seq1 == seq2);
EXPECT_FALSE(seq1 != seq2);
EXPECT_FALSE(seq1 < seq2);
EXPECT_TRUE(seq1 <= seq2);
EXPECT_FALSE(seq1 > seq2);
EXPECT_TRUE(seq1 >= seq2);
}
TEST_F(CComplexSequenceTypeTest, IteratorDistance)
{
sdv::sequence<SComplexNumber> seq1 = {SComplexNumber{10u, 110u}, SComplexNumber{20u, 120u}, SComplexNumber{30u, 130u}};
EXPECT_EQ(std::distance(seq1.begin(), seq1.end()), seq1.length());
}

View File

@@ -0,0 +1,883 @@
#include <sstream>
#include <support/sequence.h>
#include "basic_types_test.h"
using CSimpleSequenceTypeTest = CBasicTypesTest;
TEST_F(CSimpleSequenceTypeTest, ConstructorStatic)
{
// Empty sequence
sdv::sequence<uint32_t, 10> seqEmpty;
EXPECT_TRUE(seqEmpty.empty());
// Fill constructor
uint32_t uiVal = 100u;
sdv::sequence<uint32_t, 10> seqFill(5, uiVal);
EXPECT_FALSE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 5);
EXPECT_EQ(seqFill[0], 100u);
EXPECT_EQ(seqFill[1], 100u);
EXPECT_EQ(seqFill[2], 100u);
EXPECT_EQ(seqFill[3], 100u);
EXPECT_EQ(seqFill[4], 100u);
// Reserve constructor
sdv::sequence<uint32_t, 10> seqReserve(10);
EXPECT_FALSE(seqReserve.empty());
EXPECT_EQ(seqReserve.size(), 10);
// Iterator constructor
sdv::sequence<uint32_t, 15> seqIterator(seqFill.begin(), seqFill.end());
EXPECT_FALSE(seqIterator.empty());
EXPECT_EQ(seqIterator.size(), 5);
EXPECT_EQ(seqIterator[0], 100u);
EXPECT_EQ(seqIterator[1], 100u);
EXPECT_EQ(seqIterator[2], 100u);
EXPECT_EQ(seqIterator[3], 100u);
EXPECT_EQ(seqIterator[4], 100u);
// Copy constructor
sdv::sequence<uint32_t, 12> seqCopy(seqFill);
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 5);
EXPECT_EQ(seqCopy[0], 100u);
EXPECT_EQ(seqCopy[1], 100u);
EXPECT_EQ(seqCopy[2], 100u);
EXPECT_EQ(seqCopy[3], 100u);
EXPECT_EQ(seqCopy[4], 100u);
// Move constructor
sdv::sequence<uint32_t, 10> seqMove(std::move(seqFill));
EXPECT_TRUE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 5);
// C++ vector constructor
std::vector<uint32_t> vec = {10u, 20u, 30u};
sdv::sequence<uint32_t, 5> seqVector(vec);
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], 10u);
EXPECT_EQ(seqVector[1], 20u);
EXPECT_EQ(seqVector[2], 30u);
// Initializer list constructor
sdv::sequence<uint32_t, 5> seqIList = {10u, 20u, 30u};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], 10u);
EXPECT_EQ(seqIList[1], 20u);
EXPECT_EQ(seqIList[2], 30u);
}
TEST_F(CSimpleSequenceTypeTest, ConstructorDynamic)
{
// Empty sequence
sdv::sequence<uint32_t> seqEmpty;
EXPECT_TRUE(seqEmpty.empty());
// Fill constructor
uint32_t uiVal = 100u;
sdv::sequence<uint32_t> seqFill(5, uiVal);
EXPECT_FALSE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 5);
EXPECT_EQ(seqFill[0], 100u);
EXPECT_EQ(seqFill[1], 100u);
EXPECT_EQ(seqFill[2], 100u);
EXPECT_EQ(seqFill[3], 100u);
EXPECT_EQ(seqFill[4], 100u);
// Reserve constructor
sdv::sequence<uint32_t> seqReserve(10);
EXPECT_FALSE(seqReserve.empty());
EXPECT_EQ(seqReserve.size(), 10);
// Iterator constructor
sdv::sequence<uint32_t> seqIterator(seqFill.begin(), seqFill.end());
EXPECT_FALSE(seqIterator.empty());
EXPECT_EQ(seqIterator.size(), 5);
EXPECT_EQ(seqIterator[0], 100u);
EXPECT_EQ(seqIterator[1], 100u);
EXPECT_EQ(seqIterator[2], 100u);
EXPECT_EQ(seqIterator[3], 100u);
EXPECT_EQ(seqIterator[4], 100u);
// Copy constructor
sdv::sequence<uint32_t> seqCopy(seqFill);
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 5);
EXPECT_EQ(seqCopy[0], 100u);
EXPECT_EQ(seqCopy[1], 100u);
EXPECT_EQ(seqCopy[2], 100u);
EXPECT_EQ(seqCopy[3], 100u);
EXPECT_EQ(seqCopy[4], 100u);
// Move constructor
sdv::sequence<uint32_t> seqMove(std::move(seqFill));
EXPECT_TRUE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 5);
// C++ vector constructor
std::vector<uint32_t> vec = {10u, 20u, 30u};
sdv::sequence<uint32_t> seqVector(vec);
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], 10u);
EXPECT_EQ(seqVector[1], 20u);
EXPECT_EQ(seqVector[2], 30u);
// Initializer list constructor
sdv::sequence<uint32_t> seqIList = {10u, 20u, 30u};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], 10u);
EXPECT_EQ(seqIList[1], 20u);
EXPECT_EQ(seqIList[2], 30u);
}
TEST_F(CSimpleSequenceTypeTest, AssignmentOperatorStatic)
{
sdv::sequence<uint32_t, 5> seq = {10u, 20u, 30u};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 3);
EXPECT_EQ(seq[0], 10u);
EXPECT_EQ(seq[1], 20u);
EXPECT_EQ(seq[2], 30u);
// Copy assignment
sdv::sequence<uint32_t, 7> seqCopy;
EXPECT_TRUE(seqCopy.empty());
seqCopy = seq;
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 3);
EXPECT_EQ(seqCopy[0], 10u);
EXPECT_EQ(seqCopy[1], 20u);
EXPECT_EQ(seqCopy[2], 30u);
// Move assignment
sdv::sequence<uint32_t, 3> seqMove;
EXPECT_TRUE(seqMove.empty());
seqMove = std::move(seq);
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 3);
// C++ vector assignment
std::vector<uint32_t> vec = {10u, 20u, 30u};
sdv::sequence<uint32_t, 5> seqVector;
EXPECT_TRUE(seqVector.empty());
seqVector = vec;
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], 10u);
EXPECT_EQ(seqVector[1], 20u);
EXPECT_EQ(seqVector[2], 30u);
// Initializer list assignment
sdv::sequence<uint32_t, 5> seqIList;
EXPECT_TRUE(seqIList.empty());
seqIList = {10u, 20u, 30u};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], 10u);
EXPECT_EQ(seqIList[1], 20u);
EXPECT_EQ(seqIList[2], 30u);
}
TEST_F(CSimpleSequenceTypeTest, AssignmentOperatorDynamic)
{
sdv::sequence<uint32_t> seq = {10u, 20u, 30u};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 3);
EXPECT_EQ(seq[0], 10u);
EXPECT_EQ(seq[1], 20u);
EXPECT_EQ(seq[2], 30u);
// Copy assignment
sdv::sequence<uint32_t> seqCopy;
EXPECT_TRUE(seqCopy.empty());
seqCopy = seq;
EXPECT_FALSE(seqCopy.empty());
EXPECT_EQ(seqCopy.size(), 3);
EXPECT_EQ(seqCopy[0], 10u);
EXPECT_EQ(seqCopy[1], 20u);
EXPECT_EQ(seqCopy[2], 30u);
// Move assignment
sdv::sequence<uint32_t> seqMove;
EXPECT_TRUE(seqMove.empty());
seqMove = std::move(seq);
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_FALSE(seqMove.empty());
EXPECT_EQ(seqMove.size(), 3);
// C++ vector assignment
std::vector<uint32_t> vec = {10u, 20u, 30u};
sdv::sequence<uint32_t> seqVector;
EXPECT_TRUE(seqVector.empty());
seqVector = vec;
EXPECT_FALSE(seqVector.empty());
EXPECT_EQ(seqVector.size(), 3);
EXPECT_EQ(seqVector[0], 10u);
EXPECT_EQ(seqVector[1], 20u);
EXPECT_EQ(seqVector[2], 30u);
// Initializer list assignment
sdv::sequence<uint32_t> seqIList;
EXPECT_TRUE(seqIList.empty());
seqIList = {10u, 20u, 30u};
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], 10u);
EXPECT_EQ(seqIList[1], 20u);
EXPECT_EQ(seqIList[2], 30u);
}
TEST_F(CSimpleSequenceTypeTest, AssignmentFunction)
{
// Fill assignment
sdv::sequence<uint32_t> seqFill;
uint32_t uiVal = 100;
seqFill.assign(5, uiVal);
EXPECT_FALSE(seqFill.empty());
EXPECT_EQ(seqFill.size(), 5);
EXPECT_EQ(seqFill[0], 100u);
EXPECT_EQ(seqFill[1], 100u);
EXPECT_EQ(seqFill[2], 100u);
EXPECT_EQ(seqFill[3], 100u);
EXPECT_EQ(seqFill[4], 100u);
// Iterator assignment
sdv::sequence<uint32_t> seqIterator;
seqIterator.assign(seqFill.begin(), seqFill.end());
EXPECT_FALSE(seqIterator.empty());
EXPECT_EQ(seqIterator.size(), 5);
EXPECT_EQ(seqIterator[0], 100u);
EXPECT_EQ(seqIterator[1], 100u);
EXPECT_EQ(seqIterator[2], 100u);
EXPECT_EQ(seqIterator[3], 100u);
EXPECT_EQ(seqIterator[4], 100u);
// Initializer list assignment
sdv::sequence<uint32_t> seqIList;
seqIList.assign({10u, 20u, 30u});
EXPECT_FALSE(seqIList.empty());
EXPECT_EQ(seqIList.size(), 3);
EXPECT_EQ(seqIList[0], 10u);
EXPECT_EQ(seqIList[1], 20u);
EXPECT_EQ(seqIList[2], 30u);
}
TEST_F(CSimpleSequenceTypeTest, PositionFunction)
{
// Position in the sequence
sdv::sequence<uint32_t> seq1({10u, 20u, 30u, 40u, 50u});
EXPECT_EQ(seq1.at(0), 10u);
EXPECT_EQ(seq1[0], 10u);
EXPECT_EQ(seq1.front(), 10u);
EXPECT_EQ(seq1.at(4), 50u);
EXPECT_EQ(seq1[4], 50u);
EXPECT_EQ(seq1.back(), 50u);
EXPECT_THROW(seq1.at(5), sdv::XIndexOutOfRange);
EXPECT_THROW(seq1[5], sdv::XIndexOutOfRange);
// Empty sequence
sdv::sequence<uint32_t> seq2;
EXPECT_THROW(seq2.at(0), sdv::XIndexOutOfRange);
EXPECT_THROW(seq2[0], sdv::XIndexOutOfRange);
EXPECT_THROW(seq2.front(), sdv::XIndexOutOfRange);
EXPECT_THROW(seq2.back(), sdv::XIndexOutOfRange);
// Assignment
seq1.at(0) = 110u;
EXPECT_EQ(seq1[0], 110u);
seq1[0] = 10u;
EXPECT_EQ(seq1[0], 10u);
seq1.front() = 110u;
EXPECT_EQ(seq1[0], 110u);
seq1.back() = 150u;
EXPECT_EQ(seq1[4], 150u);
}
TEST_F(CSimpleSequenceTypeTest, CppVectorAccess)
{
// C++ cast operator
sdv::sequence<uint32_t> seq = {10u, 20u, 30u};
EXPECT_EQ(seq.size(), 3);
std::vector<uint32_t> vec;
EXPECT_TRUE(vec.empty());
vec = seq;
EXPECT_EQ(vec.size(), 3);
// Data access
EXPECT_EQ(memcmp(seq.data(), vec.data(), 3 * sizeof(uint32_t)), 0);
}
TEST_F(CSimpleSequenceTypeTest, ForwardIteratorBasedAccess)
{
// Empty forward iterator
sdv::sequence<uint32_t>::iterator itEmpty;
EXPECT_NO_THROW(itEmpty++);
EXPECT_NO_THROW(itEmpty--);
EXPECT_NO_THROW(itEmpty += 2);
EXPECT_NO_THROW(itEmpty -= 2);
EXPECT_THROW(itEmpty[0], sdv::XIndexOutOfRange);
// Iterator assignment
sdv::sequence seq({10u, 20u, 30u, 40u, 50u});
EXPECT_NE(itEmpty, seq.begin());
sdv::sequence<uint32_t>::iterator itPos = seq.begin();
EXPECT_NE(itEmpty, itPos);
EXPECT_EQ(itPos, seq.begin());
sdv::sequence<uint32_t>::iterator itPosCopy;
EXPECT_NE(itPosCopy, itPos);
itPosCopy = itPos;
EXPECT_EQ(itPosCopy, itPos);
sdv::sequence<uint32_t>::iterator itPosNew;
EXPECT_NE(itPosNew, itPos);
itPosNew = std::move(itPosCopy);
EXPECT_EQ(itPosNew, itPos);
EXPECT_NE(itPosCopy, itPos);
// Iterator element access
EXPECT_EQ(*itPos, 10u);
EXPECT_EQ(itPos[0], 10u);
EXPECT_EQ(itPos[4], 50u);
EXPECT_THROW(itPos[5], sdv::XIndexOutOfRange);
*itPos = 110u;
EXPECT_EQ(seq[0], 110u);
itPos[4] = 150u;
EXPECT_EQ(seq[4], 150u);
seq[0] = 10u;
seq[4] = 50u;
// Iterator iteration
itPos++;
EXPECT_EQ(*itPos, 20u);
itPos += 3;
EXPECT_EQ(*itPos, 50u);
EXPECT_NO_THROW(itPos++); // Increases at the position following last
EXPECT_THROW(*itPos, sdv::XIndexOutOfRange);
EXPECT_EQ(itPos, seq.end());
EXPECT_NO_THROW(itPos++); // Will be ignored; doesn't increase even more
itPos--;
EXPECT_EQ(*itPos, 50u);
itPos -= 4;
EXPECT_EQ(*itPos, 10u);
EXPECT_NO_THROW(itPos--); // Will be ignored; doesn't decrease even more
EXPECT_EQ(*itPos, 10u);
EXPECT_EQ(itPos, seq.begin());
// Const iterator
sdv::sequence<uint32_t>::const_iterator itPosConst = seq.cbegin();
EXPECT_EQ(itPos, itPosConst);
itPosConst++;
EXPECT_EQ(*itPosConst, 20u);
EXPECT_NE(itPosConst, itPos);
itPos++;
EXPECT_EQ(itPosConst, itPos);
EXPECT_EQ(seq.cbegin(), seq.begin());
EXPECT_EQ(seq.begin(), seq.cbegin());
EXPECT_EQ(seq.cend(), seq.end());
EXPECT_EQ(seq.end(), seq.cend());
}
TEST_F(CSimpleSequenceTypeTest, ReverseIteratorBasedAccess)
{
// Empty reverse iterator
sdv::sequence<uint32_t>::reverse_iterator itEmpty;
EXPECT_NO_THROW(itEmpty--);
EXPECT_NO_THROW(itEmpty++);
EXPECT_NO_THROW(itEmpty -= 2);
EXPECT_NO_THROW(itEmpty += 2);
EXPECT_THROW(itEmpty[0], sdv::XIndexOutOfRange);
// Iterator assignment
sdv::sequence seq({10u, 20u, 30u, 40u, 50u});
EXPECT_NE(itEmpty, seq.rbegin());
sdv::sequence<uint32_t>::reverse_iterator itPos = seq.rbegin();
EXPECT_NE(itEmpty, itPos);
EXPECT_EQ(itPos, seq.rbegin());
sdv::sequence<uint32_t>::reverse_iterator itPosCopy;
EXPECT_NE(itPosCopy, itPos);
itPosCopy = itPos;
EXPECT_EQ(itPosCopy, itPos);
sdv::sequence<uint32_t>::reverse_iterator itPosNew;
EXPECT_NE(itPosNew, itPos);
itPosNew = std::move(itPosCopy);
EXPECT_EQ(itPosNew, itPos);
EXPECT_NE(itPosCopy, itPos);
// Iterator element access
EXPECT_EQ(*itPos, 50u);
EXPECT_EQ(itPos[0], 50u);
EXPECT_EQ(itPos[4], 10u);
EXPECT_THROW(itPos[5], sdv::XIndexOutOfRange);
*itPos = 150u;
EXPECT_EQ(seq[4], 150u);
itPos[4] = 110u;
EXPECT_EQ(seq[0], 110u);
seq[0] = 10u;
seq[4] = 50u;
// Iterator iteration
itPos++;
EXPECT_EQ(*itPos, 40u);
itPos += 3;
EXPECT_EQ(*itPos, 10u);
EXPECT_NO_THROW(itPos++); // Increases at the position following last
EXPECT_THROW(*itPos, sdv::XIndexOutOfRange);
EXPECT_EQ(itPos, seq.rend());
EXPECT_NO_THROW(itPos++); // Will be ignored; doesn't increase even more
itPos--;
EXPECT_EQ(*itPos, 10u);
itPos -= 4;
EXPECT_EQ(*itPos, 50u);
EXPECT_NO_THROW(itPos--); // Will be ignored; doesn't decrease even more
EXPECT_EQ(*itPos, 50u);
EXPECT_EQ(itPos, seq.rbegin());
// Const iterator
sdv::sequence<uint32_t>::const_reverse_iterator itPosConst = seq.crbegin();
EXPECT_EQ(itPos, itPosConst);
itPosConst++;
EXPECT_EQ(*itPosConst, 40u);
EXPECT_NE(itPosConst, itPos);
itPos++;
EXPECT_EQ(itPosConst, itPos);
EXPECT_EQ(seq.crbegin(), seq.rbegin());
EXPECT_EQ(seq.rbegin(), seq.crbegin());
EXPECT_EQ(seq.crend(), seq.rend());
EXPECT_EQ(seq.rend(), seq.crend());
}
TEST_F(CSimpleSequenceTypeTest, SequenceCapacityStatic)
{
// Empty string
sdv::sequence<uint32_t, 20> seq;
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 20);
// Filled string
seq = {10u, 20u, 30u, 40u, 50u};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 20);
// Resize, reserve
seq.resize(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.resize(4);
EXPECT_EQ(seq.size(), 4);
EXPECT_EQ(seq.length(), 4);
EXPECT_EQ(seq.capacity(), 20);
seq.push_back(50u);
seq.resize(10, 60u);
EXPECT_EQ(seq[4], 50u);
EXPECT_EQ(seq[5], 60u);
EXPECT_EQ(seq[6], 60u);
EXPECT_EQ(seq[7], 60u);
EXPECT_EQ(seq[8], 60u);
EXPECT_EQ(seq[9], 60u);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.resize(5);
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 20);
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.reserve(4);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.resize(5);
// Shrink to fit
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
seq.shrink_to_fit();
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 20);
// Clear
seq.clear();
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 20);
}
TEST_F(CSimpleSequenceTypeTest, SequenceCapacityDynamic)
{
// Empty string
sdv::sequence<uint32_t> seq;
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 0);
// Filled string
seq = {10u, 20u, 30u, 40u, 50u};
EXPECT_FALSE(seq.empty());
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 5);
// Resize, reserve
seq.resize(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.resize(4);
EXPECT_EQ(seq.size(), 4);
EXPECT_EQ(seq.length(), 4);
EXPECT_EQ(seq.capacity(), 4);
seq.push_back(50u);
seq.resize(10, 60u);
EXPECT_EQ(seq[4], 50u);
EXPECT_EQ(seq[5], 60u);
EXPECT_EQ(seq[6], 60u);
EXPECT_EQ(seq[7], 60u);
EXPECT_EQ(seq[8], 60u);
EXPECT_EQ(seq[9], 60u);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.resize(5);
EXPECT_EQ(seq.size(), 5);
EXPECT_EQ(seq.length(), 5);
EXPECT_EQ(seq.capacity(), 5);
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.reserve(4);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.resize(5);
// Shrink to fit
seq.reserve(10);
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
seq.shrink_to_fit();
EXPECT_EQ(seq.size(), 10);
EXPECT_EQ(seq.length(), 10);
EXPECT_EQ(seq.capacity(), 10);
// Clear
seq.clear();
EXPECT_TRUE(seq.empty());
EXPECT_EQ(seq.size(), 0);
EXPECT_EQ(seq.length(), 0);
EXPECT_EQ(seq.capacity(), 0);
}
TEST_F(CSimpleSequenceTypeTest, InsertFunction)
{
// Value assignment
sdv::sequence<uint32_t> seq1;
EXPECT_TRUE(seq1.empty());
seq1.insert(seq1.begin(), 3, 10u);
EXPECT_EQ(seq1[0], 10u);
EXPECT_EQ(seq1[1], 10u);
EXPECT_EQ(seq1[2], 10u);
seq1.insert(seq1.begin(), 2, 20u);
EXPECT_EQ(seq1[0], 20u);
EXPECT_EQ(seq1[1], 20u);
EXPECT_EQ(seq1[2], 10u);
seq1.insert(seq1.end(), 2, 30u);
EXPECT_EQ(seq1[4], 10u);
EXPECT_EQ(seq1[5], 30u);
EXPECT_EQ(seq1[6], 30u);
seq1.insert(seq1.begin() + 4, 2, 40u);
EXPECT_EQ(seq1[0], 20u);
EXPECT_EQ(seq1[1], 20u);
EXPECT_EQ(seq1[2], 10u);
EXPECT_EQ(seq1[3], 10u);
EXPECT_EQ(seq1[4], 40u);
EXPECT_EQ(seq1[5], 40u);
EXPECT_EQ(seq1[6], 10u);
EXPECT_EQ(seq1[7], 30u);
EXPECT_EQ(seq1[8], 30u);
// Iterator assignment
sdv::sequence<uint32_t> seq2;
sdv::sequence<uint32_t> seq({10u, 20u, 30u});
EXPECT_TRUE(seq2.empty());
seq2.insert(seq2.begin(), seq.begin(), seq.end());
EXPECT_EQ(seq2[0], 10u);
EXPECT_EQ(seq2[1], 20u);
EXPECT_EQ(seq2[2], 30u);
seq2.insert(seq2.begin(), seq.begin(), seq.end());
EXPECT_EQ(seq2[0], 10u);
EXPECT_EQ(seq2[1], 20u);
EXPECT_EQ(seq2[2], 30u);
EXPECT_EQ(seq2[3], 10u);
seq2.insert(seq2.end(), seq.begin(), seq.end());
EXPECT_EQ(seq2[5], 30u);
EXPECT_EQ(seq2[6], 10u);
EXPECT_EQ(seq2[7], 20u);
EXPECT_EQ(seq2[8], 30u);
seq2.insert(seq2.begin() + 4, seq.begin(), seq.end());
EXPECT_EQ(seq2[0], 10u);
EXPECT_EQ(seq2[1], 20u);
EXPECT_EQ(seq2[2], 30u);
EXPECT_EQ(seq2[3], 10u);
EXPECT_EQ(seq2[4], 10u);
EXPECT_EQ(seq2[5], 20u);
EXPECT_EQ(seq2[6], 30u);
EXPECT_EQ(seq2[7], 20u);
EXPECT_EQ(seq2[8], 30u);
EXPECT_EQ(seq2[9], 10u);
EXPECT_EQ(seq2[10], 20u);
EXPECT_EQ(seq2[11], 30u);
// Initializer list assignment
sdv::sequence<uint32_t> seq3;
EXPECT_TRUE(seq3.empty());
seq3.insert(seq3.begin(), {10u, 20u, 30u});
EXPECT_EQ(seq3[0], 10u);
EXPECT_EQ(seq3[1], 20u);
EXPECT_EQ(seq3[2], 30u);
seq3.insert(seq3.begin(), {10u, 20u, 30u});
EXPECT_EQ(seq3[0], 10u);
EXPECT_EQ(seq3[1], 20u);
EXPECT_EQ(seq3[2], 30u);
EXPECT_EQ(seq3[3], 10u);
seq3.insert(seq3.end(), {10u, 20u, 30u});
EXPECT_EQ(seq3[5], 30u);
EXPECT_EQ(seq3[6], 10u);
EXPECT_EQ(seq3[7], 20u);
EXPECT_EQ(seq3[8], 30u);
seq3.insert(seq3.begin() + 4, {10u, 20u, 30u});
EXPECT_EQ(seq3[0], 10u);
EXPECT_EQ(seq3[1], 20u);
EXPECT_EQ(seq3[2], 30u);
EXPECT_EQ(seq3[3], 10u);
EXPECT_EQ(seq3[4], 10u);
EXPECT_EQ(seq3[5], 20u);
EXPECT_EQ(seq3[6], 30u);
EXPECT_EQ(seq3[7], 20u);
EXPECT_EQ(seq3[8], 30u);
EXPECT_EQ(seq3[9], 10u);
EXPECT_EQ(seq3[10], 20u);
EXPECT_EQ(seq3[11], 30u);
}
TEST_F(CSimpleSequenceTypeTest, EraseFunction)
{
// Single element erasure
sdv::sequence<uint32_t> seq({10u, 20u, 30u, 40u, 50u, 60u, 70u, 80u, 90u, 100u});
sdv::sequence<uint32_t>::iterator it = seq.begin();
seq.erase(it);
EXPECT_EQ(seq[0], 20u);
it = seq.end() - 1;
seq.erase(it);
EXPECT_EQ(seq[seq.size() - 1], 90u);
it = seq.begin() + 4;
seq.erase(it);
EXPECT_EQ(seq[3], 50u);
EXPECT_EQ(seq[4], 70u);
seq = {10u, 20u, 30u, 40u, 50u, 60u, 70u, 80u, 90u, 100u};
sdv::sequence<uint32_t>::const_iterator cit = seq.cbegin();
seq.erase(cit);
EXPECT_EQ(seq[0], 20u);
cit = seq.cend() - 1;
seq.erase(cit);
EXPECT_EQ(seq[seq.size() - 1], 90u);
cit = seq.begin() + 4;
seq.erase(cit);
EXPECT_EQ(seq[3], 50u);
EXPECT_EQ(seq[4], 70u);
// Element range erasure
seq = {10u, 20u, 30u, 40u, 50u, 60u, 70u, 80u, 90u, 100u};
sdv::sequence<uint32_t>::iterator it1 = seq.begin();
sdv::sequence<uint32_t>::iterator it2 = it1 + 1;
seq.erase(it1, it2);
EXPECT_EQ(seq[0], 20u);
it1 = seq.end() - 1;
it2 = seq.end();
seq.erase(it1, it2);
EXPECT_EQ(seq[seq.size() - 1], 90u);
it1 = seq.begin() + 1;
it2 = it1 + 3;
seq.erase(it1, it2);
EXPECT_EQ(seq[0], 20u);
EXPECT_EQ(seq[1], 60u);
seq = {10u, 20u, 30u, 40u, 50u, 60u, 70u, 80u, 90u, 100u};
sdv::sequence<uint32_t>::const_iterator cit1 = seq.cbegin();
sdv::sequence<uint32_t>::const_iterator cit2 = cit1 + 1;
seq.erase(cit1, cit2);
EXPECT_EQ(seq[0], 20u);
cit1 = seq.end() - 1;
cit2 = seq.end();
seq.erase(cit1, cit2);
EXPECT_EQ(seq[seq.size() - 1], 90u);
cit1 = seq.begin() + 1;
cit2 = cit1 + 3;
seq.erase(cit1, cit2);
EXPECT_EQ(seq[0], 20u);
EXPECT_EQ(seq[1], 60u);
}
TEST_F(CSimpleSequenceTypeTest, PushPopFunctions)
{
sdv::sequence<uint32_t> seq;
uint32_t uiVal1 = 10u;
seq.push_back(10u);
EXPECT_EQ(seq[0], uiVal1);
EXPECT_EQ(seq.size(), 1);
uint32_t uiVal2 = 20u;
seq.push_back(std::move(uiVal2));
EXPECT_EQ(seq[1], 20u);
EXPECT_EQ(seq.size(), 2);
seq.pop_back();
EXPECT_EQ(seq.size(), 1);
seq.pop_back();
EXPECT_TRUE(seq.empty());
EXPECT_NO_THROW(seq.pop_back());
}
TEST_F(CSimpleSequenceTypeTest, SwapFunctionStatic)
{
sdv::sequence<uint32_t, 5> seq1 = {10u, 20u, 30u};
sdv::sequence<uint32_t, 10> seq2 = {40u, 50u, 60u, 70u};
seq1.swap(seq2);
EXPECT_EQ(seq1.size(), 4);
EXPECT_EQ(seq1[0], 40u);
EXPECT_EQ(seq1[1], 50u);
EXPECT_EQ(seq1[2], 60u);
EXPECT_EQ(seq1[3], 70u);
EXPECT_EQ(seq2.size(), 3);
EXPECT_EQ(seq2[0], 10u);
EXPECT_EQ(seq2[1], 20u);
EXPECT_EQ(seq2[2], 30u);
sdv::swap(seq1, seq2);
EXPECT_EQ(seq1.size(), 3);
EXPECT_EQ(seq1[0], 10u);
EXPECT_EQ(seq1[1], 20u);
EXPECT_EQ(seq1[2], 30u);
EXPECT_EQ(seq2.size(), 4);
EXPECT_EQ(seq2[0], 40u);
EXPECT_EQ(seq2[1], 50u);
EXPECT_EQ(seq2[2], 60u);
EXPECT_EQ(seq2[3], 70u);
}
TEST_F(CSimpleSequenceTypeTest, SwapFunctionDynamic)
{
sdv::sequence<uint32_t> seq1 = {10u, 20u, 30u};
sdv::sequence<uint32_t> seq2 = {40u, 50u, 60u, 70u};
seq1.swap(seq2);
EXPECT_EQ(seq1.size(), 4);
EXPECT_EQ(seq1[0], 40u);
EXPECT_EQ(seq1[1], 50u);
EXPECT_EQ(seq1[2], 60u);
EXPECT_EQ(seq1[3], 70u);
EXPECT_EQ(seq2.size(), 3);
EXPECT_EQ(seq2[0], 10u);
EXPECT_EQ(seq2[1], 20u);
EXPECT_EQ(seq2[2], 30u);
sdv::swap(seq1, seq2);
EXPECT_EQ(seq1.size(), 3);
EXPECT_EQ(seq1[0], 10u);
EXPECT_EQ(seq1[1], 20u);
EXPECT_EQ(seq1[2], 30u);
EXPECT_EQ(seq2.size(), 4);
EXPECT_EQ(seq2[0], 40u);
EXPECT_EQ(seq2[1], 50u);
EXPECT_EQ(seq2[2], 60u);
EXPECT_EQ(seq2[3], 70u);
}
TEST_F(CSimpleSequenceTypeTest, SwapFunctionMixed)
{
sdv::sequence<uint32_t, 5> seq1 = {10u, 20u, 30u};
sdv::sequence<uint32_t> seq2 = {40u, 50u, 60u, 70u};
seq1.swap(seq2);
EXPECT_EQ(seq1.size(), 4);
EXPECT_EQ(seq1[0], 40u);
EXPECT_EQ(seq1[1], 50u);
EXPECT_EQ(seq1[2], 60u);
EXPECT_EQ(seq1[3], 70u);
EXPECT_EQ(seq2.size(), 3);
EXPECT_EQ(seq2[0], 10u);
EXPECT_EQ(seq2[1], 20u);
EXPECT_EQ(seq2[2], 30u);
sdv::swap(seq1, seq2);
EXPECT_EQ(seq1.size(), 3);
EXPECT_EQ(seq1[0], 10u);
EXPECT_EQ(seq1[1], 20u);
EXPECT_EQ(seq1[2], 30u);
EXPECT_EQ(seq2.size(), 4);
EXPECT_EQ(seq2[0], 40u);
EXPECT_EQ(seq2[1], 50u);
EXPECT_EQ(seq2[2], 60u);
EXPECT_EQ(seq2[3], 70u);
}
TEST_F(CSimpleSequenceTypeTest, CompareOperator)
{
sdv::sequence<uint32_t> seq1 = {10u, 20u, 30u};
sdv::sequence<uint32_t> seq2;
EXPECT_FALSE(seq1 == seq2);
EXPECT_TRUE(seq1 != seq2);
EXPECT_FALSE(seq1 < seq2);
EXPECT_FALSE(seq1 <= seq2);
EXPECT_TRUE(seq1 > seq2);
EXPECT_TRUE(seq1 >= seq2);
seq2 = {10u, 20u, 30u};
EXPECT_TRUE(seq1 == seq2);
EXPECT_FALSE(seq1 != seq2);
EXPECT_FALSE(seq1 < seq2);
EXPECT_TRUE(seq1 <= seq2);
EXPECT_FALSE(seq1 > seq2);
EXPECT_TRUE(seq1 >= seq2);
seq2.push_back(40u);
EXPECT_FALSE(seq1 == seq2);
EXPECT_TRUE(seq1 != seq2);
EXPECT_TRUE(seq1 < seq2);
EXPECT_TRUE(seq1 <= seq2);
EXPECT_FALSE(seq1 > seq2);
EXPECT_FALSE(seq1 >= seq2);
seq1.clear();
seq2.clear();
EXPECT_TRUE(seq1 == seq2);
EXPECT_FALSE(seq1 != seq2);
EXPECT_FALSE(seq1 < seq2);
EXPECT_TRUE(seq1 <= seq2);
EXPECT_FALSE(seq1 > seq2);
EXPECT_TRUE(seq1 >= seq2);
}
TEST_F(CSimpleSequenceTypeTest, IteratorDistance)
{
sdv::sequence<uint32_t> seq1 = {10u, 20u, 30u};
EXPECT_EQ(std::distance(seq1.begin(), seq1.end()), seq1.length());
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More