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

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