Update sdv_packager (#6)

This commit is contained in:
tompzf
2026-03-27 14:12:49 +01:00
committed by GitHub
parent 234be8917f
commit aefefd52f7
717 changed files with 42252 additions and 11334 deletions

View File

@@ -0,0 +1,41 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project
project (ComponentTest_AppControl VERSION 1.0 LANGUAGES CXX)
# Data maneger executable
add_executable(ComponentTest_AppControl
"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"
)
target_link_libraries(ComponentTest_AppControl ${CMAKE_DL_LIBS} GTest::GTest)
# Add the Data Dispatch Service unittest
add_test(NAME ComponentTest_AppControl COMMAND ComponentTest_AppControl 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_AppControl POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_AppControl>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_AppControl.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_AppControl dependency_sdv_components)
add_dependencies(ComponentTest_AppControl ComponentTest_Repository) # Use the repository components for this test

View File

@@ -0,0 +1,46 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#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,529 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#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(AppControl, 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(AppControl, 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(AppControl, 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);
}
// Testing the external application requires a process running that was initialized as main with the same instance ID. This process
// needs to be started before and shutdown after the execution of this test.
TEST(AppControl, DISABLED_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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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);
}
// Testing the external application requires a process running that was initialized as main with the same instance ID. This process
// needs to be started before and shutdown after the execution of this test.
TEST(AppControl, DISABLED_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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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);
}
// Testing the external application requires a process running that was initialized as main with the same instance ID. This process
// needs to be started before and shutdown after the execution of this test.
TEST(AppControl, DISABLED_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(AppControl, 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(AppControl, 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(AppControl, 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(AppControl, 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,656 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#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,27 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#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

@@ -1,12 +1,69 @@
# Define project
project(ConfigTests VERSION 1.0 LANGUAGES CXX)
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define target
add_executable(ComponentTest_Config config_tests.cpp)
# Define project
project (ConfigTests 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_Config --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_Config
"main.cpp"
"config_tests.cpp"
)
target_link_libraries(ComponentTest_Config ${CMAKE_DL_LIBS} GTest::GTest)
# Add the test
# Add the Data Dispatch Service unittest
add_test(NAME ComponentTest_Config COMMAND ComponentTest_Config WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
@@ -17,3 +74,5 @@ add_custom_command(TARGET ComponentTest_Config POST_BUILD
# Build dependencies
add_dependencies(ComponentTest_Config dependency_sdv_components)
add_dependencies(ComponentTest_Config ComponentTest_Repository) # Use the repository components for this test

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#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

@@ -1,5 +1,18 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project
project (ModuleControlTests VERSION 1.0 LANGUAGES CXX)
project (ConfigInstallTests VERSION 1.0 LANGUAGES CXX)
# Get CRC++ from github
include(FetchContent)

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <support/sdv_core.h>
#include <interfaces/app.h>

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <support/component_impl.h>
class CModuleTestComponent1 : public sdv::CSdvObject
@@ -7,7 +20,7 @@ public:
BEGIN_SDV_INTERFACE_MAP()
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Utility)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::utility)
DECLARE_OBJECT_CLASS_NAME("ModuleTestComponent1")
private:
};
@@ -20,7 +33,7 @@ public:
BEGIN_SDV_INTERFACE_MAP()
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Utility)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::utility)
DECLARE_OBJECT_CLASS_NAME("ModuleTestComponent2")
private:
};

View File

@@ -1,3 +1,16 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project
project (DataDispatchServiceTests VERSION 1.0 LANGUAGES CXX)

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <iostream>
#include <mutex>

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <cstring>
#include "../../../global/process_watchdog.h"

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <iostream>
#include <mutex>

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <iostream>
#include <mutex>

View File

@@ -1,3 +1,16 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project
project (DbcUtilTests VERSION 1.0 LANGUAGES CXX)

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <iostream>
#include <ostream>
@@ -93,11 +106,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitBigEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -125,7 +138,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitBigEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalBE1.Reset();
signalBE2.Reset();
@@ -203,11 +216,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmit64BitBigEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -226,7 +239,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmit64BitBigEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalInt64BE.Reset();
signalUint64BE.Reset();
@@ -347,11 +360,11 @@ TEST(DbcUtilCanDLTest, ReceiveBigEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -384,7 +397,7 @@ TEST(DbcUtilCanDLTest, ReceiveBigEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalBE1.Reset();
signalBE2.Reset();
@@ -465,11 +478,11 @@ TEST(DbcUtilCanDLTest, Receive64BitBigEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -493,7 +506,7 @@ TEST(DbcUtilCanDLTest, Receive64BitBigEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalInt64BE.Reset();
signalUint64BE.Reset();
@@ -525,11 +538,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitLittleEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -557,7 +570,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitLittleEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalLE1.Reset();
signalLE2.Reset();
@@ -635,11 +648,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmit64BitLittleEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -658,7 +671,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmit64BitLittleEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalInt64LE.Reset();
signalUint64LE.Reset();
@@ -779,11 +792,11 @@ TEST(DbcUtilCanDLTest, ReceiveLittleEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -816,7 +829,7 @@ TEST(DbcUtilCanDLTest, ReceiveLittleEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalLE1.Reset();
signalLE2.Reset();
@@ -897,11 +910,11 @@ TEST(DbcUtilCanDLTest, Receive64BitLittleEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -925,7 +938,7 @@ TEST(DbcUtilCanDLTest, Receive64BitLittleEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalInt64LE.Reset();
signalUint64LE.Reset();
@@ -957,11 +970,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransactionalTransmitBigEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -992,7 +1005,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransactionalTransmitBigEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalBE1.Reset();
signalBE2.Reset();
@@ -1050,11 +1063,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransactionalTransmitLittleEndian)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -1085,7 +1098,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransactionalTransmitLittleEndian)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalLE1.Reset();
signalLE2.Reset();
@@ -1143,11 +1156,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitBigEndianAllDataTypes)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to integer based signals
sdv::core::CDispatchService dispatch;
@@ -1222,7 +1235,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitBigEndianAllDataTypes)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalIntBE1.Reset();
signalIntBE2.Reset();
@@ -1429,11 +1442,11 @@ TEST(DbcUtilCanDLTest, ReceiveBigEndianAllDataTypes)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -1568,7 +1581,7 @@ TEST(DbcUtilCanDLTest, ReceiveBigEndianAllDataTypes)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalIntBE1.Reset();
signalIntBE2.Reset();
@@ -1615,11 +1628,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitLittleEndianAllDataTypes)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to integer based signals
sdv::core::CDispatchService dispatch;
@@ -1694,7 +1707,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitLittleEndianAllDataTypes)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalIntLE1.Reset();
signalIntLE2.Reset();
@@ -1901,11 +1914,11 @@ TEST(DbcUtilCanDLTest, ReceiveLittleEndianAllDataTypes)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -2040,7 +2053,7 @@ TEST(DbcUtilCanDLTest, ReceiveLittleEndianAllDataTypes)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalIntLE1.Reset();
signalIntLE2.Reset();
@@ -2087,11 +2100,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitBigEndianScaledDataTypes)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to integer based signals
sdv::core::CDispatchService dispatch;
@@ -2127,7 +2140,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitBigEndianScaledDataTypes)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalUintBE1.Reset();
signalUintBE2.Reset();
@@ -2257,11 +2270,11 @@ TEST(DbcUtilCanDLTest, ReceiveBigEndianScaledDataType)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -2328,7 +2341,7 @@ TEST(DbcUtilCanDLTest, ReceiveBigEndianScaledDataType)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalUintBE1.Reset();
signalUintBE2.Reset();
@@ -2364,11 +2377,11 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitLittleEndianScaledDataTypes)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to integer based signals
sdv::core::CDispatchService dispatch;
@@ -2404,7 +2417,7 @@ TEST(DbcUtilCanDLTest, SpontaneousTransmitLittleEndianScaledDataTypes)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalUintLE1.Reset();
signalUintLE2.Reset();
@@ -2534,11 +2547,11 @@ TEST(DbcUtilCanDLTest, ReceiveLittleEndianScaledDataType)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -2605,7 +2618,7 @@ TEST(DbcUtilCanDLTest, ReceiveLittleEndianScaledDataType)
// Shutdown
appcontrol.SetConfigMode();
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalUintLE1.Reset();
signalUintLE2.Reset();
@@ -2641,11 +2654,11 @@ TEST(DbcUtilCanDLTest, CyclicTransmit)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -2665,14 +2678,14 @@ TEST(DbcUtilCanDLTest, CyclicTransmit)
});
appcontrol.SetRunningMode();
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock);
cv.wait_for(lock, std::chrono::milliseconds(1000));
timer.Reset();
lock.unlock();
appcontrol.SetConfigMode();
// Shutdown
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalCounter.Reset();
@@ -2790,11 +2803,11 @@ TEST(DbcUtilCanDLTest, CyclicIfActiveTransmit)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -2815,13 +2828,13 @@ TEST(DbcUtilCanDLTest, CyclicIfActiveTransmit)
});
appcontrol.SetRunningMode();
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock);
cv.wait_for(lock, std::chrono::milliseconds(1000));
appcontrol.SetConfigMode();
timer.Reset();
// Shutdown
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalCounter.Reset();
@@ -2957,11 +2970,11 @@ TEST(DbcUtilCanDLTest, CyclicAndSpontaneousTransmit)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -2981,13 +2994,13 @@ TEST(DbcUtilCanDLTest, CyclicAndSpontaneousTransmit)
});
appcontrol.SetRunningMode();
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock);
cv.wait_for(lock, std::chrono::milliseconds(1000));
appcontrol.SetConfigMode();
timer.Reset();
// Shutdown
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalCounter.Reset();
@@ -3098,11 +3111,11 @@ TEST(DbcUtilCanDLTest, SpontaneousDelayTransmit)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -3126,13 +3139,13 @@ TEST(DbcUtilCanDLTest, SpontaneousDelayTransmit)
});
appcontrol.SetRunningMode();
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock);
cv.wait_for(lock, std::chrono::milliseconds(1000));
appcontrol.SetConfigMode();
timer.Reset();
// Shutdown
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalCounter.Reset();
@@ -3236,11 +3249,11 @@ TEST(DbcUtilCanDLTest, CyclicAndSpontaneousDelayTransmit)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -3263,13 +3276,13 @@ TEST(DbcUtilCanDLTest, CyclicAndSpontaneousDelayTransmit)
});
appcontrol.SetRunningMode();
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock);
cv.wait_for(lock, std::chrono::milliseconds(5000));
appcontrol.SetConfigMode();
timer.Reset();
// Shutdown
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalCounter.Reset();
@@ -3380,11 +3393,11 @@ TEST(DbcUtilCanDLTest, CyclicIfActiveAndSpontaneousTransmit)
// Start the data link
CDbcStructDataLink dl;
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialization_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialization_pending);
dl.Initialize("");
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::initialized);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::initialized);
dl.SetOperationMode(sdv::EOperationMode::running);
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::running);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::running);
// Subscribe to several signals
sdv::core::CDispatchService dispatch;
@@ -3404,13 +3417,13 @@ TEST(DbcUtilCanDLTest, CyclicIfActiveAndSpontaneousTransmit)
});
appcontrol.SetRunningMode();
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock);
cv.wait_for(lock, std::chrono::milliseconds(1000));
appcontrol.SetConfigMode();
timer.Reset();
// Shutdown
dl.Shutdown();
EXPECT_EQ(dl.GetStatus(), sdv::EObjectStatus::destruction_pending);
EXPECT_EQ(dl.GetObjectState(), sdv::EObjectState::destruction_pending);
signalCounter.Reset();

