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

@@ -1,3 +1,17 @@
#*******************************************************************************
# 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:
# Martin Stimpfl - initial API and implementation
# Erik Verhoeven - writing TOML and whitespace preservation
#*******************************************************************************
# Character Reader executable
add_executable(UnitTest_TOMLParser
"character_reader_tests.cpp"
@@ -5,9 +19,13 @@ add_executable(UnitTest_TOMLParser
"parser_tests.cpp"
"main.cpp"
"generate_toml_tests.cpp"
"content_modifications.cpp"
"generate_toml_delete_node.cpp"
"statement_boundary_detection.cpp"
"miscellaneous_tests.cpp")
"miscellaneous_tests.cpp"
"generate_toml_with_transfer.cpp"
"generate_toml_switch_inline.cpp"
"generate_toml_getset_comment.cpp"
"generate_toml_insert_node.cpp" "generate_toml_miscellaneous.cpp" "generate_toml_combine_reduce.cpp")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(UnitTest_TOMLParser GTest::GTest ${CMAKE_THREAD_LIBS_INIT})
if (WIN32)
@@ -29,7 +47,7 @@ add_custom_command(TARGET UnitTest_TOMLParser POST_BUILD
)
# Build dependencies
add_dependencies(UnitTest_TOMLParser core_services)
add_dependencies(UnitTest_TOMLParser dependency_sdv_components)

View File

@@ -1,3 +1,17 @@
/********************************************************************************
* 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:
* Martin Stimpfl - initial API and implementation
* Erik Verhoeven - writing TOML and whitespace preservation
********************************************************************************/
#include <gtest/gtest.h>
#include "../../../sdv_services/core/toml_parser/character_reader_utf_8.h"
#include "../../../sdv_services/core/toml_parser/exception.h"

View File

