Update {virtual,override,final} to follow C++11 style.
[chromium-blink-merge.git] / extensions / browser / quota_service_unittest.cc
blob193aa34dd5f23f4964547f65ec7e15b2d6408816
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/message_loop/message_loop.h"
6 #include "base/process/process.h"
7 #include "base/stl_util.h"
8 #include "base/strings/string_util.h"
9 #include "content/public/test/test_browser_thread.h"
10 #include "extensions/browser/extension_function.h"
11 #include "extensions/browser/quota_service.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using base::TimeDelta;
15 using base::TimeTicks;
16 using content::BrowserThread;
18 namespace extensions {
20 typedef QuotaLimitHeuristic::Bucket Bucket;
21 typedef QuotaLimitHeuristic::Config Config;
22 typedef QuotaLimitHeuristic::BucketList BucketList;
23 typedef QuotaService::TimedLimit TimedLimit;
25 namespace {
27 const char kGenericName[] = "name";
28 const Config kFrozenConfig = {0, TimeDelta::FromDays(0)};
29 const Config k2PerMinute = {2, TimeDelta::FromMinutes(1)};
30 const Config k20PerHour = {20, TimeDelta::FromHours(1)};
31 const TimeTicks kStartTime = TimeTicks();
32 const TimeTicks k1MinuteAfterStart = kStartTime + TimeDelta::FromMinutes(1);
34 class Mapper : public QuotaLimitHeuristic::BucketMapper {
35 public:
36 Mapper() {}
37 ~Mapper() override { STLDeleteValues(&buckets_); }
38 void GetBucketsForArgs(const base::ListValue* args,
39 BucketList* buckets) override {
40 for (size_t i = 0; i < args->GetSize(); i++) {
41 int id;
42 ASSERT_TRUE(args->GetInteger(i, &id));
43 if (buckets_.find(id) == buckets_.end())
44 buckets_[id] = new Bucket();
45 buckets->push_back(buckets_[id]);
49 private:
50 typedef std::map<int, Bucket*> BucketMap;
51 BucketMap buckets_;
52 DISALLOW_COPY_AND_ASSIGN(Mapper);
55 class MockMapper : public QuotaLimitHeuristic::BucketMapper {
56 public:
57 void GetBucketsForArgs(const base::ListValue* args,
58 BucketList* buckets) override {}
61 class MockFunction : public ExtensionFunction {
62 public:
63 explicit MockFunction(const std::string& name) { set_name(name); }
65 void SetArgs(const base::ListValue* args) override {}
66 std::string GetError() const override { return std::string(); }
67 void SetError(const std::string& error) override {}
68 void Destruct() const override { delete this; }
69 ResponseAction Run() override { return RespondLater(); }
70 void SendResponse(bool) override {}
72 protected:
73 ~MockFunction() override {}
76 class TimedLimitMockFunction : public MockFunction {
77 public:
78 explicit TimedLimitMockFunction(const std::string& name)
79 : MockFunction(name) {}
80 void GetQuotaLimitHeuristics(
81 QuotaLimitHeuristics* heuristics) const override {
82 heuristics->push_back(
83 new TimedLimit(k2PerMinute, new Mapper(), kGenericName));
86 private:
87 ~TimedLimitMockFunction() override {}
90 class FrozenMockFunction : public MockFunction {
91 public:
92 explicit FrozenMockFunction(const std::string& name) : MockFunction(name) {}
93 void GetQuotaLimitHeuristics(
94 QuotaLimitHeuristics* heuristics) const override {
95 heuristics->push_back(
96 new TimedLimit(kFrozenConfig, new Mapper(), kGenericName));
99 private:
100 ~FrozenMockFunction() override {}
102 } // namespace
104 class QuotaServiceTest : public testing::Test {
105 public:
106 QuotaServiceTest()
107 : extension_a_("a"),
108 extension_b_("b"),
109 extension_c_("c"),
110 loop_(),
111 ui_thread_(BrowserThread::UI, &loop_) {}
112 void SetUp() override { service_.reset(new QuotaService()); }
113 void TearDown() override {
114 loop_.RunUntilIdle();
115 service_.reset();
118 protected:
119 std::string extension_a_;
120 std::string extension_b_;
121 std::string extension_c_;
122 scoped_ptr<QuotaService> service_;
123 base::MessageLoop loop_;
124 content::TestBrowserThread ui_thread_;
127 class QuotaLimitHeuristicTest : public testing::Test {
128 public:
129 static void DoMoreThan2PerMinuteFor5Minutes(const TimeTicks& start_time,
130 QuotaLimitHeuristic* lim,
131 Bucket* b,
132 int an_unexhausted_minute) {
133 for (int i = 0; i < 5; i++) {
134 // Perform one operation in each minute.
135 int m = i * 60;
136 EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(10 + m)));
137 EXPECT_TRUE(b->has_tokens());
139 if (i == an_unexhausted_minute)
140 continue; // Don't exhaust all tokens this minute.
142 EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(15 + m)));
143 EXPECT_FALSE(b->has_tokens());
145 // These are OK because we haven't exhausted all buckets.
146 EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(20 + m)));
147 EXPECT_FALSE(b->has_tokens());
148 EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(50 + m)));
149 EXPECT_FALSE(b->has_tokens());
154 TEST_F(QuotaLimitHeuristicTest, Timed) {
155 TimedLimit lim(k2PerMinute, new MockMapper(), kGenericName);
156 Bucket b;
158 b.Reset(k2PerMinute, kStartTime);
159 EXPECT_TRUE(lim.Apply(&b, kStartTime));
160 EXPECT_TRUE(b.has_tokens());
161 EXPECT_TRUE(lim.Apply(&b, kStartTime + TimeDelta::FromSeconds(30)));
162 EXPECT_FALSE(b.has_tokens());
163 EXPECT_FALSE(lim.Apply(&b, k1MinuteAfterStart));
165 b.Reset(k2PerMinute, kStartTime);
166 EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart - TimeDelta::FromSeconds(1)));
167 EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart));
168 EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart + TimeDelta::FromSeconds(1)));
169 EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart + TimeDelta::FromSeconds(2)));
170 EXPECT_FALSE(lim.Apply(&b, k1MinuteAfterStart + TimeDelta::FromSeconds(3)));
173 TEST_F(QuotaServiceTest, NoHeuristic) {
174 scoped_refptr<MockFunction> f(new MockFunction("foo"));
175 base::ListValue args;
176 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &args, kStartTime));
179 TEST_F(QuotaServiceTest, FrozenHeuristic) {
180 scoped_refptr<MockFunction> f(new FrozenMockFunction("foo"));
181 base::ListValue args;
182 args.Append(new base::FundamentalValue(1));
183 EXPECT_NE("", service_->Assess(extension_a_, f.get(), &args, kStartTime));
186 TEST_F(QuotaServiceTest, SingleHeuristic) {
187 scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
188 base::ListValue args;
189 args.Append(new base::FundamentalValue(1));
190 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &args, kStartTime));
191 EXPECT_EQ("",
192 service_->Assess(extension_a_,
193 f.get(),
194 &args,
195 kStartTime + TimeDelta::FromSeconds(10)));
196 EXPECT_NE("",
197 service_->Assess(extension_a_,
198 f.get(),
199 &args,
200 kStartTime + TimeDelta::FromSeconds(15)));
202 base::ListValue args2;
203 args2.Append(new base::FundamentalValue(1));
204 args2.Append(new base::FundamentalValue(2));
205 EXPECT_EQ("", service_->Assess(extension_b_, f.get(), &args2, kStartTime));
206 EXPECT_EQ("",
207 service_->Assess(extension_b_,
208 f.get(),
209 &args2,
210 kStartTime + TimeDelta::FromSeconds(10)));
212 TimeDelta peace = TimeDelta::FromMinutes(30);
213 EXPECT_EQ("",
214 service_->Assess(extension_b_, f.get(), &args, kStartTime + peace));
215 EXPECT_EQ("",
216 service_->Assess(extension_b_,
217 f.get(),
218 &args,
219 kStartTime + peace + TimeDelta::FromSeconds(10)));
220 EXPECT_NE("",
221 service_->Assess(extension_b_,
222 f.get(),
223 &args2,
224 kStartTime + peace + TimeDelta::FromSeconds(15)));
226 // Test that items are independent.
227 base::ListValue args3;
228 args3.Append(new base::FundamentalValue(3));
229 EXPECT_EQ("", service_->Assess(extension_c_, f.get(), &args, kStartTime));
230 EXPECT_EQ("",
231 service_->Assess(extension_c_,
232 f.get(),
233 &args3,
234 kStartTime + TimeDelta::FromSeconds(10)));
235 EXPECT_EQ("",
236 service_->Assess(extension_c_,
237 f.get(),
238 &args,
239 kStartTime + TimeDelta::FromSeconds(15)));
240 EXPECT_EQ("",
241 service_->Assess(extension_c_,
242 f.get(),
243 &args3,
244 kStartTime + TimeDelta::FromSeconds(20)));
245 EXPECT_NE("",
246 service_->Assess(extension_c_,
247 f.get(),
248 &args,
249 kStartTime + TimeDelta::FromSeconds(25)));
250 EXPECT_NE("",
251 service_->Assess(extension_c_,
252 f.get(),
253 &args3,
254 kStartTime + TimeDelta::FromSeconds(30)));
257 TEST_F(QuotaServiceTest, MultipleFunctionsDontInterfere) {
258 scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
259 scoped_refptr<MockFunction> g(new TimedLimitMockFunction("bar"));
261 base::ListValue args_f;
262 base::ListValue args_g;
263 args_f.Append(new base::FundamentalValue(1));
264 args_g.Append(new base::FundamentalValue(2));
266 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &args_f, kStartTime));
267 EXPECT_EQ("", service_->Assess(extension_a_, g.get(), &args_g, kStartTime));
268 EXPECT_EQ("",
269 service_->Assess(extension_a_,
270 f.get(),
271 &args_f,
272 kStartTime + TimeDelta::FromSeconds(10)));
273 EXPECT_EQ("",
274 service_->Assess(extension_a_,
275 g.get(),
276 &args_g,
277 kStartTime + TimeDelta::FromSeconds(10)));
278 EXPECT_NE("",
279 service_->Assess(extension_a_,
280 f.get(),
281 &args_f,
282 kStartTime + TimeDelta::FromSeconds(15)));
283 EXPECT_NE("",
284 service_->Assess(extension_a_,
285 g.get(),
286 &args_g,
287 kStartTime + TimeDelta::FromSeconds(15)));
290 TEST_F(QuotaServiceTest, ViolatorsWillBeForgiven) {
291 scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
292 base::ListValue arg;
293 arg.Append(new base::FundamentalValue(1));
294 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &arg, kStartTime));
295 EXPECT_EQ("",
296 service_->Assess(extension_a_,
297 f.get(),
298 &arg,
299 kStartTime + TimeDelta::FromSeconds(10)));
300 EXPECT_NE("",
301 service_->Assess(extension_a_,
302 f.get(),
303 &arg,
304 kStartTime + TimeDelta::FromSeconds(15)));
306 // Waiting a while will give the extension access to the function again.
307 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &arg,
308 kStartTime + TimeDelta::FromDays(1)));
310 // And lose it again soon after.
311 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &arg,
312 kStartTime + TimeDelta::FromDays(1) +
313 TimeDelta::FromSeconds(10)));
314 EXPECT_NE("", service_->Assess(extension_a_, f.get(), &arg,
315 kStartTime + TimeDelta::FromDays(1) +
316 TimeDelta::FromSeconds(15)));
318 // Going further over quota should continue to fail within this time period,
319 // but still all restored later.
320 EXPECT_NE("", service_->Assess(extension_a_, f.get(), &arg,
321 kStartTime + TimeDelta::FromDays(1) +
322 TimeDelta::FromSeconds(20)));
323 EXPECT_NE("", service_->Assess(extension_a_, f.get(), &arg,
324 kStartTime + TimeDelta::FromDays(1) +
325 TimeDelta::FromSeconds(25)));
327 // Like now.
328 EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &arg,
329 kStartTime + TimeDelta::FromDays(2)));
332 } // namespace extensions