1 | //===-- Unittests for atexit ----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/__support/CPP/array.h" |
10 | #include "src/__support/CPP/utility.h" |
11 | #include "src/stdlib/_Exit.h" |
12 | #include "src/stdlib/atexit.h" |
13 | #include "src/stdlib/exit.h" |
14 | #include "test/UnitTest/Test.h" |
15 | |
16 | static int a; |
17 | TEST(LlvmLibcAtExit, Basic) { |
18 | // In case tests ever run multiple times. |
19 | a = 0; |
20 | |
21 | auto test = [] { |
22 | int status = LIBC_NAMESPACE::atexit(+[] { |
23 | if (a != 1) |
24 | __builtin_trap(); |
25 | }); |
26 | status |= LIBC_NAMESPACE::atexit(+[] { a++; }); |
27 | if (status) |
28 | __builtin_trap(); |
29 | |
30 | LIBC_NAMESPACE::exit(0); |
31 | }; |
32 | EXPECT_EXITS(test, 0); |
33 | } |
34 | |
35 | TEST(LlvmLibcAtExit, AtExitCallsSysExit) { |
36 | auto test = [] { |
37 | LIBC_NAMESPACE::atexit(+[] { LIBC_NAMESPACE::_Exit(1); }); |
38 | LIBC_NAMESPACE::exit(0); |
39 | }; |
40 | EXPECT_EXITS(test, 1); |
41 | } |
42 | |
43 | static int size; |
44 | static LIBC_NAMESPACE::cpp::array<int, 256> arr; |
45 | |
46 | template <int... Ts> |
47 | void register_atexit_handlers( |
48 | LIBC_NAMESPACE::cpp::integer_sequence<int, Ts...>) { |
49 | (LIBC_NAMESPACE::atexit(+[] { arr[size++] = Ts; }), ...); |
50 | } |
51 | |
52 | template <int count> constexpr auto getTest() { |
53 | return [] { |
54 | LIBC_NAMESPACE::atexit(+[] { |
55 | if (size != count) |
56 | __builtin_trap(); |
57 | for (int i = 0; i < count; i++) |
58 | if (arr[i] != count - 1 - i) |
59 | __builtin_trap(); |
60 | }); |
61 | register_atexit_handlers( |
62 | LIBC_NAMESPACE::cpp::make_integer_sequence<int, count>{}); |
63 | LIBC_NAMESPACE::exit(0); |
64 | }; |
65 | } |
66 | |
67 | TEST(LlvmLibcAtExit, ReverseOrder) { |
68 | // In case tests ever run multiple times. |
69 | size = 0; |
70 | |
71 | auto test = getTest<32>(); |
72 | EXPECT_EXITS(test, 0); |
73 | } |
74 | |
75 | TEST(LlvmLibcAtExit, Many) { |
76 | // In case tests ever run multiple times. |
77 | size = 0; |
78 | |
79 | auto test = getTest<256>(); |
80 | EXPECT_EXITS(test, 0); |
81 | } |
82 | |
83 | TEST(LlvmLibcAtExit, HandlerCallsAtExit) { |
84 | auto test = [] { |
85 | LIBC_NAMESPACE::atexit( |
86 | +[] { LIBC_NAMESPACE::atexit(+[] { LIBC_NAMESPACE::exit(1); }); }); |
87 | LIBC_NAMESPACE::exit(0); |
88 | }; |
89 | EXPECT_EXITS(test, 1); |
90 | } |
91 | |