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/quarantines/size_limited_quarantine.h"
16 :
17 : #include "gmock/gmock.h"
18 : #include "gtest/gtest.h"
19 :
20 : namespace agent {
21 : namespace asan {
22 : namespace quarantines {
23 :
24 : // A dummy lightweight object for storing in a quarantine under test.
25 : // This is outside of the anonymous namespace to keep gmock happy.
26 : struct DummyObject {
27 : size_t size;
28 :
29 : DummyObject() : size(0) { }
30 E : explicit DummyObject(size_t size) : size(size) { }
31 E : DummyObject(const DummyObject& o) : size(o.size) { } // NOLINT
32 : };
33 :
34 E : std::ostream& operator<<(std::ostream& os, const DummyObject& o) {
35 E : os << "DummyObject(size=" << o.size << ")";
36 E : return os;
37 E : }
38 :
39 E : bool operator==(const DummyObject& o1, const DummyObject& o2) {
40 E : return o1.size == o2.size;
41 E : }
42 :
43 : namespace {
44 :
45 : struct DummyObjectSizeFunctor {
46 E : size_t operator()(const DummyObject& o) {
47 E : return o.size;
48 E : }
49 : };
50 :
51 : typedef std::vector<DummyObject> DummyObjectVector;
52 :
53 : class TestQuarantine
54 : : public SizeLimitedQuarantineImpl<DummyObject, DummyObjectSizeFunctor> {
55 : public:
56 E : TestQuarantine() { }
57 E : virtual ~TestQuarantine() { }
58 :
59 : protected:
60 : // @name SizeLimitedQuarantine interface.
61 : // @{
62 E : bool PushImpl(const DummyObject& o) {
63 E : objects_.push_back(o);
64 E : return true;
65 E : }
66 :
67 E : bool PopImpl(DummyObject* o) {
68 E : DCHECK_NE(static_cast<DummyObject*>(NULL), o);
69 E : DCHECK(!objects_.empty());
70 E : *o = objects_.back();
71 E : objects_.pop_back();
72 E : return true;
73 E : }
74 :
75 E : void EmptyImpl(DummyObjectVector* os) {
76 E : DCHECK_NE(static_cast<DummyObjectVector*>(NULL), os);
77 E : os->swap(objects_);
78 E : }
79 :
80 i : size_t GetLockIdImpl(const DummyObject& o) { return 0; }
81 i : void LockImpl(size_t lock_id) { };
82 i : void UnlockImpl(size_t lock_id) { };
83 : // @}
84 :
85 : DummyObjectVector objects_;
86 : };
87 :
88 : } // namespace
89 :
90 E : TEST(SizeLimitedQuarantineTest, ConstructorsSettersAndGetters) {
91 E : TestQuarantine q;
92 E : EXPECT_EQ(TestQuarantine::kUnboundedSize, q.max_object_size());
93 E : EXPECT_EQ(TestQuarantine::kUnboundedSize, q.max_quarantine_size());
94 E : EXPECT_EQ(0u, q.size());
95 E : EXPECT_EQ(0u, q.GetCount());
96 :
97 E : q.set_max_object_size(100);
98 E : EXPECT_EQ(100u, q.max_object_size());
99 :
100 E : q.set_max_quarantine_size(1000);
101 E : EXPECT_EQ(1000u, q.max_quarantine_size());
102 E : }
103 :
104 E : TEST(SizeLimitedQuarantineTest, NoSizeLimit) {
105 E : TestQuarantine q;
106 E : for (size_t i = 0; i < 1000; ++i) {
107 E : q.Push(DummyObject(i * 1000));
108 E : EXPECT_EQ(i + 1, q.GetCount());
109 E : }
110 E : }
111 :
112 E : TEST(SizeLimitedQuarantineTest, MaxObjectSizeEnforced) {
113 E : TestQuarantine q;
114 E : q.set_max_object_size(10);
115 E : for (size_t i = 1; i < 20; ++i) {
116 E : if (i <= 10) {
117 E : EXPECT_TRUE(q.Push(DummyObject(i)));
118 E : EXPECT_EQ(i, q.GetCount());
119 E : } else {
120 E : EXPECT_FALSE(q.Push(DummyObject(i)));
121 E : EXPECT_EQ(10u, q.GetCount());
122 : }
123 E : }
124 E : }
125 :
126 E : TEST(SizeLimitedQuarantineTest, InvariantEnforced) {
127 E : TestQuarantine q;
128 E : DummyObject o(10);
129 :
130 E : q.set_max_quarantine_size(15);
131 :
132 E : EXPECT_TRUE(q.Push(o));
133 E : EXPECT_EQ(10u, q.size());
134 E : EXPECT_EQ(1u, q.GetCount());
135 :
136 E : EXPECT_FALSE(q.Pop(&o));
137 E : EXPECT_EQ(10u, q.size());
138 E : EXPECT_EQ(1u, q.GetCount());
139 :
140 E : EXPECT_TRUE(q.Push(o));
141 E : EXPECT_EQ(20u, q.size());
142 E : EXPECT_EQ(2u, q.GetCount());
143 :
144 E : EXPECT_TRUE(q.Pop(&o));
145 E : EXPECT_EQ(10u, q.size());
146 E : EXPECT_EQ(1u, q.GetCount());
147 :
148 E : EXPECT_FALSE(q.Pop(&o));
149 E : EXPECT_EQ(10u, q.size());
150 E : EXPECT_EQ(1u, q.GetCount());
151 E : }
152 :
153 E : TEST(SizeLimitedQuarantineTest, EmptyWorks) {
154 E : TestQuarantine q;
155 E : DummyObject o(10);
156 :
157 E : EXPECT_TRUE(q.Push(o));
158 E : EXPECT_TRUE(q.Push(o));
159 E : EXPECT_TRUE(q.Push(o));
160 E : EXPECT_EQ(30u, q.size());
161 E : EXPECT_EQ(3u, q.GetCount());
162 :
163 E : DummyObjectVector os;
164 E : q.Empty(&os);
165 :
166 E : EXPECT_THAT(os, testing::ElementsAre(o, o, o));
167 E : }
168 :
169 : } // namespace quarantines
170 : } // namespace asan
171 : } // namespace agent
|