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