/******************************************************************************** * 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 "includes.h" #include "parser_test.h" #include "../../../sdv_executables/sdv_idl_compiler/entities/meta_entity.cpp" #include "../../../sdv_executables/sdv_idl_compiler/parser.h" #include using CParserMetaTest = CParserTest; TEST_F(CParserMetaTest, CheckIncludeLocal) { // Create a dummy file std::ofstream fstreamTest("include_test.idl", std::ios_base::out | std::ios_base::trunc); ASSERT_TRUE(fstreamTest.is_open()); fstreamTest << "const int32 i = 10;"; fstreamTest.close(); // Parse the statement CParser parser("#include \"include_test.idl\""); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 1); // Check for the include meta (first entry) ASSERT_TRUE(rlstMeta.front() != nullptr); CEntityPtr ptrMeta = rlstMeta.front(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::include_local); EXPECT_EQ(pMeta->GetContent(), "\"include_test.idl\""); fstreamTest.close(); try { std::filesystem::remove("include_test.idl"); } catch (const std::filesystem::filesystem_error&) {} } TEST_F(CParserMetaTest, CheckIncludeLocalAbsolute) { // Create a dummy file std::filesystem::path pathCurrent = std::filesystem::current_path(); std::ofstream fstreamTest("include_test.idl", std::ios_base::out | std::ios_base::trunc); ASSERT_TRUE(fstreamTest.is_open()); fstreamTest << "const int32 i = 10;"; fstreamTest.close(); // Parse the statement std::string ssCode = "#include \""; ssCode += (pathCurrent / "include_test.idl").generic_u8string(); ssCode += "\""; CParser parser(ssCode.c_str()); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 1); // Check for the include meta (first entry) ASSERT_TRUE(rlstMeta.front() != nullptr); CEntityPtr ptrMeta = rlstMeta.front(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::include_local); EXPECT_EQ(pMeta->GetContent(), std::string("\"") + (pathCurrent / "include_test.idl").generic_u8string() + "\""); fstreamTest.close(); try { std::filesystem::remove("include_test.idl"); } catch (const std::filesystem::filesystem_error&) {} } TEST_F(CParserMetaTest, CheckIncludeGlobal) { // Create a dummy file std::filesystem::create_directory("dummy1"); std::filesystem::path path = "dummy1/include_test.idl"; std::ofstream fstreamTest(path.generic_u8string().c_str(), std::ios_base::out | std::ios_base::trunc); ASSERT_TRUE(fstreamTest.is_open()); fstreamTest << "const int32 i = 20;"; fstreamTest.close(); // Make include dirs (1st argument is the executable file path). std::vector vecArgs = {"idl_compiler_test.exe", "-Idummy1"}; CIdlCompilerEnvironment environment(vecArgs); // Parse the statement CParser parser("#include ", environment); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 1); // Check for the include meta (first entry) ASSERT_TRUE(rlstMeta.front() != nullptr); CEntityPtr ptrMeta = rlstMeta.front(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::include_global); EXPECT_EQ(pMeta->GetContent(), ""); fstreamTest.close(); try { std::filesystem::remove(path); std::filesystem::remove_all("dummy1"); } catch (const std::filesystem::filesystem_error&) {} } TEST_F(CParserMetaTest, CheckDefine) { // Parse the statement CParser parser("#define def1\n#define def2 10"); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 2); // Check for the 1st define meta ASSERT_TRUE(rlstMeta.front() != nullptr); CEntityPtr ptrMeta = rlstMeta.front(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::define); EXPECT_EQ(pMeta->GetContent(), "def1"); // Check for the 2nd define meta ASSERT_TRUE(rlstMeta.back() != nullptr); ptrMeta = rlstMeta.back(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::define); EXPECT_EQ(pMeta->GetContent(), "def2 10"); } TEST_F(CParserMetaTest, CheckUndef) { // Parse the statement CParser parser("#define def1 10\n#undef def1"); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 2); // Check for the define meta (first entry) ASSERT_TRUE(rlstMeta.front() != nullptr); CEntityPtr ptrMeta = rlstMeta.front(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::define); EXPECT_EQ(pMeta->GetContent(), "def1 10"); // Check for the undef meta (second entry) ASSERT_TRUE(rlstMeta.back() != nullptr); ptrMeta = rlstMeta.back(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::undef); EXPECT_EQ(pMeta->GetContent(), "def1"); } TEST_F(CParserMetaTest, CheckIncludeLocalDefineCombi) { // Create a dummy file std::ofstream fstreamTest("include_test.idl", std::ios_base::out | std::ios_base::trunc); ASSERT_TRUE(fstreamTest.is_open()); fstreamTest << "#define HELLO"; fstreamTest.close(); // Parse the statement CParser parser("#include \"include_test.idl\""); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 2); // Check for the include meta (first entry) ASSERT_TRUE(rlstMeta.front() != nullptr); CEntityPtr ptrMeta = rlstMeta.front(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::include_local); EXPECT_EQ(pMeta->GetContent(), "\"include_test.idl\""); // Check for the define meta (second entry) ASSERT_TRUE(rlstMeta.back() != nullptr); ptrMeta = rlstMeta.back(); EXPECT_EQ(ptrMeta->GetType(), sdv::idl::EEntityType::type_meta); pMeta = ptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::define); EXPECT_EQ(pMeta->GetContent(), "HELLO"); fstreamTest.close(); try { std::filesystem::remove("include_test.idl"); } catch (const std::filesystem::filesystem_error&) {} } TEST_F(CParserMetaTest, CheckVerbatim) { // Parse the statement CParser parser( "#verbatim const int32 i = 10\n" "#verbatim const int32 j = 10\n" "#verbatim const int32 k = 10\\\n" "const int32 l = 10\n" "// Definition of M\n" "#verbatim #define M\n" "#verbatim #include "); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 5); size_t nIndex = 0; for (const CEntityPtr& rptrMeta : rlstMeta) { EXPECT_EQ(rptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = rptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::verbatim); switch (nIndex) { case 0: EXPECT_EQ(pMeta->GetContent(), "const int32 i = 10"); break; case 1: EXPECT_EQ(pMeta->GetContent(), "const int32 j = 10"); break; case 2: EXPECT_EQ(pMeta->GetContent(), "const int32 k = 10\\\nconst int32 l = 10"); break; case 3: { EXPECT_EQ(pMeta->GetContent(), "#define M"); uint32_t uiFlags = 0; EXPECT_EQ(pMeta->GetComments(uiFlags), "Definition of M"); break; } case 4: EXPECT_EQ(pMeta->GetContent(), "#include "); break; } nIndex++; } } TEST_F(CParserMetaTest, CheckVerbatimBlock) { // Parse the statement CParser parser( "#verbatim_begin\n" "const int32 i = 10\n" "const int32 j = 10\n" "const int32 k = 10\\\n" "const int32 l = 10\n" "// Definition of M\n" "#define M\n" "#include \n" "#verbatim_end\n" "#define N\n"); parser.Parse(); const CEntityList& rlstMeta = parser.Root()->Get()->GetMeta(); ASSERT_EQ(rlstMeta.size(), 2); size_t nIndex = 0; for (const CEntityPtr& rptrMeta : rlstMeta) { EXPECT_EQ(rptrMeta->GetType(), sdv::idl::EEntityType::type_meta); const CMetaEntity* pMeta = rptrMeta->Get(); ASSERT_TRUE(pMeta != nullptr); switch (nIndex) { case 0: EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::verbatim); EXPECT_EQ(pMeta->GetContent(), "const int32 i = 10\n" "const int32 j = 10\n" "const int32 k = 10\\\n" "const int32 l = 10\n" "// Definition of M\n" "#define M\n" "#include \n" ); break; case 1: EXPECT_EQ(pMeta->GetMetaType(), sdv::idl::IMetaEntity::EType::define); EXPECT_EQ(pMeta->GetContent(), "N"); break; } nIndex++; } }