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 "base/basictypes.h"
21 : #include "gmock/gmock.h"
22 : #include "gtest/gtest.h"
23 : #include "syzygy/agent/asan/unittest_util.h"
24 :
25 : namespace agent {
26 : namespace asan {
27 :
28 : namespace {
29 :
30 : class DummyMemoryNotifier : public MemoryNotifierInterface {
31 : public:
32 : typedef std::pair<const void*, size_t> MemoryRange;
33 : typedef std::set<MemoryRange> MemoryRangeSet;
34 :
35 E : DummyMemoryNotifier()
36 : : internal_used_(0), future_used_(0) {
37 E : }
38 :
39 E : virtual ~DummyMemoryNotifier() { }
40 :
41 E : virtual void NotifyInternalUse(const void* address, size_t size) {
42 E : MemoryRange range(address, size);
43 E : ASSERT_TRUE(internal_.find(range) == internal_.end());
44 E : ASSERT_TRUE(future_.find(range) == future_.end());
45 E : internal_used_ += size;
46 E : internal_.insert(range);
47 E : }
48 :
49 i : virtual void NotifyFutureHeapUse(const void* address, size_t size) {
50 i : MemoryRange range(address, size);
51 i : ASSERT_TRUE(internal_.find(range) == internal_.end());
52 i : ASSERT_TRUE(future_.find(range) == future_.end());
53 i : future_used_ += size;
54 i : future_.insert(range);
55 i : }
56 :
57 E : virtual void NotifyReturnedToOS(const void* address, size_t size) {
58 E : MemoryRange range(address, size);
59 E : size_t count_internal = internal_.erase(range);
60 E : size_t count_future = future_.erase(range);
61 E : ASSERT_EQ(1u, count_internal + count_future);
62 E : if (count_internal) {
63 E : internal_used_ -= size;
64 E : ASSERT_LE(0u, internal_used_);
65 : }
66 E : if (count_future) {
67 i : future_used_ -= size;
68 i : ASSERT_LE(0u, future_used_);
69 : }
70 E : }
71 :
72 : size_t internal_used_;
73 : size_t future_used_;
74 : MemoryRangeSet internal_;
75 : MemoryRangeSet future_;
76 : };
77 :
78 : typedef DummyMemoryNotifier::MemoryRange MemoryRange;
79 :
80 : } // namespace
81 :
82 E : TEST(MemoryNotifierAllocatorTest, ConstructorsWorkAsExpected) {
83 E : DummyMemoryNotifier n;
84 :
85 E : MemoryNotifierAllocator<uint32> a1(&n);
86 E : EXPECT_EQ(&n, a1.memory_notifier());
87 :
88 E : MemoryNotifierAllocator<uint32> a2(a1);
89 E : EXPECT_EQ(&n, a2.memory_notifier());
90 :
91 E : MemoryNotifierAllocator<uint16> a3(a1);
92 E : EXPECT_EQ(&n, a3.memory_notifier());
93 E : }
94 :
95 E : TEST(MemoryNotifierAllocatorTest, NotifiesInternalUse) {
96 E : DummyMemoryNotifier n;
97 E : MemoryNotifierAllocator<uint32> a1(&n);
98 E : MemoryNotifierAllocator<uint16> a2(a1);
99 :
100 E : EXPECT_EQ(0u, n.internal_.size());
101 E : EXPECT_EQ(0u, n.future_.size());
102 :
103 E : uint32* ui32 = a1.allocate(10);
104 E : EXPECT_EQ(1u, n.internal_.size());
105 E : EXPECT_EQ(0u, n.future_.size());
106 : EXPECT_THAT(n.internal_,
107 E : testing::UnorderedElementsAre(MemoryRange(ui32, 40)));
108 :
109 E : uint16* ui16 = a2.allocate(8);
110 E : EXPECT_EQ(2u, n.internal_.size());
111 E : EXPECT_EQ(0u, n.future_.size());
112 : EXPECT_THAT(n.internal_,
113 : testing::UnorderedElementsAre(MemoryRange(ui32, 40),
114 E : MemoryRange(ui16, 16)));
115 :
116 E : a1.deallocate(ui32, 10);
117 E : EXPECT_EQ(1u, n.internal_.size());
118 E : EXPECT_EQ(0u, n.future_.size());
119 : EXPECT_THAT(n.internal_,
120 E : testing::UnorderedElementsAre(MemoryRange(ui16, 16)));
121 :
122 E : a2.deallocate(ui16, 8);
123 E : EXPECT_EQ(0u, n.internal_.size());
124 E : EXPECT_EQ(0u, n.future_.size());
125 E : }
126 :
127 E : TEST(MemoryNotifierAllocatorTest, StlContainerStressTest) {
128 E : DummyMemoryNotifier n;
129 : typedef std::set<uint32,
130 : std::less<uint32>,
131 : MemoryNotifierAllocator<uint32>> DummySet;
132 E : MemoryNotifierAllocator<uint32> a(&n);
133 E : DummySet s(a);
134 :
135 E : for (size_t i = 0; i < 10000; ++i) {
136 E : uint32 j = ::rand() % 2000;
137 E : s.insert(j);
138 E : }
139 :
140 E : for (size_t i = 0; i < 1500; ++i) {
141 E : uint32 j = ::rand() % 2000;
142 E : s.erase(j);
143 E : }
144 :
145 E : s.clear();
146 E : }
147 :
148 E : TEST(HeapAllocatorTest, Allocate) {
149 E : testing::MockHeap h;
150 E : HeapAllocator<uint32> a(&h);
151 E : EXPECT_CALL(h, Allocate(sizeof(uint32)));
152 E : a.allocate(1, NULL);
153 E : }
154 :
155 E : TEST(HeapAllocatorTest, Deallocate) {
156 E : testing::MockHeap h;
157 E : HeapAllocator<uint32> a(&h);
158 E : EXPECT_CALL(h, Free(reinterpret_cast<void*>(0x12345678)));
159 E : a.deallocate(reinterpret_cast<uint32*>(0x12345678), 1);
160 E : }
161 :
162 E : TEST(HeapAllocatorTest, StlContainerStressTest) {
163 E : testing::DummyHeap h;
164 : typedef std::set<uint32,
165 : std::less<uint32>,
166 : HeapAllocator<uint32>> DummySet;
167 E : HeapAllocator<uint32> a(&h);
168 E : DummySet s(a);
169 :
170 E : for (size_t i = 0; i < 10000; ++i) {
171 E : uint32 j = ::rand() % 2000;
172 E : s.insert(j);
173 E : }
174 :
175 E : for (size_t i = 0; i < 1500; ++i) {
176 E : uint32 j = ::rand() % 2000;
177 E : s.erase(j);
178 E : }
179 :
180 E : s.clear();
181 E : }
182 :
183 : } // namespace asan
184 : } // namespace agent
|