View File

@@ -12,6 +12,7 @@ Class = "DataDispatchService"
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
[Component.Parameters]
Source="asc_reader_test.asc"
Target="asc_writer_test.asc"

View File

@@ -12,5 +12,6 @@ Class = "DataDispatchService"
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
[Component.Parameters]
Source="receiver_test.asc"

View File

@@ -12,4 +12,5 @@ Class = "DataDispatchService"
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
[Component.Parameters]
Target="transmitter_test.asc"

View File

@@ -1,3 +1,16 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
project(LoggerTests)
set(CMAKE_CXX_STANDARD 17)

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <iostream>

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include "logger_test_service.h"
CLoggerTestService::CLoggerTestService()

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#ifndef VAPI_DUMMY_TEST_SERVICE_H
#define VAPI_DUMMY_TEST_SERVICE_H
@@ -10,7 +23,7 @@ class CLoggerTestService
: public sdv::CSdvObject
{
public:
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::basic_service)
DECLARE_OBJECT_CLASS_NAME("LoggerTestService")
CLoggerTestService();

View File

@@ -1,3 +1,16 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project
project(RepositoryTests VERSION 1.0 LANGUAGES CXX)
@@ -10,7 +23,7 @@ message("Use IDL compiler: ${SDVIDL}")
# Compile the IDL
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/generated/test_component.h
OUTPUT ${PROJECT_SOURCE_DIR}/generated/test_component.h ${PROJECT_SOURCE_DIR}/generated/ps/proxystub.cpp ${PROJECT_SOURCE_DIR}/generated/serdes/test_component_serdes.h
DEPENDS sdv_idl_compiler
MAIN_DEPENDENCY test_component.idl
COMMENT "Build test_component.idl"
@@ -19,9 +32,10 @@ add_custom_command(
)
set_source_files_properties(test_component_ps.cpp OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/generated/test_component.h)
set_source_files_properties(test_component_ps.cpp OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/generated/ps/proxystub.cpp)
set_source_files_properties(test_component_ps.cpp OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/generated/serdes/test_component_serdes.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"
@@ -43,9 +57,7 @@ set_target_properties(ComponentTest_Repository_test_module PROPERTIES SUFFIX ".s
# 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
COMMAND "$<TARGET_FILE:sdv_packager>" DIRECT_INSTALL ComponentTest_Repository -T. --instance2005 "$<TARGET_FILE:ComponentTest_Repository_test_module>" "$<TARGET_FILE:ComponentTest_Repository_ps>" "-I$<TARGET_FILE_DIR:ComponentTest_Repository_test_module>" --overwrite --user_config+TestObject_ComplexHelloService+TestObject_HelloUtility --interface_config+Example_Object+Example_Object_2+TestObject_HelloDevice+TestObject_BasicHelloService+TestObject_SystemHelloService
DEPENDS ComponentTest_Repository_test_module ComponentTest_Repository_ps
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
@@ -53,7 +65,7 @@ add_custom_target(ComponentTest_Repository_install_manifest
# Define target
add_executable(ComponentTest_Repository
"repository_test.cpp"
"isolation_test.cpp"
"isolation_test.cpp"
)
target_link_libraries(ComponentTest_Repository ${CMAKE_DL_LIBS} GTest::GTest)

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <support/app_control.h>
#include <support/sdv_core.h>
@@ -39,9 +52,8 @@ ViewFilter = "Fatal"
Mode = "Main"
Instance = 2005
)code");
if (!bRet)
std::cout << "Failed to start the application for instance 1234." << std::endl;
std::cout << "Failed to start the application for instance 2005." << std::endl;
}
/**
@@ -53,9 +65,7 @@ Instance = 2005
}
};
// 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)
TEST_F(CIsolatedComponentTest, LoadNonIsolatedSystemService)
{
// Load the hello system service
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_SystemHelloService");
@@ -67,9 +77,7 @@ TEST_F(CIsolatedComponentTest, DISABLED_LoadNonIsolatedSystemService)
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)
TEST_F(CIsolatedComponentTest, LoadNonIsolatedDevice)
{
// Load the hello device
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_HelloDevice");
@@ -81,9 +89,7 @@ TEST_F(CIsolatedComponentTest, DISABLED_LoadNonIsolatedDevice)
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)
TEST_F(CIsolatedComponentTest, LoadNonIsolatedBasicService)
{
// Load the hello basic service
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_BasicHelloService");
@@ -95,9 +101,7 @@ TEST_F(CIsolatedComponentTest, DISABLED_LoadNonIsolatedBasicService)
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)
TEST_F(CIsolatedComponentTest, LoadIsolatedComplexService)
{
// Load the hello basic service
IHello* pHello = sdv::core::GetObject<IHello>("TestObject_ComplexHelloService");

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <interfaces/repository.h>
#include <support/local_service_access.h>
@@ -29,38 +42,43 @@ public:
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig) override
{
FAIL() << "Error: Initialize should not be called by Repo Service!";
// m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
// m_eObjectState = sdv::EObjectState::initialization_failure;
}
virtual sdv::EObjectStatus GetStatus() const
virtual sdv::EObjectState GetObjectState() const override
{
return m_eObjectStatus;
return m_eObjectState;
}
void SetOperationMode(sdv::EOperationMode eMode)
virtual void SetOperationMode(sdv::EOperationMode eMode) override
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
m_eObjectStatus = sdv::EObjectStatus::configuring;
m_eObjectState = sdv::EObjectState::configuring;
break;
case sdv::EOperationMode::running:
m_eObjectStatus = sdv::EObjectStatus::running;
m_eObjectState = sdv::EObjectState::running;
break;
default:
break;
}
}
virtual void Shutdown()
virtual sdv::u8string GetObjectConfig() const override
{
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
return {};
}
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
virtual void Shutdown() override
{
m_eObjectState = sdv::EObjectState::destruction_pending;
}
sdv::EObjectState m_eObjectState = sdv::EObjectState::initialization_pending;
};
TEST(RepositoryTest, LoadNonexistentModule)
@@ -366,7 +384,7 @@ Mode = "Essential"
ASSERT_TRUE(pModuleControl->Load((GetExecDirectory() / "ComponentTest_Repository_test_module.sdv").generic_u8string()));
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", nullptr, "ChainedObject");
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", nullptr, "chained_object = \"ChainedObject\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("TestObject_CreateChain"));
EXPECT_NE(nullptr, pObjectAccess->GetObject("ChainedObject"));
@@ -404,7 +422,8 @@ Mode = "Essential"
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);
bool bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Bar_" + count,
"chained_object = \"BarFoo_" + count + "\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("BarFoo_" + count));
}
@@ -413,7 +432,8 @@ Mode = "Essential"
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);
bool bRes =
pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count, "chained_object =\"FooBar_" + count + "\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("FooBar_" + count));
}
@@ -460,7 +480,8 @@ Mode = "Essential"
{
std::string count = std::to_string(i);
//locks using TestLockService during construction
bRes = pRepositoryControl->CreateObject("TestObject_CreateChainLock", "Bar_" + count, "BarFoo_" + count);
bRes = pRepositoryControl->CreateObject("TestObject_CreateChainLock", "Bar_" + count,
"chained_object = \"BarFoo_" + count + "\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("BarFoo_" + count));
}
@@ -470,7 +491,8 @@ Mode = "Essential"
{
std::string count = std::to_string(i);
pLock->Lock();
bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count, "FooBar_" + count);
bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count,
"chained_object = \"FooBar_" + count + "\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("FooBar_" + count));
pLock->Unlock();
@@ -518,7 +540,8 @@ Mode = "Essential"
{
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);
bRes = pRepositoryControl->CreateObject("TestObject_CreateChainLockThread", "Bar_" + count,
"chained_object = \"BarFoo_" + count + "\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("BarFoo_" + count));
}
@@ -528,7 +551,8 @@ Mode = "Essential"
{
std::string count = std::to_string(i);
pLock->Lock();
bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count, "FooBar_" + count);
bRes = pRepositoryControl->CreateObject("TestObject_CreateChain", "Foo_" + count,
"chained_object = \"FooBar_" + count + "\"");
EXPECT_TRUE(bRes);
EXPECT_NE(nullptr, pObjectAccess->GetObject("FooBar_" + count));
pLock->Unlock();
@@ -593,9 +617,7 @@ Mode = "Essential"
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)
TEST(RepositoryTest, MainApplication_GetInstalledAndLoadedComponent)
{
// Start the app control. The application automatically loads the installation manifests and the application configuration,
// starting automatically the objects.
@@ -618,9 +640,7 @@ Instance = 2005
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)
TEST(RepositoryTest, 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.

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <mutex>
#include <iostream>
@@ -27,7 +40,7 @@ public:
SDV_INTERFACE_ENTRY(ITestLock)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::device)
DECLARE_OBJECT_CLASS_NAME("TestLockService")
void Lock() override
@@ -49,88 +62,26 @@ DEFINE_SDV_OBJECT(CTestLockService)
/**
* @brief Example component testing IObjectControl
*/
class CTestObjectControl
: public sdv::CSdvObject
, public sdv::IObjectControl
class CTestObjectControl : public sdv::CSdvObject
{
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_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.
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
virtual bool OnInitialize() override
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
m_eObjectStatus = sdv::EObjectStatus::initialized;
return true;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
* @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown.
*/
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;
virtual void OnShutdown() override
{}
};
DEFINE_SDV_OBJECT(CTestObjectControl)
@@ -138,87 +89,26 @@ DEFINE_SDV_OBJECT(CTestObjectControl)
/**
* @brief Example component testing IObjectControl - 2nd component to test duplicate instantiation
*/
class CTestObjectControl2
: public sdv::CSdvObject
, public sdv::IObjectControl
class CTestObjectControl2 : public sdv::CSdvObject
{
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_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.
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
void SetOperationMode(sdv::EOperationMode eMode)
virtual bool OnInitialize() override
{
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;
}
return true;
}
/**
* @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;
* @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown.
*/
virtual void OnShutdown() override
{}
};
DEFINE_SDV_OBJECT(CTestObjectControl2)
@@ -226,70 +116,26 @@ DEFINE_SDV_OBJECT(CTestObjectControl2)
/**
* @brief Example component testing IObjectControl
*/
class CTestObjectControlFail
: public sdv::CSdvObject
, public sdv::IObjectControl
class CTestObjectControlFail : public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
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.
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
virtual bool OnInitialize() override
{
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return false;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
* @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown.
*/
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()
virtual void OnShutdown() override
{}
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending;
};
DEFINE_SDV_OBJECT(CTestObjectControlFail)
@@ -297,95 +143,45 @@ DEFINE_SDV_OBJECT(CTestObjectControlFail)
/**
* @brief Example component testing chained object creation in Initialize
*/
class CTestObjectCreate
: public sdv::CSdvObject
, public sdv::IObjectControl
class CTestObjectCreate : public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::device)
DECLARE_OBJECT_CLASS_NAME("TestObject_CreateChain")
BEGIN_SDV_PARAM_MAP()
SDV_PARAM_ENTRY(m_ssChainedObject, "chained_object", "", "", "Name of the chained object")
END_SDV_PARAM_MAP()
/**
* @brief Initialize method. On success, a subsequent call to GetStatus returns EObjectStatus::running
* @param[in] ssObjectConfig Optional configuration string.
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
virtual void Initialize( const sdv::u8string& ssObjectConfig)
virtual bool OnInitialize() override
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
//create new example object with name ssObjectConfig
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
if (!pRepo) return false;
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
if (!pCreate) return false;
ASSERT_FALSE(ssObjectConfig.empty());
if (m_ssChainedObject.empty())
return false;
ASSERT_TRUE(pCreate->CreateObject("Example_Object", ssObjectConfig,nullptr));
if (!pCreate->CreateObject("Example_Object", m_ssChainedObject, nullptr))
return false;
m_eObjectStatus = sdv::EObjectStatus::initialized;
return true;
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
* @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown.
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
virtual void OnShutdown() override
{}
/**
* @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;
std::string m_ssChainedObject; ///< Name of the chained object
};
DEFINE_SDV_OBJECT(CTestObjectCreate)
@@ -393,31 +189,26 @@ 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
class CTestObjectCreateLock: public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
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);
BEGIN_SDV_PARAM_MAP()
SDV_PARAM_ENTRY(m_ssChainedObject, "chained_object", "", "", "Name of the chained object")
END_SDV_PARAM_MAP()
/**
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
virtual bool OnInitialize() override
{
//create new example object with name ssObjectConfig while holding lock
auto pLock = sdv::core::GetObject<ITestLock>("TestLockService");
ASSERT_NE(pLock,nullptr);
if (!pLock) return false;
struct SAutoLock
{
@@ -427,67 +218,25 @@ public:
} sAutoLock(pLock);
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
if (!pRepo) return false;
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
if (!pCreate) return false;
ASSERT_FALSE(ssObjectConfig.empty());
if (m_ssChainedObject.empty()) return false;
ASSERT_TRUE(pCreate->CreateObject("Example_Object", ssObjectConfig, nullptr));
if (!pCreate->CreateObject("Example_Object", m_ssChainedObject, nullptr)) return false;
m_eObjectStatus = sdv::EObjectStatus::initialized;
return true;
}
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
* @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown.
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
virtual void OnShutdown() override
{}
/**
* @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;
std::string m_ssChainedObject; ///< Name of the chained object
};
DEFINE_SDV_OBJECT(CTestObjectCreateLock)
@@ -495,33 +244,33 @@ 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
class CTestObjectCreateLockThread : public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
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);
BEGIN_SDV_PARAM_MAP()
SDV_PARAM_ENTRY(m_ssChainedObject, "chained_object", "", "", "Name of the chained object")
END_SDV_PARAM_MAP()
auto fun = [ssObjectConfig]()
/**
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
virtual bool OnInitialize() override
{
bool bResult = true;
auto fun = [this, &bResult]()
{
//create new example object with name ssObjectConfig while holding lock
auto pLock = sdv::core::GetObject<ITestLock>("TestLockService");
ASSERT_NE(pLock, nullptr);
if (!pLock)
{
bResult = false;
return;
}
struct SAutoLock
{
@@ -531,72 +280,46 @@ public:
} sAutoLock(pLock);
auto pRepo = sdv::core::GetObject("RepositoryService");
ASSERT_TRUE(pRepo);
if (!pRepo)
{
bResult = false;
return;
}
auto pCreate = sdv::TInterfaceAccessPtr(pRepo).GetInterface<sdv::core::IRepositoryControl>();
ASSERT_TRUE(pCreate);
if (!pCreate)
{
bResult = false;
return;
}
ASSERT_FALSE(ssObjectConfig.empty());
if (m_ssChainedObject.empty())
{
bResult = false;
return;
}
ASSERT_TRUE(pCreate->CreateObject("Example_Object", ssObjectConfig, nullptr));
if (!pCreate->CreateObject("Example_Object", m_ssChainedObject, nullptr))
{
bResult = false;
return;
}
};
std::thread testThread(fun);
testThread.join();
m_eObjectStatus = sdv::EObjectStatus::initialized;
return bResult;
}
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
* @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown.
*/
virtual sdv::EObjectStatus GetStatus() const
{
return m_eObjectStatus;
}
virtual void OnShutdown() override
{}
/**
* @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;
std::string m_ssChainedObject; ///< Name of the chained object
};
DEFINE_SDV_OBJECT(CTestObjectCreateLockThread)
@@ -605,78 +328,30 @@ DEFINE_SDV_OBJECT(CTestObjectCreateLockThread)
/**
* @brief Example component testing IObjectControl
*/
class CTestObjectCreateDuringShutdown
: public sdv::CSdvObject
, public sdv::IObjectControl
class CTestObjectCreateDuringShutdown : public sdv::CSdvObject
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
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.
* @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize.
* @return Returns 'true' when the initialization was successful, 'false' when not.
*/
virtual void Initialize([[maybe_unused]] const sdv::u8string& ssObjectConfig)
virtual bool OnInitialize() override
{
EXPECT_EQ(m_eObjectStatus, sdv::EObjectStatus::initialization_pending);
m_eObjectStatus = sdv::EObjectStatus::initialized;
return true;
}
/**
* @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.
* @brief Shutdown method called before the object is destroyed. Overload of sdv::CSdvObject::OnShutdown.
* @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
* Any subsequent call to GetObjectState should return EObjectState::destruction_pending
*/
virtual void Shutdown()
virtual void OnShutdown() override
{
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
@@ -687,12 +362,7 @@ public:
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)
@@ -707,7 +377,7 @@ public:
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::device)
DECLARE_OBJECT_CLASS_NAME("TestObject_HelloDevice")
/**
@@ -740,7 +410,7 @@ public:
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::basic_service)
DECLARE_OBJECT_CLASS_NAME("TestObject_BasicHelloService")
/**
@@ -781,7 +451,7 @@ public:
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::ComplexService)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::complex_service)
DECLARE_OBJECT_CLASS_NAME("TestObject_ComplexHelloService")
/**
@@ -814,7 +484,7 @@ public:
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Utility)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::utility)
DECLARE_OBJECT_CLASS_NAME("TestObject_HelloUtility")
/**
@@ -847,7 +517,7 @@ public:
SDV_INTERFACE_ENTRY(IHello)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::SystemObject)
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::system_object)
DECLARE_OBJECT_CLASS_NAME("TestObject_SystemHelloService")
/**

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <interfaces/core.idl>
#include <interfaces/process.idl>

View File

@@ -1 +1,14 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include "generated/ps/proxystub.cpp"

View File

@@ -1,3 +1,16 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project (multiple EXEs)
project(TaskTimerTests VERSION 1.0 LANGUAGES CXX)

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include "gtest/gtest.h"
#include <support/timer.h>
#include <chrono>
@@ -66,13 +79,13 @@ TEST(TaskSimulationTimerTest, BasicCounterTestInterface)
CTestTask task;
sdv::core::CTaskTimer timer(3, &task);
sdv::core::CTaskTimer timer(3, &task, true);
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);
ASSERT_TRUE(pTimerSimulationStep);
uint32_t expected = 5;
uint32_t expectedAdditional = 11;
@@ -122,9 +135,9 @@ TEST(TaskSimulationTimerTest, LargerTaskPeriodTest)
CTestTask task1150;
CTestTask task3100;
sdv::core::CTaskTimer timer150(150, &task150);
sdv::core::CTaskTimer timer1150(1150, &task1150);
sdv::core::CTaskTimer timer3100(3100, &task3100);
sdv::core::CTaskTimer timer150(150, &task150, true);
sdv::core::CTaskTimer timer1150(1150, &task1150, true);
sdv::core::CTaskTimer timer3100(3100, &task3100, true);
EXPECT_TRUE(timer150);
EXPECT_TRUE(timer1150);
EXPECT_TRUE(timer3100);
@@ -132,7 +145,7 @@ TEST(TaskSimulationTimerTest, LargerTaskPeriodTest)
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
ASSERT_TRUE(pTimerSimulationStep);
uint32_t expected150 = 33;
uint32_t expected1150 = 4;
@@ -179,9 +192,9 @@ TEST(TaskSimulationTimerTest, MultipleTimerIdenticalTaskPeriodTest)
CTestTask task2;
CTestTask task3;
sdv::core::CTaskTimer timer1(3, &task1);
sdv::core::CTaskTimer timer2(3, &task2);
sdv::core::CTaskTimer timer3(3, &task3);
sdv::core::CTaskTimer timer1(3, &task1, true);
sdv::core::CTaskTimer timer2(3, &task2, true);
sdv::core::CTaskTimer timer3(3, &task3, true);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer2);
EXPECT_TRUE(timer3);
@@ -189,7 +202,7 @@ TEST(TaskSimulationTimerTest, MultipleTimerIdenticalTaskPeriodTest)
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
ASSERT_TRUE(pTimerSimulationStep);
uint32_t expected = 5;
uint32_t expectedAdditional = 11;
@@ -248,9 +261,9 @@ TEST(TaskSimulationTimerTest, MultipleTimerDifferentTaskPeriodTest)
CTestTask task3;
CTestTask task4;
sdv::core::CTaskTimer timer2(2, &task2);
sdv::core::CTaskTimer timer3(3, &task3);
sdv::core::CTaskTimer timer4(4, &task4);
sdv::core::CTaskTimer timer2(2, &task2, true);
sdv::core::CTaskTimer timer3(3, &task3, true);
sdv::core::CTaskTimer timer4(4, &task4, true);
EXPECT_TRUE(timer2);
EXPECT_TRUE(timer3);
EXPECT_TRUE(timer4);
@@ -258,7 +271,7 @@ TEST(TaskSimulationTimerTest, MultipleTimerDifferentTaskPeriodTest)
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
ASSERT_TRUE(pTimerSimulationStep);
uint32_t expected2 = 7;
uint32_t expected3 = 5;
@@ -322,9 +335,9 @@ TEST(TaskSimulationTimerTest, MultipleTimerLargeSimulationStepTest)
CTestTask task150;
CTestTask task450;
sdv::core::CTaskTimer timer1(1, &task1);
sdv::core::CTaskTimer timer150(150, &task150);
sdv::core::CTaskTimer timer450(450, &task450);
sdv::core::CTaskTimer timer1(1, &task1, true);
sdv::core::CTaskTimer timer150(150, &task150, true);
sdv::core::CTaskTimer timer450(450, &task450, true);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer150);
EXPECT_TRUE(timer450);
@@ -332,7 +345,7 @@ TEST(TaskSimulationTimerTest, MultipleTimerLargeSimulationStepTest)
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
ASSERT_TRUE(pTimerSimulationStep);
uint32_t expected1 = 480;
uint32_t expected150 = 3;
@@ -369,9 +382,9 @@ TEST(TaskSimulationTimerTest, MultipleTimerLargeAndDifferentSimulationStepTest)
CTestTask task150;
CTestTask task450;
sdv::core::CTaskTimer timer1(1, &task1);
sdv::core::CTaskTimer timer150(150, &task150);
sdv::core::CTaskTimer timer450(450, &task450);
sdv::core::CTaskTimer timer1(1, &task1, true);
sdv::core::CTaskTimer timer150(150, &task150, true);
sdv::core::CTaskTimer timer450(450, &task450, true);
EXPECT_TRUE(timer1);
EXPECT_TRUE(timer150);
EXPECT_TRUE(timer450);
@@ -379,7 +392,7 @@ TEST(TaskSimulationTimerTest, MultipleTimerLargeAndDifferentSimulationStepTest)
// Get the simulation task timer service.
sdv::core::ITimerSimulationStep* pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
EXPECT_TRUE(pTimerSimulationStep);
ASSERT_TRUE(pTimerSimulationStep);
uint32_t expected1 = 480;
uint32_t expected150 = 3;

View File

@@ -1,3 +1,16 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include "gtest/gtest.h"
#include <support/timer.h>
#include <chrono>

View File

@@ -0,0 +1,32 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Erik Verhoeven - initial API and implementation
#*******************************************************************************
# Define project
project(ConfigTests VERSION 1.0 LANGUAGES CXX)
# Define target
add_executable(ComponentTest_TOMLParser toml_parser_tests.cpp)
target_link_libraries(ComponentTest_TOMLParser ${CMAKE_DL_LIBS} GTest::GTest)
# Add the test
add_test(NAME ComponentTest_TOMLParser COMMAND ComponentTest_TOMLParser WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# Execute the test
add_custom_command(TARGET ComponentTest_TOMLParser POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:ComponentTest_TOMLParser>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ComponentTest_TOMLParser.xml
VERBATIM
)
# Build dependencies
add_dependencies(ComponentTest_TOMLParser dependency_sdv_components)

View File

@@ -0,0 +1,980 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include <gtest/gtest.h>
#include <support/toml.h>
#include <support/sdv_core.h>
#include <support/app_control.h>
#include "../../../global/process_watchdog.h"
// TODO: parser functions for updating/writing nodes and combining/subtracting
#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(TOMLParser, 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(), "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_EQ(table1.GetName(), "newTableArray");
auto table2 = config.GetDirect("newTableArray[1]");
EXPECT_EQ(table2.GetType(), sdv::toml::ENodeType::node_table);
EXPECT_EQ(table2.GetName(), "newTableArray");
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(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

@@ -1,3 +1,13 @@
#*******************************************************************************
# Copyright (c) 2025-2026 ZF Friedrichshafen AG
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#*******************************************************************************
# Define project
project (VSSUtilTests VERSION 1.0 LANGUAGES CXX)

View File

@@ -1,3 +1,13 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
#include <gtest/gtest.h>
#include <fstream>
#include <sstream>