1 /*
2  * Copyright (C) 2016 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 <sys/time.h>
18 
19 #include <chrono>
20 #include <functional>
21 
22 #include <ScopedDisableMalloc.h>
23 #include <gtest/gtest.h>
24 
25 using namespace std::chrono_literals;
26 
27 namespace android {
28 
29 class DisableMallocTest : public ::testing::Test {
30  protected:
alarm(std::chrono::microseconds us)31   void alarm(std::chrono::microseconds us) {
32     std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(us);
33     itimerval t = itimerval();
34     t.it_value.tv_sec = s.count();
35     t.it_value.tv_usec = (us - s).count();
36     setitimer(ITIMER_REAL, &t, NULL);
37   }
38 };
39 
TEST_F(DisableMallocTest,reenable)40 TEST_F(DisableMallocTest, reenable) {
41   ASSERT_EXIT(
42       {
43         alarm(100ms);
44         void* ptr1 = malloc(128);
45         ASSERT_NE(ptr1, nullptr);
46         free(ptr1);
47         { ScopedDisableMalloc disable_malloc; }
48         void* ptr2 = malloc(128);
49         ASSERT_NE(ptr2, nullptr);
50         free(ptr2);
51         _exit(1);
52       },
53       ::testing::ExitedWithCode(1), "");
54 }
55 
TEST_F(DisableMallocTest,deadlock_allocate)56 TEST_F(DisableMallocTest, deadlock_allocate) {
57   ASSERT_DEATH(
58       {
59         void* ptr = malloc(128);
60         ASSERT_NE(ptr, nullptr);
61         free(ptr);
62         {
63           alarm(100ms);
64           ScopedDisableMalloc disable_malloc;
65           void* ptr = malloc(128);
66           ASSERT_NE(ptr, nullptr);
67           free(ptr);
68         }
69       },
70       "");
71 }
72 
TEST_F(DisableMallocTest,deadlock_new)73 TEST_F(DisableMallocTest, deadlock_new) {
74   ASSERT_DEATH(
75       {
76         // C++ allows `new Foo` to be replaced with a stack allocation or merged
77         // with future `new Foo` expressions, provided certain conditions are
78         // met [expr.new/10]. None of this applies to `operator new(size_t)`.
79         void* ptr = ::operator new(1);
80         ASSERT_NE(ptr, nullptr);
81         ::operator delete(ptr);
82         {
83           alarm(100ms);
84           ScopedDisableMalloc disable_malloc;
85           void* ptr = ::operator new(1);
86           ASSERT_NE(ptr, nullptr);
87           ::operator delete(ptr);
88         }
89       },
90       "");
91 }
92 
TEST_F(DisableMallocTest,deadlock_delete)93 TEST_F(DisableMallocTest, deadlock_delete) {
94   ASSERT_DEATH(
95       {
96         void* ptr = ::operator new(1);
97         ASSERT_NE(ptr, nullptr);
98         {
99           alarm(250ms);
100           ScopedDisableMalloc disable_malloc;
101           ::operator delete(ptr);
102         }
103       },
104       "");
105 }
106 
TEST_F(DisableMallocTest,deadlock_free)107 TEST_F(DisableMallocTest, deadlock_free) {
108   ASSERT_DEATH(
109       {
110         void* ptr = malloc(128);
111         ASSERT_NE(ptr, nullptr);
112         {
113           alarm(100ms);
114           ScopedDisableMalloc disable_malloc;
115           free(ptr);
116         }
117       },
118       "");
119 }
120 
TEST_F(DisableMallocTest,deadlock_fork)121 TEST_F(DisableMallocTest, deadlock_fork) {
122   ASSERT_DEATH({
123     {
124       alarm(100ms);
125       ScopedDisableMalloc disable_malloc;
126       fork();
127 }
128 }, "");
129 }
130 
131 }  // namespace android
132