Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / quota_service_unittest.cc
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.
4
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"
13
14 using base::TimeDelta;
15 using base::TimeTicks;
16 using content::BrowserThread;
17
18 namespace extensions {
19
20 typedef QuotaLimitHeuristic::Bucket Bucket;
21 typedef QuotaLimitHeuristic::Config Config;
22 typedef QuotaLimitHeuristic::BucketList BucketList;
23 typedef QuotaService::TimedLimit TimedLimit;
24
25 namespace {
26
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);
33
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]);
46     }
47   }
48
49  private:
50   typedef std::map<int, Bucket*> BucketMap;
51   BucketMap buckets_;
52   DISALLOW_COPY_AND_ASSIGN(Mapper);
53 };
54
55 class MockMapper : public QuotaLimitHeuristic::BucketMapper {
56  public:
57   void GetBucketsForArgs(const base::ListValue* args,
58                          BucketList* buckets) override {}
59 };
60
61 class MockFunction : public ExtensionFunction {
62  public:
63   explicit MockFunction(const std::string& name) { set_name(name); }
64
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 {}
71
72  protected:
73   ~MockFunction() override {}
74 };
75
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));
84   }
85
86  private:
87   ~TimedLimitMockFunction() override {}
88 };
89
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));
97   }
98
99  private:
100   ~FrozenMockFunction() override {}
101 };
102 }  // namespace
103
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();
116   }
117
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_;
125 };
126
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());
138
139       if (i == an_unexhausted_minute)
140         continue;  // Don't exhaust all tokens this minute.
141
142       EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(15 + m)));
143       EXPECT_FALSE(b->has_tokens());
144
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());
150     }
151   }
152 };
153
154 TEST_F(QuotaLimitHeuristicTest, Timed) {
155   TimedLimit lim(k2PerMinute, new MockMapper(), kGenericName);
156   Bucket b;
157
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));
164
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)));
171 }
172
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));
177 }
178
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));
184 }
185
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)));
201
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)));
211
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)));
225
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)));
255 }
256
257 TEST_F(QuotaServiceTest, MultipleFunctionsDontInterfere) {
258   scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo"));
259   scoped_refptr<MockFunction> g(new TimedLimitMockFunction("bar"));
260
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));
265
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)));
288 }
289
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)));
305
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)));
309
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)));
317
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)));
326
327   // Like now.
328   EXPECT_EQ("", service_->Assess(extension_a_, f.get(), &arg,
329                                  kStartTime + TimeDelta::FromDays(2)));
330 }
331
332 }  // namespace extensions