1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <gtest/gtest.h> 18 19 #include <dlfcn.h> 20 #include <libgen.h> 21 #include <limits.h> 22 #include <stdio.h> 23 #include <stdint.h> 24 25 #include <string> 26 27 TEST(atexit, sofile) { 28 std::string atexit_call_sequence; 29 bool valid_this_in_static_dtor = false; 30 bool attr_dtor_called = false; 31 32 void* handle = dlopen("libtest_atexit.so", RTLD_NOW); 33 ASSERT_TRUE(handle != nullptr); 34 35 typedef int (*int_fn)(void); 36 int_fn get_cxx_ctor_called, get_attr_ctor_called; 37 get_cxx_ctor_called = reinterpret_cast<int_fn>(dlsym(handle, "get_cxx_ctor_called")); 38 get_attr_ctor_called = reinterpret_cast<int_fn>(dlsym(handle, "get_attr_ctor_called")); 39 ASSERT_TRUE(get_cxx_ctor_called != nullptr); 40 ASSERT_TRUE(get_attr_ctor_called != nullptr); 41 42 ASSERT_EQ(1, get_cxx_ctor_called()); 43 ASSERT_EQ(1, get_attr_ctor_called()); 44 45 void* sym = dlsym(handle, "register_atexit"); 46 ASSERT_TRUE(sym != nullptr); 47 reinterpret_cast<void (*)(std::string*, bool*, bool*)>(sym)(&atexit_call_sequence, &valid_this_in_static_dtor, &attr_dtor_called); 48 49 ASSERT_EQ(0, dlclose(handle)); 50 // this test verifies atexit call from atexit handler. as well as the order of calls 51 ASSERT_EQ("Humpty Dumpty sat on a wall", atexit_call_sequence); 52 ASSERT_TRUE(valid_this_in_static_dtor); 53 ASSERT_TRUE(attr_dtor_called); 54 } 55 56 class TestMainStaticDtorClass { 57 public: 58 TestMainStaticDtorClass() { 59 expected_this = this; 60 } 61 62 ~TestMainStaticDtorClass() { 63 if (this != expected_this) { 64 fprintf(stderr, "\nerror: static d-tor called with incorrect this pointer: %p, expected: %p\n", this, expected_this); 65 } else { 66 fprintf(stderr, "6"); 67 } 68 } 69 private: 70 static const TestMainStaticDtorClass* expected_this; 71 }; 72 73 const TestMainStaticDtorClass* TestMainStaticDtorClass::expected_this = nullptr; 74 75 static void atexit_func5() { 76 fprintf(stderr, "5"); 77 } 78 79 static void atexit_func4() { 80 fprintf(stderr, "4"); 81 } 82 83 static void atexit_func3() { 84 fprintf(stderr, "3"); 85 atexit(atexit_func4); 86 } 87 88 static void atexit_func2() { 89 fprintf(stderr, "2"); 90 } 91 92 static void atexit_func1() { 93 fprintf(stderr, "1"); 94 } 95 96 static void atexit_main() { 97 // This should result in "123456" output to stderr 98 static TestMainStaticDtorClass static_obj; 99 atexit(atexit_func5); 100 atexit(atexit_func3); 101 atexit(atexit_func2); 102 atexit(atexit_func1); 103 exit(0); 104 } 105 106 TEST(atexit, exit) { 107 ASSERT_EXIT(atexit_main(), testing::ExitedWithCode(0), "123456"); 108 } 109 110