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/atexit.h"
12 #include "src/stdlib/exit.h"
13 #include "utils/UnitTest/Test.h"
14 
15 static int a;
TEST(LlvmLibcAtExit,Basic)16 TEST(LlvmLibcAtExit, Basic) {
17   // In case tests ever run multiple times.
18   a = 0;
19 
20   auto test = [] {
21     int status = __llvm_libc::atexit(+[] {
22       if (a != 1)
23         __builtin_trap();
24     });
25     status |= __llvm_libc::atexit(+[] { a++; });
26     if (status)
27       __builtin_trap();
28 
29     __llvm_libc::exit(0);
30   };
31   EXPECT_EXITS(test, 0);
32 }
33 
TEST(LlvmLibcAtExit,AtExitCallsSysExit)34 TEST(LlvmLibcAtExit, AtExitCallsSysExit) {
35   auto test = [] {
36     __llvm_libc::atexit(+[] { _Exit(1); });
37     __llvm_libc::exit(0);
38   };
39   EXPECT_EXITS(test, 1);
40 }
41 
42 static int size;
43 static __llvm_libc::cpp::Array<int, 256> arr;
44 
45 template <int... Ts>
register_atexit_handlers(__llvm_libc::cpp::IntegerSequence<int,Ts...>)46 void register_atexit_handlers(__llvm_libc::cpp::IntegerSequence<int, Ts...>) {
47   (__llvm_libc::atexit(+[] { arr[size++] = Ts; }), ...);
48 }
49 
getTest()50 template <int count> constexpr auto getTest() {
51   return [] {
52     __llvm_libc::atexit(+[] {
53       if (size != count)
54         __builtin_trap();
55       for (int i = 0; i < count; i++)
56         if (arr[i] != count - 1 - i)
57           __builtin_trap();
58     });
59     register_atexit_handlers(
60         __llvm_libc::cpp::MakeIntegerSequence<int, count>{});
61     __llvm_libc::exit(0);
62   };
63 }
64 
TEST(LlvmLibcAtExit,ReverseOrder)65 TEST(LlvmLibcAtExit, ReverseOrder) {
66   // In case tests ever run multiple times.
67   size = 0;
68 
69   auto test = getTest<32>();
70   EXPECT_EXITS(test, 0);
71 }
72 
TEST(LlvmLibcAtExit,Many)73 TEST(LlvmLibcAtExit, Many) {
74   // In case tests ever run multiple times.
75   size = 0;
76 
77   auto test = getTest<256>();
78   EXPECT_EXITS(test, 0);
79 }
80 
TEST(LlvmLibcAtExit,HandlerCallsAtExit)81 TEST(LlvmLibcAtExit, HandlerCallsAtExit) {
82   auto test = [] {
83     __llvm_libc::atexit(+[] {
84       __llvm_libc::atexit(+[] { __llvm_libc::exit(1); });
85     });
86     __llvm_libc::exit(0);
87   };
88   EXPECT_EXITS(test, 1);
89 }
90