Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: components/password_manager/core/browser/affiliation_fetch_throttler_unittest.cc

Issue 807503002: Implement throttling logic for fetching affiliation information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@aff_database
Patch Set: Addressed first round of comments. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 <queue>
6
7 #include "base/callback.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/test/test_mock_time_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/time/tick_clock.h"
14 #include "base/time/time.h"
15 #include "components/password_manager/core/browser/affiliation_fetch_throttler.h "
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace password_manager {
20 namespace {
21
22 class MockAffiliationFetchThrottlerDelegate
23 : public testing::StrictMock<AffiliationFetchThrottlerDelegate> {
24 public:
25 MockAffiliationFetchThrottlerDelegate() {}
26
27 MOCK_METHOD0(OnCanSendNetworkRequest, bool());
28
29 private:
30 DISALLOW_COPY_AND_ASSIGN(MockAffiliationFetchThrottlerDelegate);
31 };
32
33 class MockNetworkChangeNotifier : public net::NetworkChangeNotifier {
34 public:
35 MockNetworkChangeNotifier() : connection_type_(CONNECTION_UNKNOWN) {}
36
37 void set_connection_type(ConnectionType connection_type) {
38 connection_type_ = connection_type;
39 NotifyObserversOfConnectionTypeChangeForTests(connection_type_);
40 }
41
42 ConnectionType GetCurrentConnectionType() const override {
43 return connection_type_;
44 }
45
46 private:
47 ConnectionType connection_type_;
48 };
49
50 } // namespace
51
52 class AffiliationFetchThrottlerTest : public testing::Test {
53 public:
54 AffiliationFetchThrottlerTest()
55 : network_change_notifier_(new MockNetworkChangeNotifier),
56 task_runner_(new base::TestMockTimeTaskRunner) {}
57 ~AffiliationFetchThrottlerTest() override {}
58
59 void SetUp() override {
60 policy_.reset(new AffiliationFetchThrottler(
61 &mock_delegate_, task_runner_, task_runner_->GetMockTickClock()));
62 }
63
64 void SimulateHasNetworkConnectivity(bool has_connectivity) {
65 network_change_notifier_->set_connection_type(
66 has_connectivity ? net::NetworkChangeNotifier::CONNECTION_UNKNOWN
67 : net::NetworkChangeNotifier::CONNECTION_NONE);
68 base::RunLoop().RunUntilIdle();
69 }
70
71 // Forwards time, and given that MockAffiliationFetchThrottlerDelegate is a
72 // strict mock, also ensures OnCanSendNetworkRequest() is not called back
73 // during this period.
74 void FastForwardTimeBySecs(double secs) {
75 task_runner_->FastForwardBy(base::TimeDelta::FromSecondsD(secs));
76 }
77
78 void FastForwardUntilNoTasksRemain() {
79 task_runner_->FastForwardUntilNoTasksRemain();
80 }
81
82 size_t NumberOfEnqueuedTasks() { return task_runner_->GetPendingTaskCount(); }
83
84 // Forwards time until the next OnCanSendNetworkRequest() callback, and
85 // verifies that it occurs between |min_delay_sec| and |max_delay_sec| seconds
86 // from now, inclusive.
87 void AssertReleaseBetweenSecs(double min_delay_sec, double max_delay_sec) {
88 base::TimeTicks ticks_at_start = task_runner_->GetCurrentTime();
89 base::TimeDelta min_delay = base::TimeDelta::FromSecondsD(min_delay_sec);
90 if (min_delay.ToInternalValue() > 0) {
91 task_runner_->FastForwardBy(min_delay -
92 base::TimeDelta::FromInternalValue(1));
93 }
94 EXPECT_CALL(mock_delegate_, OnCanSendNetworkRequest())
95 .Times(1)
96 .WillRepeatedly(testing::Return(true));
97 task_runner_->FastForwardUntilNoTasksRemain();
98 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate_));
99 ASSERT_GE(base::TimeDelta::FromSecondsD(max_delay_sec),
100 task_runner_->GetCurrentTime() - ticks_at_start);
101 }
102
103 AffiliationFetchThrottler& policy() { return *policy_.get(); }
104
105 private:
106 // Needed because NetworkChangeNotifier uses ObserverList, which notifies
107 // observers on the MessageLoop that belongs to the thread from which they
108 // have registered.
109 base::MessageLoop message_loop_;
110 scoped_ptr<MockNetworkChangeNotifier> network_change_notifier_;
111 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
112 MockAffiliationFetchThrottlerDelegate mock_delegate_;
113 scoped_ptr<AffiliationFetchThrottler> policy_;
114
115 DISALLOW_COPY_AND_ASSIGN(AffiliationFetchThrottlerTest);
116 };
117
118 TEST_F(AffiliationFetchThrottlerTest, SuccessfulRequests) {
119 SimulateHasNetworkConnectivity(true);
120
121 policy().SignalNetworkRequestNeeded();
122 AssertReleaseBetweenSecs(0, 0);
123
124 // Signal while request is in flight should be ignored.
125 policy().SignalNetworkRequestNeeded();
126 FastForwardUntilNoTasksRemain();
127 policy().InformOfNetworkRequestComplete(true);
128 FastForwardUntilNoTasksRemain();
129
130 // Duplicate the second signal 3 times: still only 1 callback should arrive.
131 policy().SignalNetworkRequestNeeded();
132 policy().SignalNetworkRequestNeeded();
133 policy().SignalNetworkRequestNeeded();
134 AssertReleaseBetweenSecs(0, 0);
135 }
136
137 TEST_F(AffiliationFetchThrottlerTest, FailedRequests) {
138 SimulateHasNetworkConnectivity(true);
139
140 policy().SignalNetworkRequestNeeded();
141 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(0, 0));
142 policy().InformOfNetworkRequestComplete(false);
143
144 // Request after first failure should be delayed by 10 seconds % 50% fuzzing
145 // factor.
146 policy().SignalNetworkRequestNeeded();
147 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(5, 10));
148 policy().InformOfNetworkRequestComplete(false);
149
150 // Request after first failure should be delayed by 40 seconds % 50% fuzzing
151 // factor, applied twice.
152 policy().SignalNetworkRequestNeeded();
153 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(10, 40));
154 policy().InformOfNetworkRequestComplete(false);
155 }
156
157 TEST_F(AffiliationFetchThrottlerTest, GracePeriodAfterConnectivityIsRestored) {
158 SimulateHasNetworkConnectivity(false);
159
160 // After connectivity is re-established, the first request should be delayed
161 // by 10 seconds % 50% fuzzing factor.
162 policy().SignalNetworkRequestNeeded();
163 SimulateHasNetworkConnectivity(true);
164 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(5, 10));
165 policy().InformOfNetworkRequestComplete(true);
166
167 // The next request should not be delayed.
168 policy().SignalNetworkRequestNeeded();
169 AssertReleaseBetweenSecs(0, 0);
170 }
171
172 // Same as GracePeriodAfterConnectivityIsRestored, but the network comes back
173 // just before SignalNetworkRequestNeeded() is called.
174 TEST_F(AffiliationFetchThrottlerTest, GracePeriodAfterConnectivityIsRestored2) {
175 SimulateHasNetworkConnectivity(false);
176
177 SimulateHasNetworkConnectivity(true);
178 policy().SignalNetworkRequestNeeded();
179 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(5, 10));
180 policy().InformOfNetworkRequestComplete(true);
181
182 policy().SignalNetworkRequestNeeded();
183 AssertReleaseBetweenSecs(0, 0);
184 }
185
186 // TODO(engedy): This test is flaky. Investigate.
187 TEST_F(AffiliationFetchThrottlerTest, ConnectivityLostDuringBackoff) {
188 SimulateHasNetworkConnectivity(true);
189
190 policy().SignalNetworkRequestNeeded();
191 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(0, 0));
192 policy().InformOfNetworkRequestComplete(false);
193
194 policy().SignalNetworkRequestNeeded();
195 SimulateHasNetworkConnectivity(false);
196
197 // Let the exponential backoff delay expire, and verify nothing happens.
198 FastForwardUntilNoTasksRemain();
199
200 // Verify that the request is, however, sent after 10 seconds % 50 fuzzing
201 // factor.
202 SimulateHasNetworkConnectivity(true);
203 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(5, 10));
204 }
205
206 TEST_F(AffiliationFetchThrottlerTest,
207 ConnectivityLostAndRestoredDuringBackoff) {
208 SimulateHasNetworkConnectivity(true);
209
210 policy().SignalNetworkRequestNeeded();
211 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(0, 0));
212 policy().InformOfNetworkRequestComplete(false);
213
214 policy().SignalNetworkRequestNeeded();
215
216 // Also verify that a flaky connection will not flood the task queue with lots
217 // of tasks.
218 for (size_t t = 1; t <= 5; ++t) {
219 SimulateHasNetworkConnectivity(false);
220 SimulateHasNetworkConnectivity(true);
221 FastForwardTimeBySecs(1);
222 }
223 EXPECT_EQ(1u, NumberOfEnqueuedTasks());
224
225 ASSERT_NO_FATAL_FAILURE(AssertReleaseBetweenSecs(5, 10));
226 }
227
228 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698