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/mman.h> 18 #include <unistd.h> 19 20 #include "HeapWalker.h" 21 22 #include <ScopedDisableMalloc.h> 23 #include <gtest/gtest.h> 24 #include "Allocator.h" 25 26 namespace android { 27 28 class HeapWalkerTest : public ::testing::Test { 29 public: 30 HeapWalkerTest() : disable_malloc_(), heap_() {} 31 32 void TearDown() { 33 ASSERT_TRUE(heap_.empty()); 34 if (!HasFailure()) { 35 ASSERT_FALSE(disable_malloc_.timed_out()); 36 } 37 } 38 39 protected: 40 ScopedDisableMallocTimeout disable_malloc_; 41 Heap heap_; 42 }; 43 44 TEST_F(HeapWalkerTest, allocation) { 45 HeapWalker heap_walker(heap_); 46 ASSERT_TRUE(heap_walker.Allocation(3, 4)); 47 ASSERT_TRUE(heap_walker.Allocation(2, 3)); 48 ASSERT_TRUE(heap_walker.Allocation(4, 5)); 49 ASSERT_TRUE(heap_walker.Allocation(6, 7)); 50 ASSERT_TRUE(heap_walker.Allocation(0, 1)); 51 } 52 53 TEST_F(HeapWalkerTest, overlap) { 54 HeapWalker heap_walker(heap_); 55 ASSERT_TRUE(heap_walker.Allocation(2, 3)); 56 ASSERT_TRUE(heap_walker.Allocation(3, 4)); 57 ASSERT_FALSE(heap_walker.Allocation(2, 3)); 58 ASSERT_FALSE(heap_walker.Allocation(1, 3)); 59 ASSERT_FALSE(heap_walker.Allocation(1, 4)); 60 ASSERT_FALSE(heap_walker.Allocation(1, 5)); 61 ASSERT_FALSE(heap_walker.Allocation(3, 4)); 62 ASSERT_FALSE(heap_walker.Allocation(3, 5)); 63 ASSERT_TRUE(heap_walker.Allocation(4, 5)); 64 ASSERT_TRUE(heap_walker.Allocation(1, 2)); 65 } 66 67 TEST_F(HeapWalkerTest, zero) { 68 HeapWalker heap_walker(heap_); 69 ASSERT_TRUE(heap_walker.Allocation(2, 2)); 70 ASSERT_FALSE(heap_walker.Allocation(2, 2)); 71 ASSERT_TRUE(heap_walker.Allocation(3, 3)); 72 ASSERT_TRUE(heap_walker.Allocation(1, 1)); 73 ASSERT_FALSE(heap_walker.Allocation(2, 3)); 74 } 75 76 #define buffer_begin(buffer) reinterpret_cast<uintptr_t>(buffer) 77 #define buffer_end(buffer) (reinterpret_cast<uintptr_t>(buffer) + sizeof(buffer)) 78 79 TEST_F(HeapWalkerTest, leak) { 80 void* buffer1[16]{}; 81 char buffer2[16]{}; 82 buffer1[0] = &buffer2[0] - sizeof(void*); 83 buffer1[1] = &buffer2[15] + sizeof(void*); 84 85 HeapWalker heap_walker(heap_); 86 heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2)); 87 88 ASSERT_EQ(true, heap_walker.DetectLeaks()); 89 90 allocator::vector<Range> leaked(heap_); 91 size_t num_leaks = 0; 92 size_t leaked_bytes = 0; 93 ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes)); 94 95 EXPECT_EQ(1U, num_leaks); 96 EXPECT_EQ(16U, leaked_bytes); 97 ASSERT_EQ(1U, leaked.size()); 98 EXPECT_EQ(buffer_begin(buffer2), leaked[0].begin); 99 EXPECT_EQ(buffer_end(buffer2), leaked[0].end); 100 } 101 102 TEST_F(HeapWalkerTest, live) { 103 const int from_buffer_entries = 4; 104 const int to_buffer_bytes = 16; 105 106 for (int i = 0; i < from_buffer_entries; i++) { 107 for (int j = 0; j < to_buffer_bytes; j++) { 108 void* buffer1[from_buffer_entries]{}; 109 char buffer2[to_buffer_bytes]{}; 110 buffer1[i] = &buffer2[j]; 111 112 HeapWalker heap_walker(heap_); 113 heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2)); 114 heap_walker.Root(buffer_begin(buffer1), buffer_end(buffer1)); 115 116 ASSERT_EQ(true, heap_walker.DetectLeaks()); 117 118 allocator::vector<Range> leaked(heap_); 119 size_t num_leaks = SIZE_MAX; 120 size_t leaked_bytes = SIZE_MAX; 121 ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes)); 122 123 EXPECT_EQ(0U, num_leaks); 124 EXPECT_EQ(0U, leaked_bytes); 125 EXPECT_EQ(0U, leaked.size()); 126 } 127 } 128 } 129 130 TEST_F(HeapWalkerTest, unaligned) { 131 const int from_buffer_entries = 4; 132 const int to_buffer_bytes = 16; 133 void* buffer1[from_buffer_entries]{}; 134 char buffer2[to_buffer_bytes]{}; 135 136 buffer1[1] = &buffer2; 137 138 for (unsigned int i = 0; i < sizeof(uintptr_t); i++) { 139 for (unsigned int j = 0; j < sizeof(uintptr_t); j++) { 140 HeapWalker heap_walker(heap_); 141 heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2)); 142 heap_walker.Root(buffer_begin(buffer1) + i, buffer_end(buffer1) - j); 143 144 ASSERT_EQ(true, heap_walker.DetectLeaks()); 145 146 allocator::vector<Range> leaked(heap_); 147 size_t num_leaks = SIZE_MAX; 148 size_t leaked_bytes = SIZE_MAX; 149 ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes)); 150 151 EXPECT_EQ(0U, num_leaks); 152 EXPECT_EQ(0U, leaked_bytes); 153 EXPECT_EQ(0U, leaked.size()); 154 } 155 } 156 } 157 158 TEST_F(HeapWalkerTest, cycle) { 159 void* buffer1; 160 void* buffer2; 161 162 buffer1 = &buffer2; 163 buffer2 = &buffer1; 164 165 HeapWalker heap_walker(heap_); 166 heap_walker.Allocation(buffer_begin(buffer1), buffer_end(buffer1)); 167 heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2)); 168 169 ASSERT_EQ(true, heap_walker.DetectLeaks()); 170 171 allocator::vector<Range> leaked(heap_); 172 size_t num_leaks = 0; 173 size_t leaked_bytes = 0; 174 ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes)); 175 176 EXPECT_EQ(2U, num_leaks); 177 EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes); 178 ASSERT_EQ(2U, leaked.size()); 179 } 180 181 TEST_F(HeapWalkerTest, segv) { 182 const size_t page_size = sysconf(_SC_PAGE_SIZE); 183 void* buffer1 = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 184 ASSERT_NE(buffer1, nullptr); 185 void* buffer2; 186 187 buffer2 = &buffer1; 188 189 HeapWalker heap_walker(heap_); 190 heap_walker.Allocation(buffer_begin(buffer1), buffer_begin(buffer1) + page_size); 191 heap_walker.Root(buffer_begin(buffer2), buffer_end(buffer2)); 192 193 ASSERT_EQ(true, heap_walker.DetectLeaks()); 194 195 allocator::vector<Range> leaked(heap_); 196 size_t num_leaks = 0; 197 size_t leaked_bytes = 0; 198 ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes)); 199 200 EXPECT_EQ(0U, num_leaks); 201 EXPECT_EQ(0U, leaked_bytes); 202 ASSERT_EQ(0U, leaked.size()); 203 } 204 205 } // namespace android 206