mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-07-02 05:35:11 +00:00
77
tests/component_tests/repository/CMakeLists.txt
Normal file
77
tests/component_tests/repository/CMakeLists.txt
Normal 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)
|
||||
135
tests/component_tests/repository/isolation_test.cpp
Normal file
135
tests/component_tests/repository/isolation_test.cpp
Normal 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
|
||||
|
||||
|
||||
|
||||
*/
|
||||
646
tests/component_tests/repository/repository_test.cpp
Normal file
646
tests/component_tests/repository/repository_test.cpp
Normal 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();
|
||||
}
|
||||
|
||||
870
tests/component_tests/repository/test_component.cpp
Normal file
870
tests/component_tests/repository/test_component.cpp
Normal 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)
|
||||
35
tests/component_tests/repository/test_component.idl
Normal file
35
tests/component_tests/repository/test_component.idl
Normal 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;
|
||||
};
|
||||
1
tests/component_tests/repository/test_component_ps.cpp
Normal file
1
tests/component_tests/repository/test_component_ps.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "generated/ps/proxystub.cpp"
|
||||
Reference in New Issue
Block a user