| //===-- Unittests for atexit ----------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "src/__support/CPP/array.h" | |
| #include "src/__support/CPP/utility.h" | |
| #include "src/stdlib/_Exit.h" | |
| #include "src/stdlib/atexit.h" | |
| #include "src/stdlib/exit.h" | |
| #include "test/UnitTest/Test.h" | |
| static int a; | |
| TEST(LlvmLibcAtExit, Basic) { | |
| // In case tests ever run multiple times. | |
| a = 0; | |
| auto test = [] { | |
| int status = LIBC_NAMESPACE::atexit(+[] { | |
| if (a != 1) | |
| __builtin_trap(); | |
| }); | |
| status |= LIBC_NAMESPACE::atexit(+[] { a++; }); | |
| if (status) | |
| __builtin_trap(); | |
| LIBC_NAMESPACE::exit(0); | |
| }; | |
| EXPECT_EXITS(test, 0); | |
| } | |
| TEST(LlvmLibcAtExit, AtExitCallsSysExit) { | |
| auto test = [] { | |
| LIBC_NAMESPACE::atexit(+[] { LIBC_NAMESPACE::_Exit(1); }); | |
| LIBC_NAMESPACE::exit(0); | |
| }; | |
| EXPECT_EXITS(test, 1); | |
| } | |
| static int size; | |
| static LIBC_NAMESPACE::cpp::array<int, 256> arr; | |
| template <int... Ts> | |
| void register_atexit_handlers( | |
| LIBC_NAMESPACE::cpp::integer_sequence<int, Ts...>) { | |
| (LIBC_NAMESPACE::atexit(+[] { arr[size++] = Ts; }), ...); | |
| } | |
| template <int count> constexpr auto getTest() { | |
| return [] { | |
| LIBC_NAMESPACE::atexit(+[] { | |
| if (size != count) | |
| __builtin_trap(); | |
| for (int i = 0; i < count; i++) | |
| if (arr[i] != count - 1 - i) | |
| __builtin_trap(); | |
| }); | |
| register_atexit_handlers( | |
| LIBC_NAMESPACE::cpp::make_integer_sequence<int, count>{}); | |
| LIBC_NAMESPACE::exit(0); | |
| }; | |
| } | |
| TEST(LlvmLibcAtExit, ReverseOrder) { | |
| // In case tests ever run multiple times. | |
| size = 0; | |
| auto test = getTest<32>(); | |
| EXPECT_EXITS(test, 0); | |
| } | |
| TEST(LlvmLibcAtExit, Many) { | |
| // In case tests ever run multiple times. | |
| size = 0; | |
| auto test = getTest<256>(); | |
| EXPECT_EXITS(test, 0); | |
| } | |
| TEST(LlvmLibcAtExit, HandlerCallsAtExit) { | |
| auto test = [] { | |
| LIBC_NAMESPACE::atexit( | |
| +[] { LIBC_NAMESPACE::atexit(+[] { LIBC_NAMESPACE::exit(1); }); }); | |
| LIBC_NAMESPACE::exit(0); | |
| }; | |
| EXPECT_EXITS(test, 1); | |
| } |