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

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

Issue 767163005: Add AffiliationFetcher to fetch authoritative affiliation information regarding facets. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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 2014 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 "components/password_manager/core/browser/affiliation_fetcher.h"
6
7 #include "base/test/null_task_runner.h"
8 #include "net/url_request/test_url_fetcher_factory.h"
9 #include "net/url_request/url_request_test_util.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace password_manager {
14
15 namespace {
16
17 const char kExampleAndroidFacetURI[] = "android://hash@com.example/";
18 const char kExampleWebFacet1URI[] = "https://www.example.com/";
19 const char kExampleWebFacet2URI[] = "https://www.example.org/";
20
21 class MockAffiliationFetcherDelegate
22 : public testing::StrictMock<AffiliationFetcherDelegate> {
23 public:
24 MockAffiliationFetcherDelegate() {}
25 ~MockAffiliationFetcherDelegate() {}
26
27 MOCK_METHOD0(OnFetchSucceededProxy, void());
28 MOCK_METHOD0(OnFetchFailed, void());
29 MOCK_METHOD0(OnMalformedResponse, void());
30
31 void OnFetchSucceeded(
32 scoped_ptr<AffiliationFetcher::Result> result) override {
33 OnFetchSucceededProxy();
34 result_ = result.Pass();
35 }
36
37 const AffiliationFetcher::Result& result() const { return *result_.get(); }
38
39 private:
40 scoped_ptr<AffiliationFetcher::Result> result_;
41
42 DISALLOW_COPY_AND_ASSIGN(MockAffiliationFetcherDelegate);
43 };
44
45 } // namespace
46
47 class AffiliationFetcherTest : public testing::Test {
48 public:
49 AffiliationFetcherTest()
50 : request_context_getter_(new net::TestURLRequestContextGetter(
51 make_scoped_refptr(new base::NullTaskRunner))) {}
52
53 ~AffiliationFetcherTest() override {}
54
55 protected:
56 void VerifyRequestPayload(std::string expected_payload) {
57 net::TestURLFetcher* url_fetcher =
58 test_url_fetcher_factory_.GetFetcherByID(0);
59 ASSERT_NE(nullptr, url_fetcher);
60
61 ReplaceSubstringsAfterOffset(&expected_payload, 0, " ", "");
62 EXPECT_EQ("application/json", url_fetcher->upload_content_type());
63 EXPECT_EQ(expected_payload, url_fetcher->upload_data());
64 }
65
66 void ServiceURLRequest(const std::string& response) {
67 net::TestURLFetcher* url_fetcher =
68 test_url_fetcher_factory_.GetFetcherByID(0);
69 ASSERT_NE(nullptr, url_fetcher);
70
71 url_fetcher->set_response_code(200);
72 url_fetcher->SetResponseString(response);
73 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
74 }
75
76 void SimulateServerError() {
77 net::TestURLFetcher* url_fetcher =
78 test_url_fetcher_factory_.GetFetcherByID(0);
79 ASSERT_NE(nullptr, url_fetcher);
80
81 url_fetcher->set_response_code(500);
82 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
83 }
84
85 void SimulateNetworkError() {
86 net::TestURLFetcher* url_fetcher =
87 test_url_fetcher_factory_.GetFetcherByID(0);
88 ASSERT_NE(nullptr, url_fetcher);
89 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
90 net::ERR_NETWORK_CHANGED));
91 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
92 }
93
94 net::TestURLRequestContextGetter* request_context_getter() {
95 return request_context_getter_.get();
96 }
97
98 private:
99 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
100 net::TestURLFetcherFactory test_url_fetcher_factory_;
101
102 DISALLOW_COPY_AND_ASSIGN(AffiliationFetcherTest);
103 };
104
105 TEST_F(AffiliationFetcherTest, BasicReqestAndResponse) {
106 const char kNotExampleAndroidFacetURI[] = "android://hash2@com.example.not/";
107 const char kNotExampleWebFacetURI[] = "https://not.example.com/";
108
109 const char kExpectedRequestString[] =
110 "{"
111 " \"facet\": ["
112 " \"https://www.example.com/\","
113 " \"android://hash2@com.example.not/\""
114 " ]"
115 "}";
116
117 const char kTestResponseString[] =
118 "{"
119 " \"affiliation\": ["
120 " {"
121 " \"facet\": ["
122 " \"https://www.example.com/\","
123 " \"https://www.example.org/\","
124 " \"android://hash@com.example/\""
125 " ]"
126 " },"
127 " {"
128 " \"facet\": ["
129 " \"https://not.example.com/\","
130 " \"android://hash2@com.example.not/\""
131 " ]"
132 " }"
133 " ]"
134 "}";
135
136 std::vector<std::string> uris;
137 uris.push_back(kExampleWebFacet1URI);
138 uris.push_back(kNotExampleAndroidFacetURI);
139
140 MockAffiliationFetcherDelegate mock_delegate;
141 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
142 request_context_getter(), uris, &mock_delegate));
143 fetcher->StartRequest();
144
145 EXPECT_CALL(mock_delegate, OnFetchSucceededProxy());
146 ASSERT_NO_FATAL_FAILURE(VerifyRequestPayload(kExpectedRequestString));
147 ASSERT_NO_FATAL_FAILURE(ServiceURLRequest(kTestResponseString));
148 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate));
149
150 EXPECT_THAT(mock_delegate.result()[0],
151 testing::ElementsAre(kExampleWebFacet1URI, kExampleWebFacet2URI,
152 kExampleAndroidFacetURI));
153 EXPECT_THAT(
154 mock_delegate.result()[1],
155 testing::ElementsAre(kNotExampleWebFacetURI, kNotExampleAndroidFacetURI));
156 }
157
158 // The API does not return facet URIs that are not affiliated with anything, or
159 // facet URIs that it does not know about. However, the AffiliationFetcher has
160 // promised to return an equivalence class for each requested facet.
161 TEST_F(AffiliationFetcherTest, MissingEquivalenceClassesAreCreated) {
162 // Pretend the service does not know about example.com.
163 const char kTestResponseString[] = "{\"affiliation\": []}";
164
165 std::vector<std::string> uris;
166 uris.push_back(kExampleWebFacet1URI);
167
168 MockAffiliationFetcherDelegate mock_delegate;
169 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
170 request_context_getter(), uris, &mock_delegate));
171 fetcher->StartRequest();
172
173 EXPECT_CALL(mock_delegate, OnFetchSucceededProxy());
174 ASSERT_NO_FATAL_FAILURE(ServiceURLRequest(kTestResponseString));
175 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate));
176
177 ASSERT_EQ(1u, mock_delegate.result().size());
178 EXPECT_THAT(mock_delegate.result()[0],
179 testing::ElementsAre(kExampleWebFacet1URI));
180 }
181
182 TEST_F(AffiliationFetcherTest, DuplicateEquivalenceClassesAreIgnored) {
183 const char kTestResponseString[] =
184 "{"
185 " \"affiliation\": ["
186 " {"
187 " \"facet\": ["
188 " \"https://www.example.com/\","
189 " \"https://www.example.org/\","
190 " \"android://hash@com.example/\""
191 " ]"
192 " },"
193 " {"
194 " \"facet\": ["
195 " \"android://hash@com.example/\","
196 " \"https://www.example.com/\","
197 " \"https://www.example.org/\""
198 " ]"
199 " }"
200 " ]"
201 "}";
202
203 std::vector<std::string> uris;
204 uris.push_back(kExampleWebFacet1URI);
205
206 MockAffiliationFetcherDelegate mock_delegate;
207 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
208 request_context_getter(), uris, &mock_delegate));
209 fetcher->StartRequest();
210
211 EXPECT_CALL(mock_delegate, OnFetchSucceededProxy());
212 ASSERT_NO_FATAL_FAILURE(ServiceURLRequest(kTestResponseString));
213 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate));
214
215 ASSERT_EQ(1u, mock_delegate.result().size());
216 EXPECT_THAT(mock_delegate.result()[0],
217 testing::ElementsAre(kExampleWebFacet1URI, kExampleWebFacet2URI,
218 kExampleAndroidFacetURI));
219 }
220
221 TEST_F(AffiliationFetcherTest, UnrecognizedFieldsAreIgnoredWhenSafe) {
222 const char kTestResponseString[] =
223 "{"
224 " \"affiliation\": ["
225 " {"
226 " \"facet\": ["
227 " \"https://www.example.com/\","
228 " \"https://www.example.org/\","
229 " \"android://hash@com.example/\","
230 // Facet IDs corresponding to new platform.
231 " \"new-platform://app-id-on-new-platform/\""
232 " ],"
233 // Unknown dictionary keys.
234 " \"ignored_dictionary_entry\": true"
235 " },"
236 " {"
237 // Equivalence classes only unknown facet IDs.
238 " \"facet\": ["
239 " \"new-platform://app-id-on-new-platform/\""
240 " ]"
241 " },"
242 " {"
243 // Empty equivalence classes.
244 " \"facet\": []"
245 " }"
246 " ],"
247 // Unknown dictionary keys.
248 " \"ignored_dictionary_entry\": true"
249 "}";
250
251 std::vector<std::string> uris;
252 uris.push_back(kExampleWebFacet1URI);
253
254 MockAffiliationFetcherDelegate mock_delegate;
255 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
256 request_context_getter(), uris, &mock_delegate));
257 fetcher->StartRequest();
258
259 EXPECT_CALL(mock_delegate, OnFetchSucceededProxy());
260 ASSERT_NO_FATAL_FAILURE(ServiceURLRequest(kTestResponseString));
261 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate));
262
263 ASSERT_EQ(1u, mock_delegate.result().size());
264 EXPECT_THAT(mock_delegate.result()[0],
265 testing::ElementsAre(kExampleWebFacet1URI, kExampleWebFacet2URI,
266 kExampleAndroidFacetURI));
267 }
268
269 TEST_F(AffiliationFetcherTest, FailDueToMalformedResponse) {
270 const char* kMalformedResponses[] = {
271 "Not a valid JSON.",
272 "\"Not a dictionary.\"",
273 "{\"no_affiliation_key\": true}",
274 "{\"affiliation\": \"is not a list\"}",
275 "{\"affiliation\": [\"is not a dictionary\"]}",
276 "{\"affiliation\": [{\"no_facet_key\": true}]}",
277 "{\"affiliation\": [{\"facet\": \"is not a list\"}]}",
278 // List of URIs contains non-string.
279 "{\"affiliation\": [{\"facet\": [123456789]}]}",
280 // Response can not be part of an equivalence relation.
281 "{\"affiliation\": ["
282 " {\"facet\": [\"https://www.example.com/\", \"https://foo/\"]}"
283 " {\"facet\": [\"https://www.example.com/\", \"https://bar/\"]}"
284 "]}"};
285
286 std::vector<std::string> uris;
287 uris.push_back(kExampleWebFacet1URI);
288 for (size_t i = 0; i < arraysize(kMalformedResponses); ++i) {
289 SCOPED_TRACE(kMalformedResponses[i]);
290
291 MockAffiliationFetcherDelegate mock_delegate;
292 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
293 request_context_getter(), uris, &mock_delegate));
294 fetcher->StartRequest();
295
296 EXPECT_CALL(mock_delegate, OnMalformedResponse());
297 ASSERT_NO_FATAL_FAILURE(ServiceURLRequest(kMalformedResponses[i]));
298 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate));
299 }
300 }
301
302 TEST_F(AffiliationFetcherTest, FailOnFirstServerError) {
303 std::vector<std::string> uris;
304 uris.push_back(kExampleWebFacet1URI);
305
306 MockAffiliationFetcherDelegate mock_delegate;
307 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
308 request_context_getter(), uris, &mock_delegate));
309 fetcher->StartRequest();
310
311 EXPECT_CALL(mock_delegate, OnFetchFailed());
312 ASSERT_NO_FATAL_FAILURE(SimulateServerError());
313 }
314
315 TEST_F(AffiliationFetcherTest, FailOnFirstNetworkError) {
316 std::vector<std::string> uris;
317 uris.push_back(kExampleWebFacet1URI);
318
319 MockAffiliationFetcherDelegate mock_delegate;
320 scoped_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create(
321 request_context_getter(), uris, &mock_delegate));
322 fetcher->StartRequest();
323
324 EXPECT_CALL(mock_delegate, OnFetchFailed());
325 ASSERT_NO_FATAL_FAILURE(SimulateNetworkError());
326 }
327
328 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698