From 6894faac1fc45c55c2c5ec6dad1961f05f23cc50 Mon Sep 17 00:00:00 2001 From: Dan Klishch Date: Sun, 21 Apr 2024 22:37:35 -0400 Subject: [PATCH] Tests/LibELF: Add basic test checking initializer ordering --- Base/home/anon/.config/Tests.ini | 2 +- Tests/LibELF/CMakeLists.txt | 29 +++++++++++++--- Tests/LibELF/TestOrder.cpp | 58 ++++++++++++++++++++++++++++++++ Tests/LibELF/TestOrderExe.cpp | 20 +++++++++++ Tests/LibELF/TestOrderLib1.cpp | 18 ++++++++++ Tests/LibELF/TestOrderLib2.cpp | 18 ++++++++++ 6 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 Tests/LibELF/TestOrder.cpp create mode 100644 Tests/LibELF/TestOrderExe.cpp create mode 100644 Tests/LibELF/TestOrderLib1.cpp create mode 100644 Tests/LibELF/TestOrderLib2.cpp diff --git a/Base/home/anon/.config/Tests.ini b/Base/home/anon/.config/Tests.ini index 4ffa2c5d6eb..ea0e04b5462 100644 --- a/Base/home/anon/.config/Tests.ini +++ b/Base/home/anon/.config/Tests.ini @@ -2,7 +2,7 @@ SkipDirectories=Kernel/Legacy Shell SkipRegex=^ue-.*$ SkipTests=TestCommonmark function.sh -NotTestsPattern=^.*(txt|frm|inc)$ +NotTestsPattern=^.*(txt|frm|inc|so|elf)$ [test-js] Arguments=--show-progress=false diff --git a/Tests/LibELF/CMakeLists.txt b/Tests/LibELF/CMakeLists.txt index 64140637e96..9579678315c 100644 --- a/Tests/LibELF/CMakeLists.txt +++ b/Tests/LibELF/CMakeLists.txt @@ -3,10 +3,13 @@ set(CMAKE_SKIP_RPATH FALSE) macro(add_test_lib NAME FILE) add_library(${NAME} SHARED ${FILE}) serenity_set_implicit_links(${NAME}) - # Avoid execution by the test runner - install(TARGETS ${NAME} - DESTINATION usr/Tests/LibELF - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE GROUP_WRITE) + install(TARGETS ${NAME} DESTINATION usr/Tests/LibELF) +endmacro() + +macro(add_test_exe NAME FILE) + add_executable(${NAME} ${FILE}) + serenity_set_implicit_links(${NAME}) + install(TARGETS ${NAME} DESTINATION usr/Tests/LibELF) endmacro() macro(add_dlopen_lib NAME FUNCTION) @@ -28,6 +31,7 @@ unset(CMAKE_INSTALL_RPATH) set(TEST_SOURCES test-elf.cpp TestDlOpen.cpp + TestOrder.cpp TestTLS.cpp TestWeakSymbolResolution.cpp ) @@ -48,3 +52,20 @@ add_test_lib(TestWeakSymbolResolution1 TestWeakSymbolResolution1.cpp) add_test_lib(TestWeakSymbolResolution2 TestWeakSymbolResolution2.cpp) target_link_libraries(TestWeakSymbolResolution PRIVATE TestWeakSymbolResolution1 TestWeakSymbolResolution2) set_target_properties(TestWeakSymbolResolution PROPERTIES INSTALL_RPATH "$ORIGIN") + +add_test_lib(TestOrderLib1 TestOrderLib1.cpp) +add_test_lib(TestOrderLib2 TestOrderLib2.cpp) +target_link_libraries(TestOrderLib2 PRIVATE TestOrderLib1) +set_target_properties(TestOrderLib2 PROPERTIES INSTALL_RPATH "$ORIGIN") + +# NOTE: This is so ugly because CMake sorts targets supplied to target_link_libraries. +# .elf extension here avoids direct invocations by SerenityOS's test runner. +add_test_exe(TestOrderExe1.elf TestOrderExe.cpp) +target_link_libraries(TestOrderExe1.elf PRIVATE $ $) +add_dependencies(TestOrderExe1.elf TestOrderLib1 TestOrderLib2) +set_target_properties(TestOrderExe1.elf PROPERTIES INSTALL_RPATH "$ORIGIN") + +add_test_exe(TestOrderExe2.elf TestOrderExe.cpp) +target_link_libraries(TestOrderExe2.elf PRIVATE $ $) +add_dependencies(TestOrderExe2.elf TestOrderLib1 TestOrderLib2) +set_target_properties(TestOrderExe2.elf PROPERTIES INSTALL_RPATH "$ORIGIN") diff --git a/Tests/LibELF/TestOrder.cpp b/Tests/LibELF/TestOrder.cpp new file mode 100644 index 00000000000..05e2da85c7d --- /dev/null +++ b/Tests/LibELF/TestOrder.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +auto temp_directory = [] { + return MUST(FileSystem::TempFile::create_temp_directory()); +}(); + +static ByteBuffer run(ByteString executable) +{ + static auto path_to_captured_output = LexicalPath::join(temp_directory->path(), "output"sv); + + auto process = MUST(Core::Process::spawn(Core::ProcessSpawnOptions { + .executable = move(executable), + .file_actions = { + Core::FileAction::OpenFile { + .path = path_to_captured_output.string(), + .mode = Core::File::OpenMode::Write, + .fd = 1, + }, + }, + })); + MUST(process.wait_for_termination()); + auto output = MUST(Core::File::open(path_to_captured_output.string(), Core::File::OpenMode::Read)); + return MUST(output->read_until_eof()); +} + +TEST_CASE(order) +{ + { + auto expected = R"(TestOrderLib1.cpp:init +TestOrderLib2.cpp:init +TestOrderExe.cpp:init +TestOrderExe.cpp:main +f() returns: TestOrderLib1.cpp +)"sv; + auto output = run("TestOrderExe1.elf"); + EXPECT_EQ(StringView(output.bytes()), expected); + } + + { + auto expected = R"(TestOrderLib1.cpp:init +TestOrderLib2.cpp:init +TestOrderExe.cpp:init +TestOrderExe.cpp:main +f() returns: TestOrderLib2.cpp +)"sv; + auto output = run("TestOrderExe2.elf"); + EXPECT_EQ(StringView(output.bytes()), expected); + } +} diff --git a/Tests/LibELF/TestOrderExe.cpp b/Tests/LibELF/TestOrderExe.cpp new file mode 100644 index 00000000000..3ba77e69a40 --- /dev/null +++ b/Tests/LibELF/TestOrderExe.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +[[gnu::constructor]] static void init() +{ + outln("TestOrderExe.cpp:init"); +} + +StringView f(); + +int main() +{ + outln("TestOrderExe.cpp:main"); + outln("f() returns: {}", f()); +} diff --git a/Tests/LibELF/TestOrderLib1.cpp b/Tests/LibELF/TestOrderLib1.cpp new file mode 100644 index 00000000000..9a2ad2dbdc9 --- /dev/null +++ b/Tests/LibELF/TestOrderLib1.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +[[gnu::constructor]] static void init() +{ + outln("TestOrderLib1.cpp:init"); +} + +StringView f(); +StringView f() +{ + return "TestOrderLib1.cpp"sv; +} diff --git a/Tests/LibELF/TestOrderLib2.cpp b/Tests/LibELF/TestOrderLib2.cpp new file mode 100644 index 00000000000..bce8f356752 --- /dev/null +++ b/Tests/LibELF/TestOrderLib2.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +[[gnu::constructor]] static void init() +{ + outln("TestOrderLib2.cpp:init"); +} + +StringView f(); +StringView f() +{ + return "TestOrderLib2.cpp"sv; +}