@@ -0,0 +1,515 @@
/********************************************************************************
* 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 "../../../sdv_services/core/toml_parser/parser_node_toml.h"
#include "../../../sdv_services/core/toml_parser/parser_toml.h"
TEST(GenerateTOML, CombineRoot)
{
toml_parser::CParser parser1(R"toml(
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml(
val3 = 30.0
val1 = 10)toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineRootComments)
{
toml_parser::CParser parser1(R"toml(
val1 = 10 # This is value 1
val2 = "20" # This is value 2)toml");
toml_parser::CParser parser2(R"toml(
val3 = 30.0 # This is value 3
val1 = 10 # This is again value 1)toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(
val1 = 10 # This is value 1
val2 = "20" # This is value 2
val3 = 30.0 # This is value 3)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineRootwithTable)
{
toml_parser::CParser parser1(R"toml(
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml([MyTable]
val3 = 30.0
val1 = 10)toml");
auto ptrTable = parser2.Root().Direct("MyTable");
ASSERT_TRUE(ptrTable);
EXPECT_TRUE(parser1.Root().Combine(ptrTable->Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineTablewithRoot)
{
toml_parser::CParser parser1(R"toml([MyTable]
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml(
val3 = 30.0
val1 = 10)toml");
auto ptrNode = parser1.Root().Direct("MyTable");
ASSERT_TRUE(ptrNode);
auto ptrTable = ptrNode->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable);
EXPECT_TRUE(ptrTable->Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code([MyTable]
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineTablewithDifferentTable)
{
toml_parser::CParser parser1(R"toml([MyTable1]
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml([MyTable2]
val3 = 30.0
val1 = 10)toml");
auto ptrNode1 = parser1.Root().Direct("MyTable1");
ASSERT_TRUE(ptrNode1);
auto ptrTable1 = ptrNode1->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable1);
auto ptrNode2 = parser2.Root().Direct("MyTable2");
ASSERT_TRUE(ptrNode2);
auto ptrTable2 = ptrNode2->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable2);
EXPECT_TRUE(ptrTable1->Combine(ptrTable2));
std::string ssCombinedTOML = R"code([MyTable1]
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineTablewithIdenticalTable)
{
toml_parser::CParser parser1(R"toml([MyTable]
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml([MyTable]
val3 = 30.0
val1 = 10)toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code([MyTable]
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineInlineTablewithDifferentStandardTable)
{
toml_parser::CParser parser1(R"toml(MyTable1 = {val1 = 10, val2 = "20"})toml");
toml_parser::CParser parser2(R"toml([MyTable2]
val3 = 30.0
val1 = 10)toml");
auto ptrNode1 = parser1.Root().Direct("MyTable1");
ASSERT_TRUE(ptrNode1);
auto ptrTable1 = ptrNode1->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable1);
auto ptrNode2 = parser2.Root().Direct("MyTable2");
ASSERT_TRUE(ptrNode2);
auto ptrTable2 = ptrNode2->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable2);
EXPECT_TRUE(ptrTable1->Combine(ptrTable2));
std::string ssCombinedTOML = R"code(MyTable1 = {val1 = 10, val2 = "20", val3 = 30.0})code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineInlineTablewithIdenticalStandardTable)
{
toml_parser::CParser parser1(R"toml(MyTable = {val1 = 10, val2 = "20"})toml");
toml_parser::CParser parser2(R"toml([MyTable]
val3 = 30.0
val1 = 10)toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(MyTable = {val1 = 10, val2 = "20", val3 = 30.0})code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineStandardTablewithDifferentInlineTable)
{
toml_parser::CParser parser1(R"toml([MyTable1]
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml(MyTable2 = {val3 = 30.0, val1 = 10})toml");
auto ptrNode1 = parser1.Root().Direct("MyTable1");
ASSERT_TRUE(ptrNode1);
auto ptrTable1 = ptrNode1->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable1);
auto ptrNode2 = parser2.Root().Direct("MyTable2");
ASSERT_TRUE(ptrNode2);
auto ptrTable2 = ptrNode2->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable2);
EXPECT_TRUE(ptrTable1->Combine(ptrTable2));
std::string ssCombinedTOML = R"code([MyTable1]
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineStandardTablewithIdenticalInlineTable)
{
toml_parser::CParser parser1(R"toml([MyTable]
val1 = 10
val2 = "20")toml");
toml_parser::CParser parser2(R"toml(MyTable = {val3 = 30.0, val1 = 10})toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code([MyTable]
val1 = 10
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineInlineTablewithDifferentInlineTable)
{
toml_parser::CParser parser1(R"toml(MyTable1 = {val1 = 10, val2 = "20"})toml");
toml_parser::CParser parser2(R"toml(MyTable2 = {val3 = 30.0, val1 = 10})toml");
auto ptrNode1 = parser1.Root().Direct("MyTable1");
ASSERT_TRUE(ptrNode1);
auto ptrTable1 = ptrNode1->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable1);
auto ptrNode2 = parser2.Root().Direct("MyTable2");
ASSERT_TRUE(ptrNode2);
auto ptrTable2 = ptrNode2->Cast<toml_parser::CNodeCollection>();
ASSERT_TRUE(ptrTable2);
EXPECT_TRUE(ptrTable1->Combine(ptrTable2));
std::string ssCombinedTOML = R"code(MyTable1 = {val1 = 10, val2 = "20", val3 = 30.0})code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineInlineTablewithIdenticalInlineTable)
{
toml_parser::CParser parser1(R"toml(MyTable = {val1 = 10, val2 = "20"})toml");
toml_parser::CParser parser2(R"toml(MyTable = {val3 = 30.0, val1 = 10})toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(MyTable = {val1 = 10, val2 = "20", val3 = 30.0})code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineDifferentArrays)
{
toml_parser::CParser parser1(R"toml(
val1 = [10, 20]
val2 = ["30", "40"])toml");
toml_parser::CParser parser2(R"toml(
val3 = [50.0, 60.0]
val1 = [70, 80])toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(
val1 = [70, 80]
val2 = ["30", "40"]
val3 = [50.0, 60.0])code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, CombineDifferentTableArrays)
{
toml_parser::CParser parser1(R"toml([[table_array1]]
val1 = [10, 20]
[[table_array1]]
val2 = ["30", "40"])toml");
toml_parser::CParser parser2(R"toml(
[[table_array2]]
val3 = [50.0, 60.0]
[[table_array2]]
val1 = [70, 80])toml");
EXPECT_TRUE(parser1.Root().Combine(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code([[table_array1]]
val1 = [10, 20]
[[table_array1]]
val2 = ["30", "40"]
[[table_array2]]
val3 = [50.0, 60.0]
[[table_array2]]
val1 = [70, 80])code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceRoot)
{
toml_parser::CParser parser1(R"toml(
val1 = 10
val2 = "20"
val3 = 30.0)toml");
toml_parser::CParser parser2(R"toml(
val3 = 35.0
val1 = 10)toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceRootComments)
{
toml_parser::CParser parser1(R"toml(
val1 = 10 # This is value 1
val2 = "20" # This is value 2
val3 = 30.0 # This is value 3)toml");
toml_parser::CParser parser2(R"toml(
val3 = 35.0 # This also is value 3
val1 = 10 # This also is value 1)toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(
val2 = "20" # This is value 2
val3 = 30.0 # This is value 3)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceTable)
{
toml_parser::CParser parser1(R"toml([my_table]
val1 = 10
val2 = "20"
val3 = 30.0)toml");
toml_parser::CParser parser2(R"toml([my_table]
val3 = 35.0
val1 = 10)toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code([my_table]
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceStandardTableWithInlineTable)
{
toml_parser::CParser parser1(R"toml([my_table]
val1 = 10
val2 = "20"
val3 = 30.0)toml");
toml_parser::CParser parser2(R"toml(my_table = {val3 = 35.0, val1 = 10})toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code([my_table]
val2 = "20"
val3 = 30.0)code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceInlineTableWithStandardTable)
{
toml_parser::CParser parser1(R"toml(my_table = {val1 = 10, val2 = "20", val3 = 30.0})toml");
toml_parser::CParser parser2(R"toml([my_table]
val3 = 35.0
val1 = 10)toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(my_table = { val2 = "20", val3 = 30.0})code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceInlineTable)
{
toml_parser::CParser parser1(R"toml(my_table = {val1 = 10, val2 = "20", val3 = 30.0})toml");
toml_parser::CParser parser2(R"toml(my_table = {val3 = 35.0, val1 = 10})toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"code(my_table = { val2 = "20", val3 = 30.0})code";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceDifferentArrays)
{
toml_parser::CParser parser1(R"code(
val1 = [10, 20]
val2 = ["30", "40"]
val3 = [50.0, 60.0])code");
toml_parser::CParser parser2(R"toml(
val3 = [50.0, 60.0]
val1 = [70, 80])toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"toml(
val1 = [10, 20]
val2 = ["30", "40"]
)toml";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}
TEST(GenerateTOML, ReduceDifferentTableArrays)
{
toml_parser::CParser parser1(R"code([[table_array1]]
val1 = [10, 20]
[[table_array1]]
val2 = ["30", "40"]
[[table_array2]]
val3 = [50.0, 60.0]
[[table_array2]]
val1 = [70, 80])code");
toml_parser::CParser parser2(R"toml(
[[table_array1]]
val2 = ["30", "40"]
[[table_array2]]
val3 = [50.0, 60.0]
[[table_array2]]
val1 = [70]
)toml");
EXPECT_TRUE(parser1.Root().Reduce(parser2.Root().Cast<toml_parser::CNodeCollection>()));
std::string ssCombinedTOML = R"toml([[table_array1]]
val1 = [10, 20]
[[table_array2]]
val1 = [70, 80])toml";
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser1.GenerateTOML());
EXPECT_EQ(ssGenerated, ssCombinedTOML);
}

View File

@@ -0,0 +1,648 @@
/********************************************************************************
* 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 "../../../sdv_services/core/toml_parser/parser_node_toml.h"
#include "../../../sdv_services/core/toml_parser/parser_toml.h"
// Delete nodes (for all types of nodes, between all types of nodes)
// - beginning
// - middle
// - end
// - Using deleted node info -- error
// - Last node (empty after that)
// - Smart delete (comments/whitespace around)
// Insert nodes (for all types of nodes, between all types of nodes)
// Before and after:
// - beginning
// - middle
// - end
// - Being the first item in a TOML file
// - Inserted and straight away deleted
// - Inserted with false/deleted reference --error
// - Inserted values before (okay) and behind (error) tables
// - Inserted duplicate value -- error
// - Smart insert (comments/whitespace around)
// Shift nodes (for all types of nodes, between root, tables and arrays)
/*
* @brief Delete a key from the TOML string.
* @param[in] rssTOMLInput Reference to the TOML string.
* @param[in] rssKey Reference to the key to delete.
* @param[in] rssOuput Reference to the expected ouput.
* @return Returns 'true' on success.
*/
bool TestDelete(const std::string& rssTOMLInput, const std::string& rssKey, const std::string& rssOutput)
{
toml_parser::CParser parser;
bool bRes = true;
EXPECT_NO_THROW(bRes = parser.Process(rssTOMLInput));
EXPECT_TRUE(bRes);
if (!bRes) return bRes;
auto ptrNode = parser.Root().Direct(rssKey);
EXPECT_TRUE(ptrNode);
if (!ptrNode) return false;
EXPECT_TRUE(bRes = ptrNode->DeleteNode());
if (!bRes) return bRes;
std::string ssTOML = parser.GenerateTOML();
EXPECT_EQ(ssTOML, rssOutput);
if (ssTOML != rssOutput) return false;
return true;
};
TEST(TOMLDeleteNode, DeleteValues)
{
// Delete a key from the begin (whitespace reduced)
EXPECT_TRUE(TestDelete(R"toml(key = 10 # value key
bare_key = "value" # value bare_key
bare-key = false # value bare-key)toml",
"key",
R"toml(bare_key = "value" # value bare_key
bare-key = false # value bare-key)toml"));
// Delete a key from the begin
EXPECT_TRUE(TestDelete(R"toml(
key = 10 # value key
bare_key = "value" # value bare_key
bare-key = false # value bare-key
)toml",
"key",
R"toml(
bare_key = "value" # value bare_key
bare-key = false # value bare-key
)toml"));
// Delete a key from the middle
EXPECT_TRUE(TestDelete(R"toml(
key = 10 # value key
bare_key = "value" # value bare_key
bare-key = false # value bare-key
)toml",
"bare_key",
R"toml(
key = 10 # value key
bare-key = false # value bare-key
)toml"));
// Delete a key from the end
EXPECT_TRUE(TestDelete(R"toml(
key = 10 # value key
bare_key = "value" # value bare_key
bare-key = false # value bare-key
)toml",
"bare-key",
R"toml(
key = 10 # value key
bare_key = "value" # value bare_key
)toml"));
}
TEST(TOMLDeleteNode, DeleteInlineTableValues)
{
// Delete key from the inline table
EXPECT_TRUE(TestDelete(R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml",
"1234.y",
R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, z = 2, str = "abc"}
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml",
"1234.x",
R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = { y = 1, z = 2, str = "abc"}
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml",
"1234.str",
R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2}
)toml"));
}
TEST(TOMLDeleteNode, DeleteInlineSubTableValues)
{
// Delete key from the inline sub-table
EXPECT_TRUE(TestDelete(R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, b=2, c=3}}
)toml",
"1234.tbl.b",
R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, c=3}}
)toml"));
}
TEST(TOMLDeleteNode, DeleteInlineTables)
{
// Delete table
EXPECT_TRUE(TestDelete(R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, b=2, c=3}}
)toml",
"1234.tbl",
R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, b=2, c=3}}
)toml",
"1234",
R"toml(
key = 10
bare_key = "value"
bare-key = false
)toml"));
}
TEST(TOMLDeleteNode, DeleteTableValues)
{
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
)toml",
"my_table.key",
R"toml(
[my_table]
bare_key = "value"
bare-key = false
)toml"));
// Delete a key from the middle
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
)toml",
"my_table.bare_key",
R"toml(
[my_table]
key = 10
bare-key = false
)toml"));
// Delete a key from the end
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
)toml",
"my_table.bare-key",
R"toml(
[my_table]
key = 10
bare_key = "value"
)toml"));
}
TEST(TOMLDeleteNode, DeleteInlineTableValueInTable)
{
// Delete key from the inline table in a table
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml",
"my_table.1234.y",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, z = 2, str = "abc"}
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml",
"my_table.1234.x",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = { y = 1, z = 2, str = "abc"}
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml",
"my_table.1234.str",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2}
)toml"));
}
TEST(TOMLDeleteNode, DeleteInlineSubTableValueInTable)
{
// Delete key from the inline sub-table
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, b=2, c=3}}
)toml",
"my_table.1234.tbl.b",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, c=3}}
)toml"));
}
TEST(TOMLDeleteNode, DeleteInlineTableInTable)
{
// Delete table
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, b=2, c=3}}
)toml",
"my_table.1234.tbl",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc"}
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
1234 = {x = 0, y = 1, z = 2, str = "abc", tbl={a =1, b=2, c=3}}
)toml",
"my_table.1234",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
)toml"));
}
TEST(TOMLDeleteNode, DeleteValuesInChildTable)
{
// Delete key from the child-table
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
str = "abc"
)toml",
"my_table.1234.y",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
z = 2
str = "abc"
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
str = "abc"
)toml",
"my_table.1234.x",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
y = 1
z = 2
str = "abc"
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
str = "abc"
)toml",
"my_table.1234.str",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
)toml"));
}
TEST(TOMLDeleteNode, DeleteChildTableInTable)
{
// Delete table
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
str = "abc"
[my_table.1234.tbl]
a =1
b=2
c=3
)toml",
"my_table.1234.tbl",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
str = "abc"
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
[my_table.1234]
x = 0
y = 1
z = 2
str = "abc"
[my_table.1234.tbl]
a =1
b=2
c=3
)toml",
"my_table.1234",
R"toml(
[my_table]
key = 10
bare_key = "value"
bare-key = false
)toml"));
}
TEST(TOMLDeleteNode, DeleteArrayValues)
{
// Delete array values
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"key[0]",
R"toml(
key = [ 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"key[1]",
R"toml(
key = [10, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"key[2]",
R"toml(
key = [10, 20]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml"));
}
TEST(TOMLDeleteNode, DeleteArrayValuesWithSucceedingComma)
{
// Delete array values with succeeding comma
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare_key[0]",
R"toml(
key = [10, 20, 30]
bare_key = [ "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare_key[1]",
R"toml(
key = [10, 20, 30]
bare_key = ["value1", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare_key[2]",
R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml"));
}
TEST(TOMLDeleteNode, DeleteValuesWithComments)
{
// Delete array values with comments
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare-key[0]",
R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [ 2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare-key[0].a",
R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{ b = true}, # value 0
2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare-key[0].b",
R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false}, # value 0
2020, # value 1
]
)toml"));
EXPECT_TRUE(TestDelete(R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
2020, # value 1
]
)toml",
"bare-key[1]",
R"toml(
key = [10, 20, 30]
bare_key = ["value1", "value2", 3030, ]
bare-key = [{a = false, b = true}, # value 0
]
)toml"));
}

View File

@@ -0,0 +1,328 @@
/********************************************************************************
* 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 "../../../sdv_services/core/toml_parser/parser_node_toml.h"
#include "../../../sdv_services/core/toml_parser/parser_toml.h"
TEST(GenerateTOML, GetCommentRoot)
{
toml_parser::CParser parser;
std::string ssTOML = R"code(# This is a comment)code";
EXPECT_NO_THROW(parser.Process(ssTOML));
std::string ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_TRUE(ssComment.empty());
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_TRUE(ssComment.empty());
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_TRUE(ssComment.empty());
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, "This is a comment");
}
TEST(GenerateTOML, GetMultiLineCommentRoot)
{
toml_parser::CParser parser;
std::string ssTOML = R"code(
# This is a comment that stretches
# more than one line.
# And here's another comment of more
# than one line.
)code";
EXPECT_NO_THROW(parser.Process(ssTOML));
std::string ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_TRUE(ssComment.empty());
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_TRUE(ssComment.empty());
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_TRUE(ssComment.empty());
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, R"code(This is a comment that stretches more than one line.
And here's another comment of more than one line.)code");
}
TEST(GenerateTOML, SetCommentRoot)
{
toml_parser::CParser parser;
// This will test the SetComment function and overwriting the existing comment.
std::string ssTOMLInput = R"code(# This is a double line comment
# This is line two of the double line comment)code";
std::string ssTOMLOutput = R"code(# This is comment way before
# This is comment before
# This is comment way behind
)code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_before , "This is comment before");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_behind , "This is comment behind");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before , "This is comment way before");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind , "This is comment way behind");
std::string ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_EQ(ssComment, "This is comment before");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_EQ(ssComment, "This is comment behind");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_EQ(ssComment, "This is comment way before");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, "This is comment way behind");
std::string ssGenerated = parser.Root().GenerateTOML();
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}
TEST(GenerateTOML, SetMultiLineCommentRoot)
{
toml_parser::CParser parser;
std::string ssTOMLInput = R"code(# This is a double line comment
# This is line two of the double line comment)code";
std::string ssTOMLOutput = R"code(# This is comment way before
# And surprise, also a second line
# This is comment before
#
# With a second line
# This is comment way behind
# And final, also a second line
)code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_before, R"(This is comment before
With a second line)");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_behind, R"(This is comment behind
Also with a second line)");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before, R"(This is comment way before
And surprise, also a second line)");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind, R"(This is comment way behind
And final, also a second line)");
std::string ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_EQ(ssComment, R"(This is comment before
With a second line)");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_EQ(ssComment, R"(This is comment behind
Also with a second line)");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_EQ(ssComment, R"(This is comment way before
And surprise, also a second line)");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, R"(This is comment way behind
And final, also a second line)");
std::string ssGenerated = parser.Root().GenerateTOML();
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}
TEST(GenerateTOML, RemoveCommentRoot)
{
toml_parser::CParser parser;
std::string ssTOMLInput = R"code(# This is a double line comment
# This is line two of the double line comment)code";
std::string ssTOMLOutput = R"code()code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind, std::string());
std::string ssGenerated = parser.Root().GenerateTOML();
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}
TEST(GenerateTOML, GetCommentRootValue)
{
toml_parser::CParser parser;
std::string ssTOML = R"code(# This is a separate comment
# This is a comment before the value
value = "this is the value text" # Comment following the value
# This is also a separate comment)code";
EXPECT_NO_THROW(parser.Process(ssTOML));
sdv::TInterfaceAccessPtr ptrValue = parser.Root().GetNodeDirect("value");
ASSERT_TRUE(ptrValue);
sdv::toml::INodeInfo* pComment = ptrValue.GetInterface<sdv::toml::INodeInfo>();
ASSERT_NE(pComment, nullptr);
std::string ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_EQ(ssComment, "This is a comment before the value");
ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_EQ(ssComment, "Comment following the value");
ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_EQ(ssComment, "This is a separate comment");
ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, "This is also a separate comment");
}
TEST(GenerateTOML, GetMultiLineCommentRootValue)
{
toml_parser::CParser parser;
std::string ssTOML = R"code(
# This is a separate comment with several line-breaks before.
# Followed by this text on the same line.
# Note: there was a space after the empty comment line.
# And another separate comment on a next line.
# This is a comment before the value.
# And another comment before the value at the same line.
#
# Note: there was a space after the empty comment line.
# But that should not influence the comment lines.
value = "this is the value text" # Comment following the value.
# More comment following the value.
# This becomes one line.
#
# But this is a separate line.
# This is also a separate comment.
# Followed by this text on the same line.
# And another text on a separate line.)code";
EXPECT_NO_THROW(parser.Process(ssTOML));
sdv::TInterfaceAccessPtr ptrValue = parser.Root().GetNodeDirect("value");
ASSERT_TRUE(ptrValue);
sdv::toml::INodeInfo* pComment = ptrValue.GetInterface<sdv::toml::INodeInfo>();
ASSERT_NE(pComment, nullptr);
std::string ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_EQ(ssComment, R"code(This is a comment before the value. And another comment before the value at the same line.
Note: there was a space after the empty comment line. But that should not influence the comment lines.)code");
ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_EQ(ssComment, R"code(Comment following the value. More comment following the value. This becomes one line.
But this is a separate line.)code");
ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_EQ(ssComment, R"code(This is a separate comment with several line-breaks before. Followed by this text on the same line.
Note: there was a space after the empty comment line. And another separate comment on a next line.)code");
ssComment = pComment->GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, R"code(This is also a separate comment. Followed by this text on the same line.
And another text on a separate line.)code");
}
TEST(GenerateTOML, SetCommentRootValue)
{
toml_parser::CParser parser;
// This will test the SetComment function and overwriting the existing comment.
std::string ssTOMLInput = R"code(# This is a double line comment
# This is line two of the double line comment)code";
std::string ssTOMLOutput = R"code(# This is comment #3
# This is comment #1
# This is comment #4
)code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_before , "This is comment #1");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_behind , "This is comment #2");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before , "This is comment #3");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind , "This is comment #4");
std::string ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_EQ(ssComment, "This is comment #1");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_EQ(ssComment, "This is comment #2");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_EQ(ssComment, "This is comment #3");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, "This is comment #4");
std::string ssGenerated = parser.Root().GenerateTOML();
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}
TEST(GenerateTOML, SetMultiLineCommentRootValue)
{
toml_parser::CParser parser;
std::string ssTOMLInput = R"code(# This is a double line comment
# This is line two of the double line comment)code";
std::string ssTOMLOutput = R"code(# This is comment #3
# And surprise, also a second line
# This is comment #1
#
# With a second line
# This is comment #4
# And final, also a second line
)code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_before, R"(This is comment #1
With a second line)");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::comment_behind, R"(This is comment #2
Also with a second line)");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before, R"(This is comment #3
And surprise, also a second line)");
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind, R"(This is comment #4
And final, also a second line)");
std::string ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_before);
EXPECT_EQ(ssComment, R"(This is comment #1
With a second line)");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::comment_behind);
EXPECT_EQ(ssComment, R"(This is comment #2
Also with a second line)");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_before);
EXPECT_EQ(ssComment, R"(This is comment #3
And surprise, also a second line)");
ssComment = parser.Root().GetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind);
EXPECT_EQ(ssComment, R"(This is comment #4
And final, also a second line)");
std::string ssGenerated = parser.Root().GenerateTOML();
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}
TEST(GenerateTOML, RemoveCommentRootValue)
{
toml_parser::CParser parser;
std::string ssTOMLInput = R"code(# This is a double line comment
# This is line two of the double line comment)code";
std::string ssTOMLOutput = R"code()code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
parser.Root().SetComment(sdv::toml::INodeInfo::ECommentType::out_of_scope_comment_behind, std::string());
std::string ssGenerated = parser.Root().GenerateTOML();
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
/********************************************************************************
* 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 "../../../sdv_services/core/toml_parser/parser_node_toml.h"
#include "../../../sdv_services/core/toml_parser/parser_toml.h"
// Test TODO:
// Shift nodes up and down within one container
// Remove formatting from node

View File

@@ -0,0 +1,50 @@
/********************************************************************************
* 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 "../../../sdv_services/core/toml_parser/parser_node_toml.h"
#include "../../../sdv_services/core/toml_parser/parser_toml.h"
// Test TODO:
// Switch to inline and vice versa
TEST(GenerateTOML, SwitchTableToInline)
{
toml_parser::CParser parser;
std::string ssTOMLInput = R"code([table]
key1 = "some string"
key2 = 123)code";
std::string ssTOMLOutput = R"code(table = {key1 = "some string", key2 = 123})code";
EXPECT_NO_THROW(parser.Process(ssTOMLInput));
std::string ssGenerated;
EXPECT_NO_THROW(ssGenerated = parser.GenerateTOML());
EXPECT_EQ(ssGenerated, ssTOMLInput);
sdv::TInterfaceAccessPtr ptrTable = parser.Root().GetNodeDirect("table");
EXPECT_TRUE(ptrTable);
sdv::toml::INodeInfo* pInfo = ptrTable.GetInterface<sdv::toml::INodeInfo>();
sdv::toml::INodeCollectionConvert* pConvert = ptrTable.GetInterface<sdv::toml::INodeCollectionConvert>();
ASSERT_NE(pInfo, nullptr);
ASSERT_NE(pConvert, nullptr);
EXPECT_FALSE(pInfo->IsInline());
EXPECT_TRUE(pConvert->CanMakeInline());
EXPECT_TRUE(pConvert->MakeInline());
EXPECT_TRUE(pInfo->IsInline());
EXPECT_NO_THROW(ssGenerated = parser.GenerateTOML());
EXPECT_EQ(ssGenerated, ssTOMLOutput);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,17 @@
/********************************************************************************
* 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:
* Martin Stimpfl - initial API and implementation
* Erik Verhoeven - writing TOML and whitespace preservation
********************************************************************************/
#include <gtest/gtest.h>
#include <limits>
#include <functional>

View File

@@ -1,3 +1,17 @@
/********************************************************************************
* 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:
* Martin Stimpfl - initial API and implementation
* Erik Verhoeven - writing TOML and whitespace preservation
********************************************************************************/
#include <gtest/gtest.h>
#include "../../../global/process_watchdog.h"
#include "../../../sdv_services/core/toml_parser/character_reader_utf_8.cpp"
@@ -6,6 +20,7 @@
#include "../../../sdv_services/core/toml_parser/parser_toml.cpp"
#include "../../../sdv_services/core/toml_parser/parser_node_toml.cpp"
#include "../../../sdv_services/core/toml_parser/miscellaneous.cpp"
#include "../../../sdv_services/core/toml_parser/code_snippet.cpp"
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int argc, wchar_t* argv[])

