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