1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/allocators.h"
16 :
17 : #include <set>
18 : #include <utility>
19 :
20 : #include "gmock/gmock.h"
21 : #include "gtest/gtest.h"
22 : #include "syzygy/agent/asan/unittest_util.h"
23 :
24 : namespace agent {
25 : namespace asan {
26 :
27 : namespace {
28 :
29 : class DummyMemoryNotifier : public MemoryNotifierInterface {
30 : public:
31 : typedef std::pair<const void*, size_t> MemoryRange;
32 : typedef std::set<MemoryRange> MemoryRangeSet;
33 :
34 E : DummyMemoryNotifier()
35 E : : internal_used_(0), future_used_(0) {
36 E : }
37 :
38 E : virtual ~DummyMemoryNotifier() { }
39 :
40 E : virtual void NotifyInternalUse(const void* address, size_t size) {
41 E : MemoryRange range(address, size);
42 E : ASSERT_TRUE(internal_.find(range) == internal_.end());
43 E : ASSERT_TRUE(future_.find(range) == future_.end());
44 E : internal_used_ += size;
45 E : internal_.insert(range);
46 E : }
47 :
48 i : virtual void NotifyFutureHeapUse(const void* address, size_t size) {
49 i : MemoryRange range(address, size);
50 i : ASSERT_TRUE(internal_.find(range) == internal_.end());
51 i : ASSERT_TRUE(future_.find(range) == future_.end());
52 i : future_used_ += size;
53 i : future_.insert(range);
54 i : }
55 :
56 E : virtual void NotifyReturnedToOS(const void* address, size_t size) {
57 E : MemoryRange range(address, size);
58 E : size_t count_internal = internal_.erase(range);
59 E : size_t count_future = future_.erase(range);
60 E : ASSERT_EQ(1u, count_internal + count_future);
61 E : if (count_internal) {
62 E : internal_used_ -= size;
63 E : ASSERT_LE(0u, internal_used_);
64 : }
65 E : if (count_future) {
66 i : future_used_ -= size;
67 i : ASSERT_LE(0u, future_used_);
68 : }
69 E : }
70 :
71 : size_t internal_used_;
72 : size_t future_used_;
73 : MemoryRangeSet internal_;
74 : MemoryRangeSet future_;
75 : };
76 :
77 : typedef DummyMemoryNotifier::MemoryRange MemoryRange;
78 :
79 : } // namespace
80 :
81 E : TEST(MemoryNotifierAllocatorTest, ConstructorsWorkAsExpected) {
82 E : DummyMemoryNotifier n;
83 :
84 E : MemoryNotifierAllocator<uint32_t> a1(&n);
85 E : EXPECT_EQ(&n, a1.memory_notifier());
86 :
87 E : MemoryNotifierAllocator<uint32_t> a2(a1);
88 E : EXPECT_EQ(&n, a2.memory_notifier());
89 :
90 E : MemoryNotifierAllocator<uint16_t> a3(a1);
91 E : EXPECT_EQ(&n, a3.memory_notifier());
92 E : }
93 :
94 E : TEST(MemoryNotifierAllocatorTest, NotifiesInternalUse) {
95 E : DummyMemoryNotifier n;
96 E : MemoryNotifierAllocator<uint32_t> a1(&n);
97 E : MemoryNotifierAllocator<uint16_t> a2(a1);
98 :
99 E : EXPECT_EQ(0u, n.internal_.size());
100 E : EXPECT_EQ(0u, n.future_.size());
101 :
102 E : uint32_t* ui32 = a1.allocate(10);
103 E : EXPECT_EQ(1u, n.internal_.size());
104 E : EXPECT_EQ(0u, n.future_.size());
105 E : EXPECT_THAT(n.internal_,
106 E : testing::UnorderedElementsAre(MemoryRange(ui32, 40)));
107 :
108 E : uint16_t* ui16 = a2.allocate(8);
109 E : EXPECT_EQ(2u, n.internal_.size());
110 E : EXPECT_EQ(0u, n.future_.size());
111 E : EXPECT_THAT(n.internal_,
112 : testing::UnorderedElementsAre(MemoryRange(ui32, 40),
113 E : MemoryRange(ui16, 16)));
114 :
115 E : a1.deallocate(ui32, 10);
116 E : EXPECT_EQ(1u, n.internal_.size());
117 E : EXPECT_EQ(0u, n.future_.size());
118 E : EXPECT_THAT(n.internal_,
119 E : testing::UnorderedElementsAre(MemoryRange(ui16, 16)));
120 :
121 E : a2.deallocate(ui16, 8);
122 E : EXPECT_EQ(0u, n.internal_.size());
123 E : EXPECT_EQ(0u, n.future_.size());
124 E : }
125 :
126 E : TEST(MemoryNotifierAllocatorTest, StlContainerStressTest) {
127 E : DummyMemoryNotifier n;
128 : typedef std::set<uint32_t, std::less<uint32_t>,
129 : MemoryNotifierAllocator<uint32_t>> DummySet;
130 E : MemoryNotifierAllocator<uint32_t> a(&n);
131 E : DummySet s(a);
132 :
133 E : for (size_t i = 0; i < 10000; ++i) {
134 E : uint32_t j = ::rand() % 2000;
135 E : s.insert(j);
136 E : }
137 :
138 E : for (size_t i = 0; i < 1500; ++i) {
139 E : uint32_t j = ::rand() % 2000;
140 E : s.erase(j);
141 E : }
142 :
143 E : s.clear();
144 E : }
145 :
146 E : TEST(HeapAllocatorTest, Allocate) {
147 E : testing::MockHeap h;
148 E : HeapAllocator<uint32_t> a(&h);
149 E : EXPECT_CALL(h, Allocate(sizeof(uint32_t)));
150 E : a.allocate(1, NULL);
151 E : }
152 :
153 E : TEST(HeapAllocatorTest, Deallocate) {
154 E : testing::MockHeap h;
155 E : HeapAllocator<uint32_t> a(&h);
156 E : EXPECT_CALL(h, Free(reinterpret_cast<void*>(0x12345678)));
157 E : a.deallocate(reinterpret_cast<uint32_t*>(0x12345678), 1);
158 E : }
159 :
160 E : TEST(HeapAllocatorTest, StlContainerStressTest) {
161 E : testing::DummyHeap h;
162 : typedef std::set<uint32_t, std::less<uint32_t>, HeapAllocator<uint32_t>>
163 : DummySet;
164 E : HeapAllocator<uint32_t> a(&h);
165 E : DummySet s(a);
166 :
167 E : for (size_t i = 0; i < 10000; ++i) {
168 E : uint32_t j = ::rand() % 2000;
169 E : s.insert(j);
170 E : }
171 :
172 E : for (size_t i = 0; i < 1500; ++i) {
173 E : uint32_t j = ::rand() % 2000;
174 E : s.erase(j);
175 E : }
176 :
177 E : s.clear();
178 E : }
179 :
180 : } // namespace asan
181 : } // namespace agent
|