View File

@@ -1,3 +1,17 @@
/********************************************************************************
* 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:
* Martin Stimpfl - initial API and implementation
* Erik Verhoeven - writing TOML and whitespace preservation
********************************************************************************/
#include <functional>
#include <gtest/gtest.h>
#include <limits>

View File

@@ -1,3 +1,17 @@
/********************************************************************************
* 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:
* Martin Stimpfl - initial API and implementation
* Erik Verhoeven - writing TOML and whitespace preservation
********************************************************************************/
#include <gtest/gtest.h>
#include "../../../sdv_services/core/toml_parser/parser_toml.h"
#include "../../../sdv_services/core/toml_parser/parser_node_toml.h"
@@ -59,7 +73,7 @@ TEST(RecognizeTypes, Key_Value)
auto value_name = parser.Root().Direct("name");
EXPECT_EQ(value_name->GetType(), sdv::toml::ENodeType::node_string);
EXPECT_EQ(value_name->GetValue(), sdv::any_t("Hammer"));
EXPECT_EQ(value_name->GetValue(), "Hammer");
EXPECT_EQ(value_name->GetIndex(), 0u);
auto value_id = parser.Root().Direct("id");
@@ -427,6 +441,37 @@ TEST(NestedContent, InlineTable)
EXPECT_EQ(static_cast<std::string>(table3_e_b->GetValue()), "E");
}
TEST(NestedContent, InlineTableBreakLine)
{
// The following are not allowed
EXPECT_THROW(toml_parser::CParser(R"code(
table = { a = 1, b = 2,
c = 3, d = 4 }
)code"), sdv::toml::XTOMLParseException);
EXPECT_THROW(toml_parser::CParser(R"code(
table = { a = 1, b = 2
,c = 3, d = 4 }
)code"), sdv::toml::XTOMLParseException);
// Line breaks are allowed when part of an array or have multi-line strings
EXPECT_NO_THROW(toml_parser::CParser(R"code(
array = [{ a = 1, b = 2},
{c = 3, d = 4}]
)code"));
EXPECT_NO_THROW(toml_parser::CParser(R"code(
table = { a = 1, b = [2, 3,
4, 5], c = 6, d = 7}
)code"));
EXPECT_NO_THROW(toml_parser::CParser(R"code(
table = { x = "abc", y = """def-
ghi""", z = "jkl" }
)code"));
EXPECT_NO_THROW(toml_parser::CParser(R"code(
table = { x = 'abc', y = '''def-
ghi''', z = 'jkl' }
)code"));
}
TEST(SpecialCases, Keys)
{
using namespace std::string_literals;

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 <limits>
#include <functional>
@@ -9,7 +22,7 @@ std::string DumpTokenList(toml_parser::CLexer& rLexer)
{
auto eNavMode = rLexer.NavigationMode();
rLexer.NavigationMode(toml_parser::CLexer::ENavigationMode::do_not_skip_anything);
rLexer.Reset();
rLexer.ResetCursor();
std::stringstream sstream;
while (!rLexer.IsEnd())
{
@@ -51,7 +64,7 @@ std::string DumpTokenList(toml_parser::CLexer& rLexer)
}
}
rLexer.Reset();
rLexer.ResetCursor();
rLexer.NavigationMode(eNavMode);
return sstream.str();
}
@@ -365,7 +378,6 @@ std::string CategoryText(toml_parser::ETokenCategory eCategory)
}
}
/**
* @brief Find routine, extend the line and check for smart boundaries
* @param[in] rlexer Reference to the lexer to search for the tokens. The position will be reset and consumed until the
@@ -378,7 +390,7 @@ bool FindAndExtendToken(toml_parser::CLexer& rlexer, const std::string& rssKey,
const std::vector<toml_parser::ETokenCategory>& rvecCategories)
{
// Find the key
rlexer.Reset();
rlexer.ResetCursor();
while (!rlexer.IsEnd())
{
const toml_parser::CToken& rToken = rlexer.Consume();
@@ -386,31 +398,47 @@ bool FindAndExtendToken(toml_parser::CLexer& rlexer, const std::string& rssKey,
{
// Determine the range boundaries and create the range
auto prBoundaries = StatementBoundaries(rToken);
EXPECT_TRUE(prBoundaries.first);
EXPECT_TRUE(prBoundaries.second);
if (!prBoundaries.first || !prBoundaries.second)
{
std::cout << "Invalid statent boundaries..." << std::endl;
return false;
}
toml_parser::CNodeTokenRange range(toml_parser::CTokenRange(prBoundaries.first, prBoundaries.second.Next()));
// Auto extend the boundaries
rlexer.SmartExtendNodeRange(range);
EXPECT_TRUE(range.ExtendedNode().Begin());
if (!range.ExtendedNode().Begin())
{
std::cout << "Invalid extended node..." << std::endl;
return false;
}
std::reference_wrapper<const toml_parser::CToken> refToken(range.ExtendedNode().Begin());
size_t nIndex = 0;
auto itCategory = rvecCategories.begin();
do
{
if (nIndex == rvecCategories.size())
std::cout << "Find " << rssKey << " Index #" << nIndex << ": Received " << CategoryText(refToken.get().Category()) << std::endl;
EXPECT_LT(nIndex, rvecCategories.size());
{
std::cout << "Find " << rssKey << " Index #" << nIndex << ": Received "
<< CategoryText(refToken.get().Category()) << std::endl;
return false;
}
if (itCategory == rvecCategories.end()) return false;
if (*itCategory != refToken.get().Category())
std::cout << "Find " << rssKey << " Index #" << nIndex << ": Expected " << CategoryText(*itCategory) <<
", received " << CategoryText(refToken.get().Category()) << std::endl;
EXPECT_EQ(*itCategory, refToken.get().Category());
{
std::cout << "Find " << rssKey << " Index #" << nIndex << ": Expected " << CategoryText(*itCategory)
<< ", received " << CategoryText(refToken.get().Category()) << std::endl;
return false;
}
nIndex++;
itCategory++;
} while ((refToken = refToken.get().Next()).get() && refToken.get() != range.ExtendedNode().End());
if (itCategory != rvecCategories.end())
{
std::cout << "More items in the category vector than in the extended range: itCategory: "
<< CategoryText(*itCategory) << std::endl;
return false;
}
return true; // successful
}
}
@@ -466,7 +494,6 @@ token_a = 10
toml_parser::ETokenCategory::token_syntax_assignment,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_integer,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_syntax_new_line}));
}
@@ -511,7 +538,6 @@ token_d = "def"
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_float,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_syntax_new_line}));
}
@@ -610,6 +636,71 @@ token_f = "ghi" # after
toml_parser::ETokenCategory::token_syntax_new_line}));
}
TEST(TOMLLexerStatementBoundaryTests, AssignmentWithFollowingComment2)
{
std::string ssTOML = R"code(
# This is a separate comment with several line-breaks before.
# Followed by this text on the same line.
# Note: there was a space after the empty comment line.
# And another separate comment on a next line.
# This is a comment before the value.
# And another comment before the value at the same line.
#
# Note: there was a space after the empty comment line.
# But that should not influence the comment lines.
value = "this is the value text" # Comment following the value.
# More comment following the value.
# This becomes one line.
#
# But this is a separate line.
# This is also a separate comment.
# Followed by this text on the same line.
# And another text on a separate line.)code";
// Process the code
toml_parser::CLexer lexerCode(ssTOML);
// Assignment. Extended boundary includes following comments, whitespace and newlines.
EXPECT_TRUE(FindAndExtendToken(lexerCode, "value",
{toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_key,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_syntax_assignment,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_string,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_comment,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_syntax_new_line}));
}
TEST(TOMLLexerStatementBoundaryTests, TableAssignmentWithDedicatedComment)
{
std::string ssCode = R"code(
@@ -962,7 +1053,7 @@ TEST(TOMLLexerStatementBoundaryTests, IndentedTableWithoutComments)
toml_parser::ETokenCategory::token_syntax_new_line}));
}
TEST(TOMLLexerStatementBoundaryTests, IndenteTableWithAndWithoutComments)
TEST(TOMLLexerStatementBoundaryTests, IndentedTableWithAndWithoutComments)
{
std::string ssCode = R"code(
[token_s]
@@ -985,6 +1076,7 @@ token_u.token_aa.token_bb = 10 # table token_u has a table token_aa which ha
toml_parser::ETokenCategory::token_syntax_table_open,
toml_parser::ETokenCategory::token_key,
toml_parser::ETokenCategory::token_syntax_table_close,
toml_parser::ETokenCategory::token_syntax_new_line,
toml_parser::ETokenCategory::token_syntax_new_line}));
}
@@ -1095,8 +1187,7 @@ token_u.token_aa.token_cc = { dd = { ee = 10, ff = 11 }, # this is the commen
toml_parser::ETokenCategory::token_syntax_assignment,
toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_integer,
toml_parser::ETokenCategory::token_syntax_comma,
toml_parser::ETokenCategory::token_whitespace}));
toml_parser::ETokenCategory::token_syntax_comma}));
EXPECT_TRUE(FindAndExtendToken(lexerCode, "ii",
{toml_parser::ETokenCategory::token_whitespace,
toml_parser::ETokenCategory::token_key,