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

Side by Side Diff: blimp/client/core/session/assignment_source_unittest.cc

Issue 2624903006: Remove all blimp client code. (Closed)
Patch Set: Update buildbot configuration Created 3 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 2016 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 "blimp/client/core/session/assignment_source.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/json/json_writer.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/path_service.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/test/test_simple_task_runner.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "base/values.h"
22 #include "blimp/client/core/switches/blimp_client_switches.h"
23 #include "blimp/common/get_client_auth_token.h"
24 #include "blimp/common/protocol_version.h"
25 #include "blimp/common/switches.h"
26 #include "components/safe_json/testing_json_parser.h"
27 #include "net/test/test_data_directory.h"
28 #include "net/url_request/test_url_fetcher_factory.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "url/gurl.h"
32
33 using testing::_;
34 using testing::DoAll;
35 using testing::InSequence;
36 using testing::NotNull;
37 using testing::Return;
38 using testing::SetArgPointee;
39
40 namespace blimp {
41 namespace client {
42 namespace {
43
44 const uint8_t kTestIpAddress[] = {127, 0, 0, 1};
45 const uint16_t kTestPort = 8086;
46 const char kTestIpAddressString[] = "127.0.0.1";
47 const char kTcpTransportName[] = "tcp";
48 const char kSslTransportName[] = "ssl";
49 const char kCertRelativePath[] =
50 "blimp/client/core/session/test_selfsigned_cert.pem";
51 const char kTestClientAuthToken[] = "secrett0ken";
52 const char kTestAuthToken[] = "UserAuthT0kenz";
53 const char kAssignerUrl[] = "http://www.assigner.test/";
54 const char kTestClientAuthTokenPath[] = "blimp/test/data/test_client_token";
55
56 MATCHER_P(AssignmentEquals, assignment, "") {
57 return arg.transport_protocol == assignment.transport_protocol &&
58 arg.engine_endpoint == assignment.engine_endpoint &&
59 arg.client_auth_token == assignment.client_auth_token &&
60 ((!assignment.cert && !arg.cert) ||
61 (arg.cert && assignment.cert &&
62 arg.cert->Equals(assignment.cert.get())));
63 }
64
65 // Converts |value| to a JSON string.
66 std::string ValueToString(const base::Value& value) {
67 std::string json;
68 base::JSONWriter::Write(value, &json);
69 return json;
70 }
71
72 class AssignmentSourceTest : public testing::Test {
73 public:
74 AssignmentSourceTest()
75 : source_(GURL(kAssignerUrl),
76 message_loop_.task_runner(),
77 message_loop_.task_runner()) {}
78
79 void SetUp() override {
80 base::FilePath src_root;
81 PathService::Get(base::DIR_SOURCE_ROOT, &src_root);
82 ASSERT_FALSE(src_root.empty());
83 cert_path_ = src_root.Append(kCertRelativePath);
84 client_auth_token_path_ = src_root.Append(kTestClientAuthTokenPath);
85 ASSERT_TRUE(base::ReadFileToString(cert_path_, &cert_pem_));
86 net::CertificateList cert_list =
87 net::X509Certificate::CreateCertificateListFromBytes(
88 cert_pem_.data(), cert_pem_.size(),
89 net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
90 ASSERT_FALSE(cert_list.empty());
91 cert_ = std::move(cert_list[0]);
92 ASSERT_TRUE(cert_);
93 }
94
95 // This expects the AssignmentSource::GetAssignment to return a custom
96 // endpoint without having to hit the network. This will typically be used
97 // for testing that specifying an assignment via the command line works as
98 // expected.
99 void GetAlternateAssignment() {
100 source_.GetAssignment("",
101 base::Bind(&AssignmentSourceTest::AssignmentResponse,
102 base::Unretained(this)));
103 EXPECT_EQ(nullptr, factory_.GetFetcherByID(0));
104 base::RunLoop().RunUntilIdle();
105 }
106
107 // See net/base/net_errors.h for possible status errors.
108 void GetNetworkAssignmentAndWaitForResponse(
109 net::HttpStatusCode response_code,
110 int status,
111 const std::string& response,
112 const std::string& client_auth_token,
113 const int protocol_version) {
114 source_.GetAssignment(client_auth_token,
115 base::Bind(&AssignmentSourceTest::AssignmentResponse,
116 base::Unretained(this)));
117 base::RunLoop().RunUntilIdle();
118
119 net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
120
121 EXPECT_NE(nullptr, fetcher);
122 EXPECT_EQ(kAssignerUrl, fetcher->GetOriginalURL().spec());
123
124 // Check that the request has a valid protocol_version.
125 std::unique_ptr<base::Value> json =
126 base::JSONReader::Read(fetcher->upload_data());
127 EXPECT_NE(nullptr, json.get());
128
129 const base::DictionaryValue* dict;
130 EXPECT_TRUE(json->GetAsDictionary(&dict));
131
132 std::string uploaded_protocol_version;
133 EXPECT_TRUE(
134 dict->GetString("protocol_version", &uploaded_protocol_version));
135 std::string expected_protocol_version = base::IntToString(protocol_version);
136 EXPECT_EQ(expected_protocol_version, uploaded_protocol_version);
137
138 // Check that the request has a valid authentication header.
139 net::HttpRequestHeaders headers;
140 fetcher->GetExtraRequestHeaders(&headers);
141
142 std::string authorization;
143 EXPECT_TRUE(headers.GetHeader("Authorization", &authorization));
144 EXPECT_EQ("Bearer " + client_auth_token, authorization);
145
146 // Send the fake response back.
147 fetcher->set_response_code(response_code);
148 fetcher->set_status(net::URLRequestStatus::FromError(status));
149 fetcher->SetResponseString(response);
150 fetcher->delegate()->OnURLFetchComplete(fetcher);
151
152 base::RunLoop().RunUntilIdle();
153 }
154
155 MOCK_METHOD2(AssignmentResponse,
156 void(AssignmentRequestResult, const Assignment&));
157
158 protected:
159 Assignment BuildSslAssignment();
160
161 // Builds simulated JSON response from the Assigner service.
162 std::unique_ptr<base::DictionaryValue> BuildAssignerResponse();
163
164 // Used to drive all AssignmentSource tasks.
165 // MessageLoop is required by TestingJsonParser's self-deletion logic.
166 // TODO(bauerb): Replace this with a TestSimpleTaskRunner once
167 // TestingJsonParser no longer requires having a MessageLoop.
168 base::MessageLoop message_loop_;
169
170 net::TestURLFetcherFactory factory_;
171
172 // Path to the PEM-encoded certificate chain.
173 base::FilePath cert_path_;
174
175 // Path to the client auth token;
176 base::FilePath client_auth_token_path_;
177
178 // Payload of PEM certificate chain at |cert_path_|.
179 std::string cert_pem_;
180
181 // X509 certificate decoded from |cert_path_|.
182 scoped_refptr<net::X509Certificate> cert_;
183
184 AssignmentSource source_;
185
186 // Allows safe_json to parse JSON in-process, instead of depending on a
187 // utility proces.
188 safe_json::TestingJsonParser::ScopedFactoryOverride json_parsing_factory_;
189 };
190
191 Assignment AssignmentSourceTest::BuildSslAssignment() {
192 Assignment assignment;
193 assignment.transport_protocol = Assignment::TransportProtocol::SSL;
194 assignment.engine_endpoint = net::IPEndPoint(kTestIpAddress, kTestPort);
195 assignment.client_auth_token = kTestClientAuthToken;
196 assignment.cert = cert_;
197 return assignment;
198 }
199
200 std::unique_ptr<base::DictionaryValue>
201 AssignmentSourceTest::BuildAssignerResponse() {
202 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
203 dict->SetString("clientToken", kTestClientAuthToken);
204 dict->SetString("host", kTestIpAddressString);
205 dict->SetInteger("port", kTestPort);
206 dict->SetString("certificate", cert_pem_);
207 return dict;
208 }
209
210 TEST_F(AssignmentSourceTest, TestTCPAlternateEndpointSuccess) {
211 Assignment assignment;
212 assignment.transport_protocol = Assignment::TransportProtocol::TCP;
213 assignment.engine_endpoint = net::IPEndPoint(kTestIpAddress, kTestPort);
214 assignment.cert = scoped_refptr<net::X509Certificate>(nullptr);
215
216 auto* cmd_line = base::CommandLine::ForCurrentProcess();
217 cmd_line->AppendSwitchASCII(switches::kEngineIP, kTestIpAddressString);
218 cmd_line->AppendSwitchASCII(switches::kEnginePort,
219 std::to_string(kTestPort));
220 cmd_line->AppendSwitchASCII(switches::kEngineTransport, kTcpTransportName);
221 cmd_line->AppendSwitchASCII(kClientAuthTokenPath,
222 client_auth_token_path_.value());
223
224 assignment.client_auth_token = GetClientAuthToken(*cmd_line);
225
226 CHECK_EQ("MyVoiceIsMyPassport", assignment.client_auth_token);
227
228 EXPECT_CALL(*this, AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_OK,
229 AssignmentEquals(assignment)))
230 .Times(1);
231
232 GetAlternateAssignment();
233 }
234
235 TEST_F(AssignmentSourceTest, TestSSLAlternateEndpointSuccess) {
236 Assignment assignment;
237 assignment.transport_protocol = Assignment::TransportProtocol::SSL;
238 assignment.engine_endpoint = net::IPEndPoint(kTestIpAddress, kTestPort);
239 assignment.cert = cert_;
240
241 auto* cmd_line = base::CommandLine::ForCurrentProcess();
242
243 cmd_line->AppendSwitchASCII(switches::kEngineIP, kTestIpAddressString);
244 cmd_line->AppendSwitchASCII(switches::kEnginePort,
245 std::to_string(kTestPort));
246 cmd_line->AppendSwitchASCII(switches::kEngineTransport, kSslTransportName);
247 cmd_line->AppendSwitchASCII(switches::kEngineCertPath, cert_path_.value());
248 cmd_line->AppendSwitchASCII(kClientAuthTokenPath,
249 client_auth_token_path_.value());
250
251 assignment.client_auth_token = GetClientAuthToken(*cmd_line);
252
253 EXPECT_CALL(*this, AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_OK,
254 AssignmentEquals(assignment)))
255 .Times(1);
256
257 GetAlternateAssignment();
258 }
259
260 TEST_F(AssignmentSourceTest, TestSuccess) {
261 Assignment assignment = BuildSslAssignment();
262
263 EXPECT_CALL(*this, AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_OK,
264 AssignmentEquals(assignment)))
265 .Times(1);
266
267 GetNetworkAssignmentAndWaitForResponse(
268 net::HTTP_OK, net::Error::OK, ValueToString(*BuildAssignerResponse()),
269 kTestAuthToken, kProtocolVersion);
270 }
271
272 TEST_F(AssignmentSourceTest, TestValidAfterError) {
273 InSequence sequence;
274 Assignment assignment = BuildSslAssignment();
275
276 EXPECT_CALL(*this,
277 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_NETWORK_FAILURE, _))
278 .Times(1)
279 .RetiresOnSaturation();
280
281 EXPECT_CALL(*this, AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_OK,
282 AssignmentEquals(assignment)))
283 .Times(1)
284 .RetiresOnSaturation();
285
286 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK,
287 net::Error::ERR_INSUFFICIENT_RESOURCES,
288 "", kTestAuthToken, kProtocolVersion);
289
290 GetNetworkAssignmentAndWaitForResponse(
291 net::HTTP_OK, net::Error::OK, ValueToString(*BuildAssignerResponse()),
292 kTestAuthToken, kProtocolVersion);
293 }
294
295 TEST_F(AssignmentSourceTest, TestNetworkFailure) {
296 EXPECT_CALL(*this,
297 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_NETWORK_FAILURE, _));
298 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK,
299 net::Error::ERR_INSUFFICIENT_RESOURCES,
300 "", kTestAuthToken, kProtocolVersion);
301 }
302
303 TEST_F(AssignmentSourceTest, TestBadRequest) {
304 EXPECT_CALL(*this,
305 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_BAD_REQUEST, _));
306 GetNetworkAssignmentAndWaitForResponse(net::HTTP_BAD_REQUEST, net::Error::OK,
307 "", kTestAuthToken, kProtocolVersion);
308 }
309
310 TEST_F(AssignmentSourceTest, TestUnauthorized) {
311 EXPECT_CALL(*this, AssignmentResponse(
312 ASSIGNMENT_REQUEST_RESULT_EXPIRED_ACCESS_TOKEN, _));
313 GetNetworkAssignmentAndWaitForResponse(net::HTTP_UNAUTHORIZED, net::Error::OK,
314 "", kTestAuthToken, kProtocolVersion);
315 }
316
317 TEST_F(AssignmentSourceTest, TestForbidden) {
318 EXPECT_CALL(*this,
319 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_USER_INVALID, _));
320 GetNetworkAssignmentAndWaitForResponse(net::HTTP_FORBIDDEN, net::Error::OK,
321 "", kTestAuthToken, kProtocolVersion);
322 }
323
324 TEST_F(AssignmentSourceTest, TestTooManyRequests) {
325 EXPECT_CALL(*this,
326 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_OUT_OF_VMS, _));
327 GetNetworkAssignmentAndWaitForResponse(static_cast<net::HttpStatusCode>(429),
328 net::Error::OK, "", kTestAuthToken,
329 kProtocolVersion);
330 }
331
332 TEST_F(AssignmentSourceTest, TestInternalServerError) {
333 EXPECT_CALL(*this,
334 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_SERVER_ERROR, _));
335 GetNetworkAssignmentAndWaitForResponse(net::HTTP_INTERNAL_SERVER_ERROR,
336 net::Error::OK, "", kTestAuthToken,
337 kProtocolVersion);
338 }
339
340 TEST_F(AssignmentSourceTest, TestUnexpectedNetCodeFallback) {
341 EXPECT_CALL(*this,
342 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_BAD_RESPONSE, _));
343 GetNetworkAssignmentAndWaitForResponse(net::HTTP_NOT_IMPLEMENTED,
344 net::Error::OK, "", kTestAuthToken,
345 kProtocolVersion);
346 }
347
348 TEST_F(AssignmentSourceTest, TestInvalidJsonResponse) {
349 Assignment assignment = BuildSslAssignment();
350
351 // Remove half the response.
352 std::string response = ValueToString(*BuildAssignerResponse());
353 response = response.substr(response.size() / 2);
354
355 EXPECT_CALL(*this,
356 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_BAD_RESPONSE, _));
357 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK, net::Error::OK, response,
358 kTestAuthToken, kProtocolVersion);
359 }
360
361 TEST_F(AssignmentSourceTest, TestMissingResponsePort) {
362 std::unique_ptr<base::DictionaryValue> response = BuildAssignerResponse();
363 response->Remove("port", nullptr);
364 EXPECT_CALL(*this,
365 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_BAD_RESPONSE, _));
366 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK, net::Error::OK,
367 ValueToString(*response),
368 kTestAuthToken, kProtocolVersion);
369 }
370
371 TEST_F(AssignmentSourceTest, TestInvalidIPAddress) {
372 std::unique_ptr<base::DictionaryValue> response = BuildAssignerResponse();
373 response->SetString("host", "happywhales.test");
374
375 EXPECT_CALL(*this,
376 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_BAD_RESPONSE, _));
377 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK, net::Error::OK,
378 ValueToString(*response),
379 kTestAuthToken, kProtocolVersion);
380 }
381
382 TEST_F(AssignmentSourceTest, TestMissingCert) {
383 std::unique_ptr<base::DictionaryValue> response = BuildAssignerResponse();
384 response->Remove("certificate", nullptr);
385 EXPECT_CALL(*this,
386 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_BAD_RESPONSE, _));
387 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK, net::Error::OK,
388 ValueToString(*response),
389 kTestAuthToken, kProtocolVersion);
390 }
391
392 TEST_F(AssignmentSourceTest, TestInvalidCert) {
393 std::unique_ptr<base::DictionaryValue> response = BuildAssignerResponse();
394 response->SetString("certificate", "h4x0rz!");
395 EXPECT_CALL(*this,
396 AssignmentResponse(ASSIGNMENT_REQUEST_RESULT_INVALID_CERT, _));
397 GetNetworkAssignmentAndWaitForResponse(net::HTTP_OK, net::Error::OK,
398 ValueToString(*response),
399 kTestAuthToken, kProtocolVersion);
400 }
401
402 } // namespace
403 } // namespace client
404 } // namespace blimp
OLDNEW
« no previous file with comments | « blimp/client/core/session/assignment_source.cc ('k') | blimp/client/core/session/client_network_components.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698