OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/budget_service/budget_database.h" | 5 #include "chrome/browser/budget_service/budget_database.h" |
6 | 6 |
7 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
| 8 #include "base/test/simple_test_clock.h" |
8 #include "base/threading/thread_task_runner_handle.h" | 9 #include "base/threading/thread_task_runner_handle.h" |
9 #include "chrome/browser/budget_service/budget.pb.h" | 10 #include "chrome/browser/budget_service/budget.pb.h" |
10 #include "chrome/test/base/testing_profile.h" | 11 #include "chrome/test/base/testing_profile.h" |
11 #include "components/leveldb_proto/proto_database.h" | 12 #include "components/leveldb_proto/proto_database.h" |
12 #include "components/leveldb_proto/proto_database_impl.h" | 13 #include "components/leveldb_proto/proto_database_impl.h" |
13 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
14 #include "content/public/test/test_browser_thread_bundle.h" | 15 #include "content/public/test/test_browser_thread_bundle.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
16 | 17 |
17 namespace { | 18 namespace { |
18 | 19 |
19 const double kDefaultDebt = -0.72; | |
20 const double kDefaultBudget1 = 1.234; | 20 const double kDefaultBudget1 = 1.234; |
21 const double kDefaultBudget2 = 2.345; | 21 const double kDefaultBudget2 = 2.345; |
22 const double kDefaultExpiration = 3600000000; | 22 const double kDefaultExpirationInHours = 72; |
23 | 23 |
24 const char kTestOrigin[] = "https://example.com"; | 24 const char kTestOrigin[] = "https://example.com"; |
25 | 25 |
| 26 } // namespace |
| 27 |
26 class BudgetDatabaseTest : public ::testing::Test { | 28 class BudgetDatabaseTest : public ::testing::Test { |
27 public: | 29 public: |
28 BudgetDatabaseTest() | 30 BudgetDatabaseTest() |
29 : success_(false), | 31 : success_(false), |
30 db_(profile_.GetPath().Append(FILE_PATH_LITERAL("BudgetDabase")), | 32 db_(profile_.GetPath().Append(FILE_PATH_LITERAL("BudgetDabase")), |
31 base::ThreadTaskRunnerHandle::Get()) {} | 33 base::ThreadTaskRunnerHandle::Get()) {} |
32 | 34 |
33 void SetBudgetComplete(base::Closure run_loop_closure, bool success) { | 35 // The BudgetDatabase assumes that a budget will always be queried before it |
| 36 // is written to. Use GetBudgetDetails() to pre-populate the cache. |
| 37 void SetUp() override { GetBudgetDetails(); } |
| 38 |
| 39 void AddBudgetComplete(base::Closure run_loop_closure, bool success) { |
34 success_ = success; | 40 success_ = success; |
35 run_loop_closure.Run(); | 41 run_loop_closure.Run(); |
36 } | 42 } |
37 | 43 |
38 // Set up basic default values. | 44 // Add budget to the origin. |
39 bool SetBudgetWithDefaultValues() { | 45 bool AddBudget(const GURL& origin, double amount) { |
40 budget_service::Budget budget; | |
41 budget.set_debt(kDefaultDebt); | |
42 | |
43 // Create two chunks and give them default values. | |
44 budget_service::BudgetChunk* budget_chunk = budget.add_budget(); | |
45 budget_chunk->set_amount(kDefaultBudget1); | |
46 budget_chunk->set_expiration(kDefaultExpiration); | |
47 budget_chunk = budget.add_budget(); | |
48 budget_chunk->set_amount(kDefaultBudget2); | |
49 budget_chunk->set_expiration(kDefaultExpiration + 1); | |
50 | |
51 base::RunLoop run_loop; | 46 base::RunLoop run_loop; |
52 db_.SetValue(GURL(kTestOrigin), budget, | 47 db_.AddBudget(origin, amount, |
53 base::Bind(&BudgetDatabaseTest::SetBudgetComplete, | 48 base::Bind(&BudgetDatabaseTest::AddBudgetComplete, |
54 base::Unretained(this), run_loop.QuitClosure())); | 49 base::Unretained(this), run_loop.QuitClosure())); |
55 run_loop.Run(); | 50 run_loop.Run(); |
56 | |
57 return success_; | 51 return success_; |
58 } | 52 } |
59 | 53 |
60 void GetBudgetComplete(base::Closure run_loop_closure, | |
61 bool success, | |
62 std::unique_ptr<budget_service::Budget> budget) { | |
63 budget_ = std::move(budget); | |
64 success_ = success; | |
65 run_loop_closure.Run(); | |
66 } | |
67 | |
68 // Excercise the very basic get method. | |
69 std::unique_ptr<budget_service::Budget> GetBudget() { | |
70 base::RunLoop run_loop; | |
71 db_.GetValue(GURL(kTestOrigin), | |
72 base::Bind(&BudgetDatabaseTest::GetBudgetComplete, | |
73 base::Unretained(this), run_loop.QuitClosure())); | |
74 run_loop.Run(); | |
75 return std::move(budget_); | |
76 } | |
77 | |
78 void GetBudgetDetailsComplete( | 54 void GetBudgetDetailsComplete( |
79 base::Closure run_loop_closure, | 55 base::Closure run_loop_closure, |
80 bool success, | 56 bool success, |
81 double debt, | 57 double debt, |
82 const BudgetDatabase::BudgetExpectation& expectation) { | 58 const BudgetDatabase::BudgetExpectation& expectation) { |
83 success_ = success; | 59 success_ = success; |
84 debt_ = debt; | 60 debt_ = debt; |
85 expectation_ = expectation; | 61 expectation_ = expectation; |
86 run_loop_closure.Run(); | 62 run_loop_closure.Run(); |
87 } | 63 } |
88 | 64 |
| 65 // Get the full set of budget expectations for the origin. |
89 void GetBudgetDetails() { | 66 void GetBudgetDetails() { |
90 base::RunLoop run_loop; | 67 base::RunLoop run_loop; |
91 db_.GetBudgetDetails( | 68 db_.GetBudgetDetails( |
92 GURL(kTestOrigin), | 69 GURL(kTestOrigin), |
93 base::Bind(&BudgetDatabaseTest::GetBudgetDetailsComplete, | 70 base::Bind(&BudgetDatabaseTest::GetBudgetDetailsComplete, |
94 base::Unretained(this), run_loop.QuitClosure())); | 71 base::Unretained(this), run_loop.QuitClosure())); |
95 run_loop.Run(); | 72 run_loop.Run(); |
96 } | 73 } |
97 | 74 |
98 Profile* profile() { return &profile_; } | 75 Profile* profile() { return &profile_; } |
99 const BudgetDatabase::BudgetExpectation& expectation() { | 76 const BudgetDatabase::BudgetExpectation& expectation() { |
100 return expectation_; | 77 return expectation_; |
101 } | 78 } |
102 | 79 |
| 80 // Setup a test clock so that the tests can control time. |
| 81 base::SimpleTestClock* SetClockForTesting() { |
| 82 base::SimpleTestClock* clock = new base::SimpleTestClock(); |
| 83 db_.SetClockForTesting(base::WrapUnique(clock)); |
| 84 return clock; |
| 85 } |
| 86 |
103 protected: | 87 protected: |
104 bool success_; | 88 bool success_; |
105 | 89 |
106 private: | 90 private: |
107 content::TestBrowserThreadBundle thread_bundle_; | 91 content::TestBrowserThreadBundle thread_bundle_; |
108 std::unique_ptr<budget_service::Budget> budget_; | 92 std::unique_ptr<budget_service::Budget> budget_; |
109 TestingProfile profile_; | 93 TestingProfile profile_; |
110 BudgetDatabase db_; | 94 BudgetDatabase db_; |
111 double debt_ = 0; | 95 double debt_ = 0; |
112 BudgetDatabase::BudgetExpectation expectation_; | 96 BudgetDatabase::BudgetExpectation expectation_; |
113 }; | 97 }; |
114 | 98 |
115 TEST_F(BudgetDatabaseTest, ReadAndWriteTest) { | 99 TEST_F(BudgetDatabaseTest, ReadAndWriteTest) { |
116 ASSERT_TRUE(SetBudgetWithDefaultValues()); | 100 const GURL origin(kTestOrigin); |
117 std::unique_ptr<budget_service::Budget> b = GetBudget(); | 101 base::SimpleTestClock* clock = SetClockForTesting(); |
| 102 base::TimeDelta expiration( |
| 103 base::TimeDelta::FromHours(kDefaultExpirationInHours)); |
| 104 base::Time expiration_time = clock->Now() + expiration; |
118 | 105 |
119 ASSERT_TRUE(success_); | 106 // Add two budget chunks with different expirations (default expiration and |
120 EXPECT_EQ(kDefaultDebt, b->debt()); | 107 // default expiration + 1 day). |
121 EXPECT_EQ(kDefaultBudget1, b->budget(0).amount()); | 108 ASSERT_TRUE(AddBudget(origin, kDefaultBudget1)); |
122 EXPECT_EQ(kDefaultBudget2, b->budget(1).amount()); | 109 clock->Advance(base::TimeDelta::FromDays(1)); |
123 EXPECT_EQ(kDefaultExpiration, b->budget(0).expiration()); | 110 ASSERT_TRUE(AddBudget(origin, kDefaultBudget2)); |
124 } | |
125 | 111 |
126 TEST_F(BudgetDatabaseTest, BudgetDetailsTest) { | 112 // Get the budget. |
127 ASSERT_TRUE(SetBudgetWithDefaultValues()); | |
128 GetBudgetDetails(); | 113 GetBudgetDetails(); |
129 | 114 |
130 // Get the expectation and validate it. | 115 // Get the expectation and validate it. |
131 const auto& expected_value = expectation(); | 116 const auto& expected_value = expectation(); |
132 ASSERT_TRUE(success_); | 117 ASSERT_TRUE(success_); |
133 ASSERT_EQ(3U, expected_value.size()); | 118 ASSERT_EQ(3U, expected_value.size()); |
134 | 119 |
135 // Make sure that the correct data is returned. | 120 // Make sure that the correct data is returned. |
136 auto iter = expected_value.begin(); | 121 auto iter = expected_value.begin(); |
137 | 122 |
138 // First value should be [total_budget, now] | 123 // First value should be [total_budget, now] |
139 EXPECT_EQ(kDefaultBudget1 + kDefaultBudget2, iter->first); | 124 EXPECT_EQ(kDefaultBudget1 + kDefaultBudget2, iter->first); |
140 // TODO(harkness): This will be "now" in the final version. For now, it's | 125 // TODO(harkness): This will be "now" in the final version. For now, it's |
141 // just 0.0. | 126 // just 0. |
142 EXPECT_EQ(0, iter->second); | 127 EXPECT_EQ(0, iter->second); |
143 | 128 |
144 // The next value should be the budget after the first chunk expires. | 129 // The next value should be the budget after the first chunk expires. |
145 iter++; | 130 iter++; |
146 EXPECT_EQ(kDefaultBudget2, iter->first); | 131 EXPECT_EQ(kDefaultBudget2, iter->first); |
147 EXPECT_EQ(kDefaultExpiration, iter->second); | 132 EXPECT_EQ(expiration_time.ToInternalValue(), iter->second); |
148 | 133 |
149 // The final value gives the budget of 0.0 after the second chunk expires. | 134 // The final value gives the budget of 0.0 after the second chunk expires. |
| 135 expiration_time += base::TimeDelta::FromDays(1); |
150 iter++; | 136 iter++; |
151 EXPECT_EQ(0, iter->first); | 137 EXPECT_EQ(0, iter->first); |
152 EXPECT_EQ(kDefaultExpiration + 1, iter->second); | 138 EXPECT_EQ(expiration_time.ToInternalValue(), iter->second); |
153 } | 139 } |
154 | |
155 } // namespace | |
OLD | NEW |