1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_function.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extensions_quota_service.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta; 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks; 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef QuotaLimitHeuristic::Bucket Bucket; 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef QuotaLimitHeuristic::Config Config; 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef QuotaLimitHeuristic::BucketList BucketList; 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef ExtensionsQuotaService::TimedLimit TimedLimit; 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef ExtensionsQuotaService::SustainedLimit SustainedLimit; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const Config kFrozenConfig = { 0, TimeDelta::FromDays(0) }; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const Config k2PerMinute = { 2, TimeDelta::FromMinutes(1) }; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const Config k20PerHour = { 20, TimeDelta::FromHours(1) }; 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const TimeTicks kStartTime = TimeTicks(); 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const TimeTicks k1MinuteAfterStart = 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromMinutes(1); 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Mapper : public QuotaLimitHeuristic::BucketMapper { 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Mapper() {} 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~Mapper() { STLDeleteValues(&buckets_); } 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < args->GetSize(); i++) { 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int id; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(args->GetInteger(i, &id)); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (buckets_.find(id) == buckets_.end()) 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buckets_[id] = new Bucket(); 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buckets->push_back(buckets_[id]); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::map<int, Bucket*> BucketMap; 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BucketMap buckets_; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(Mapper); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockMapper : public QuotaLimitHeuristic::BucketMapper { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {} 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockFunction : public ExtensionFunction { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit MockFunction(const std::string& name) { set_name(name); } 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SetArgs(const ListValue* args) {} 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual const std::string GetError() { return std::string(); } 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual const std::string GetResult() { return std::string(); } 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run() {} 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TimedLimitMockFunction : public MockFunction { 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit TimedLimitMockFunction(const std::string& name) 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : MockFunction(name) {} 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void GetQuotaLimitHeuristics( 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QuotaLimitHeuristics* heuristics) const { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch heuristics->push_back(new TimedLimit(k2PerMinute, new Mapper())); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ChainedLimitsMockFunction : public MockFunction { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit ChainedLimitsMockFunction(const std::string& name) 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : MockFunction(name) {} 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void GetQuotaLimitHeuristics( 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QuotaLimitHeuristics* heuristics) const { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No more than 2 per minute sustained over 5 minutes. 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch heuristics->push_back(new SustainedLimit(TimeDelta::FromMinutes(5), 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch k2PerMinute, new Mapper())); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No more than 20 per hour. 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch heuristics->push_back(new TimedLimit(k20PerHour, new Mapper())); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass FrozenMockFunction : public MockFunction { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit FrozenMockFunction(const std::string& name) : MockFunction(name) {} 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void GetQuotaLimitHeuristics( 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QuotaLimitHeuristics* heuristics) const { 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch heuristics->push_back(new TimedLimit(kFrozenConfig, new Mapper())); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ExtensionsQuotaServiceTest : public testing::Test { 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionsQuotaServiceTest() 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : extension_a_("a"), extension_b_("b"), extension_c_("c") {} 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SetUp() { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch service_.reset(new ExtensionsQuotaService()); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void TearDown() { 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch service_.reset(); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string extension_a_; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string extension_b_; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string extension_c_; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ExtensionsQuotaService> service_; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass QuotaLimitHeuristicTest : public testing::Test { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void DoMoreThan2PerMinuteFor5Minutes(const TimeTicks& start_time, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QuotaLimitHeuristic* lim, 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Bucket* b, 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int an_unexhausted_minute) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < 5; i++) { 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Perform one operation in each minute. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int m = i * 60; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(10 + m))); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(b->has_tokens()); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i == an_unexhausted_minute) 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // Don't exhaust all tokens this minute. 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(15 + m))); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(b->has_tokens()); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These are OK because we haven't exhausted all buckets. 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(20 + m))); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(b->has_tokens()); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim->Apply(b, start_time + TimeDelta::FromSeconds(50 + m))); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(b->has_tokens()); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(QuotaLimitHeuristicTest, Timed) { 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimedLimit lim(k2PerMinute, new MockMapper()); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Bucket b; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch b.Reset(k2PerMinute, kStartTime); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&b, kStartTime)); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(b.has_tokens()); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&b, kStartTime + TimeDelta::FromSeconds(30))); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(b.has_tokens()); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(lim.Apply(&b, k1MinuteAfterStart)); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch b.Reset(k2PerMinute, kStartTime); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart - TimeDelta::FromSeconds(1))); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart)); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart + TimeDelta::FromSeconds(1))); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&b, k1MinuteAfterStart + TimeDelta::FromSeconds(2))); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(lim.Apply(&b, k1MinuteAfterStart + TimeDelta::FromSeconds(3))); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(QuotaLimitHeuristicTest, Sustained) { 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SustainedLimit lim(TimeDelta::FromMinutes(5), k2PerMinute, new MockMapper()); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Bucket bucket; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bucket.Reset(k2PerMinute, kStartTime); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoMoreThan2PerMinuteFor5Minutes(kStartTime, &lim, &bucket, -1); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This straw breaks the camel's back. 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(lim.Apply(&bucket, kStartTime + TimeDelta::FromMinutes(6))); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The heuristic resets itself on a safe request. 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&bucket, kStartTime + TimeDelta::FromDays(1))); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do the same as above except don't exhaust final bucket. 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bucket.Reset(k2PerMinute, kStartTime); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoMoreThan2PerMinuteFor5Minutes(kStartTime, &lim, &bucket, -1); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&bucket, kStartTime + TimeDelta::FromMinutes(7))); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do the same as above except don't exhaust the 3rd (w.l.o.g) bucket. 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bucket.Reset(k2PerMinute, kStartTime); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoMoreThan2PerMinuteFor5Minutes(kStartTime, &lim, &bucket, 3); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the 3rd bucket were exhausted, this would fail (see first test). 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(lim.Apply(&bucket, kStartTime + TimeDelta::FromMinutes(6))); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ExtensionsQuotaServiceTest, NoHeuristic) { 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> f(new MockFunction("foo")); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &args, kStartTime)); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ExtensionsQuotaServiceTest, FrozenHeuristic) { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> f(new FrozenMockFunction("foo")); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(new FundamentalValue(1)); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, f, &args, kStartTime)); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ExtensionsQuotaServiceTest, SingleHeuristic) { 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo")); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(new FundamentalValue(1)); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &args, kStartTime)); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &args, 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10))); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, f, &args, 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(15))); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args2; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args2.Append(new FundamentalValue(1)); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args2.Append(new FundamentalValue(2)); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args2, kStartTime)); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args2, 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10))); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta peace = TimeDelta::FromMinutes(30); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args, kStartTime + peace)); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args, 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + peace + TimeDelta::FromSeconds(10))); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_b_, f, &args2, 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + peace + TimeDelta::FromSeconds(15))); 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Test that items are independent. 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args3; 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args3.Append(new FundamentalValue(3)); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_c_, f, &args, kStartTime)); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_c_, f, &args3, 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10))); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_c_, f, &args, 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(15))); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_c_, f, &args3, 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(20))); 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_c_, f, &args, 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(25))); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_c_, f, &args3, 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(30))); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ExtensionsQuotaServiceTest, ChainedHeuristics) { 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> f(new ChainedLimitsMockFunction("foo")); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(new FundamentalValue(1)); 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, test that the low limit can be avoided but the higher one is hit. 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // One event per minute for 20 minutes comes in under the sustained limit, 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but is equal to the timed limit. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < 20; i++) { 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &args, 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10 + i * 60))); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This will bring us to 21 events in an hour, which is a violation. 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, f, &args, 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromMinutes(30))); 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now, check that we can still hit the lower limit. 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < 5; i++) { 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args, 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10 + i * 60))); 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args, 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(15 + i * 60))); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_b_, f, &args, 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(20 + i * 60))); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_b_, f, &args, 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromMinutes(6))); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ExtensionsQuotaServiceTest, MultipleFunctionsDontInterfere) { 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo")); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> g(new TimedLimitMockFunction("bar")); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args_f; 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args_g; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args_f.Append(new FundamentalValue(1)); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args_g.Append(new FundamentalValue(2)); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &args_f, kStartTime)); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, g, &args_g, kStartTime)); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &args_f, 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10))); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, g, &args_g, 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10))); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, f, &args_f, 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(15))); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, g, &args_g, 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(15))); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ExtensionsQuotaServiceTest, ViolatorsWillBeViolators) { 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> f(new TimedLimitMockFunction("foo")); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<MockFunction> g(new TimedLimitMockFunction("bar")); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue arg; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch arg.Append(new FundamentalValue(1)); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &arg, kStartTime)); 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(service_->Assess(extension_a_, f, &arg, 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(10))); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, f, &arg, 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromSeconds(15))); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't allow this extension to use quota limited functions even if they 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // wait a while. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, f, &arg, 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromDays(1))); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(service_->Assess(extension_a_, g, &arg, 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartTime + TimeDelta::FromDays(1))); 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 305