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.
5 #include "components/copresence/rpc/rpc_handler.h"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/message_loop/message_loop.h"
15 #include "components/audio_modem/public/modem.h"
16 #include "components/audio_modem/test/stub_whispernet_client.h"
17 #include "components/copresence/copresence_state_impl.h"
18 #include "components/copresence/handlers/directive_handler.h"
19 #include "components/copresence/proto/data.pb.h"
20 #include "components/copresence/proto/enums.pb.h"
21 #include "components/copresence/proto/rpcs.pb.h"
22 #include "components/copresence/test/fake_directive_handler.h"
23 #include "net/http/http_status_code.h"
24 #include "testing/gmock/include/gmock/gmock.h"
26 using google::protobuf::MessageLite
;
27 using google::protobuf::RepeatedPtrField
;
29 using testing::ElementsAre
;
30 using testing::Property
;
31 using testing::SizeIs
;
33 using audio_modem::AudioToken
;
34 using audio_modem::WhispernetClient
;
36 namespace copresence
{
40 const char kChromeVersion
[] = "Chrome Version String";
43 const RepeatedPtrField
<SubscribedMessage
>& /* messages */) {}
47 class RpcHandlerTest
: public testing::Test
, public CopresenceDelegate
{
50 : whispernet_client_(new audio_modem::StubWhispernetClient
),
51 // TODO(ckehoe): Use a FakeCopresenceState here
52 // and test that it gets called correctly.
57 base::Bind(&IgnoreMessages
),
58 base::Bind(&RpcHandlerTest::CaptureHttpPost
,
59 base::Unretained(this))),
62 // CopresenceDelegate implementation
64 void HandleMessages(const std::string
& /* app_id */,
65 const std::string
& subscription_id
,
66 const std::vector
<Message
>& messages
) override
{
70 void HandleStatusUpdate(CopresenceStatus
/* status */) override
{
74 net::URLRequestContextGetter
* GetRequestContext() const override
{
78 const std::string
GetPlatformVersionString() const override
{
79 return kChromeVersion
;
82 const std::string
GetAPIKey(const std::string
& app_id
) const override
{
83 return app_id
+ " API Key";
86 WhispernetClient
* GetWhispernetClient() override
{
87 return whispernet_client_
.get();
90 // TODO(ckehoe): Add GCM tests.
91 gcm::GCMDriver
* GetGCMDriver() override
{
95 const std::string
GetDeviceId(bool authenticated
) override
{
96 return device_id_by_auth_state_
[authenticated
];
99 void SaveDeviceId(bool authenticated
, const std::string
& device_id
) override
{
100 device_id_by_auth_state_
[authenticated
] = device_id
;
105 // Send test input to RpcHandler
107 void RegisterDevice(bool authenticated
) {
108 rpc_handler_
.RegisterDevice(authenticated
);
111 void SendRegisterResponse(bool authenticated
,
112 const std::string
& device_id
) {
113 RegisterDeviceResponse response
;
114 response
.set_registered_device_id(device_id
);
115 response
.mutable_header()->mutable_status()->set_code(OK
);
117 std::string serialized_response
;
118 response
.SerializeToString(&serialized_response
);
119 rpc_handler_
.RegisterResponseHandler(
120 authenticated
, false, nullptr, net::HTTP_OK
, serialized_response
);
123 void SendReport(scoped_ptr
<ReportRequest
> request
,
124 const std::string
& app_id
,
125 const std::string
& auth_token
) {
126 rpc_handler_
.SendReportRequest(
127 request
.Pass(), app_id
, auth_token
, StatusCallback());
130 void SendReportResponse(int status_code
,
131 scoped_ptr
<ReportResponse
> response
) {
132 response
->mutable_header()->mutable_status()->set_code(OK
);
134 std::string serialized_response
;
135 response
->SerializeToString(&serialized_response
);
136 rpc_handler_
.ReportResponseHandler(
137 base::Bind(&RpcHandlerTest::CaptureStatus
, base::Unretained(this)),
140 serialized_response
);
143 // Read and modify RpcHandler state
145 void SetAuthToken(const std::string
& auth_token
) {
146 rpc_handler_
.auth_token_
= auth_token
;
149 const ScopedVector
<RpcHandler::PendingRequest
>& request_queue() const {
150 return rpc_handler_
.pending_requests_queue_
;
153 void AddInvalidToken(const std::string
& token
) {
154 rpc_handler_
.invalid_audio_token_cache_
.Add(token
, true);
157 bool TokenIsInvalid(const std::string
& token
) {
158 return rpc_handler_
.invalid_audio_token_cache_
.HasKey(token
);
161 // For rpc_handler_.invalid_audio_token_cache_
162 base::MessageLoop message_loop_
;
164 scoped_ptr
<WhispernetClient
> whispernet_client_
;
165 FakeDirectiveHandler directive_handler_
;
166 RpcHandler rpc_handler_
;
168 std::map
<bool, std::string
> device_id_by_auth_state_
;
170 CopresenceStatus status_
;
171 std::string rpc_name_
;
172 std::string api_key_
;
173 std::string auth_token_
;
174 ScopedVector
<MessageLite
> request_protos_
;
177 void CaptureHttpPost(
178 net::URLRequestContextGetter
* url_context_getter
,
179 const std::string
& rpc_name
,
180 const std::string
& api_key
,
181 const std::string
& auth_token
,
182 scoped_ptr
<MessageLite
> request_proto
,
183 const RpcHandler::PostCleanupCallback
& response_callback
) {
184 rpc_name_
= rpc_name
;
186 auth_token_
= auth_token
;
187 request_protos_
.push_back(request_proto
.release());
190 void CaptureStatus(CopresenceStatus status
) {
195 TEST_F(RpcHandlerTest
, RegisterDevice
) {
196 RegisterDevice(false);
197 EXPECT_THAT(request_protos_
, SizeIs(1));
198 const RegisterDeviceRequest
* registration
=
199 static_cast<RegisterDeviceRequest
*>(request_protos_
[0]);
200 EXPECT_EQ(CHROME
, registration
->device_identifiers().registrant().type());
202 SetAuthToken("Register auth");
203 RegisterDevice(true);
204 EXPECT_THAT(request_protos_
, SizeIs(2));
205 registration
= static_cast<RegisterDeviceRequest
*>(request_protos_
[1]);
206 EXPECT_FALSE(registration
->has_device_identifiers());
209 TEST_F(RpcHandlerTest
, RequestQueuing
) {
211 ReportRequest
* report
= new ReportRequest
;
212 report
->mutable_manage_messages_request()->add_id_to_unpublish("unpublish");
213 SendReport(make_scoped_ptr(report
), "Q App ID", "Q Auth Token");
214 EXPECT_THAT(request_queue(), SizeIs(1));
215 EXPECT_TRUE(request_queue()[0]->authenticated
);
217 // Check for registration request.
218 EXPECT_THAT(request_protos_
, SizeIs(1));
219 const RegisterDeviceRequest
* registration
=
220 static_cast<RegisterDeviceRequest
*>(request_protos_
[0]);
221 EXPECT_FALSE(registration
->device_identifiers().has_registrant());
222 EXPECT_EQ("Q Auth Token", auth_token_
);
224 // Send a second report.
225 report
= new ReportRequest
;
226 report
->mutable_manage_subscriptions_request()->add_id_to_unsubscribe(
228 SendReport(make_scoped_ptr(report
), "Q App ID", "Q Auth Token");
229 EXPECT_THAT(request_protos_
, SizeIs(1));
230 EXPECT_THAT(request_queue(), SizeIs(2));
231 EXPECT_TRUE(request_queue()[1]->authenticated
);
233 // Send an anonymous report.
234 report
= new ReportRequest
;
235 report
->mutable_update_signals_request()->add_token_observation()
236 ->set_token_id("Q Audio Token");
237 SendReport(make_scoped_ptr(report
), "Q App ID", "");
238 EXPECT_THAT(request_queue(), SizeIs(3));
239 EXPECT_FALSE(request_queue()[2]->authenticated
);
241 // Check for another registration request.
242 EXPECT_THAT(request_protos_
, SizeIs(2));
243 registration
= static_cast<RegisterDeviceRequest
*>(request_protos_
[1]);
244 EXPECT_TRUE(registration
->device_identifiers().has_registrant());
245 EXPECT_EQ("", auth_token_
);
247 // Respond to the first registration.
248 SendRegisterResponse(true, "Q Auth Device ID");
249 EXPECT_EQ("Q Auth Device ID", device_id_by_auth_state_
[true]);
251 // Check that queued reports are sent.
252 EXPECT_THAT(request_protos_
, SizeIs(4));
253 EXPECT_THAT(request_queue(), SizeIs(1));
254 EXPECT_THAT(directive_handler_
.removed_directives(),
255 ElementsAre("unpublish", "unsubscribe"));
256 report
= static_cast<ReportRequest
*>(request_protos_
[2]);
257 EXPECT_EQ("unpublish", report
->manage_messages_request().id_to_unpublish(0));
258 report
= static_cast<ReportRequest
*>(request_protos_
[3]);
259 EXPECT_EQ("unsubscribe",
260 report
->manage_subscriptions_request().id_to_unsubscribe(0));
262 // Respond to the second registration.
263 SendRegisterResponse(false, "Q Anonymous Device ID");
264 EXPECT_EQ("Q Anonymous Device ID", device_id_by_auth_state_
[false]);
266 // Check for last report.
267 EXPECT_THAT(request_protos_
, SizeIs(5));
268 EXPECT_TRUE(request_queue().empty());
269 report
= static_cast<ReportRequest
*>(request_protos_
[4]);
270 EXPECT_EQ("Q Audio Token",
271 report
->update_signals_request().token_observation(0).token_id());
274 TEST_F(RpcHandlerTest
, CreateRequestHeader
) {
275 device_id_by_auth_state_
[true] = "CreateRequestHeader Device ID";
276 SendReport(make_scoped_ptr(new ReportRequest
),
277 "CreateRequestHeader App",
278 "CreateRequestHeader Auth Token");
280 EXPECT_EQ(RpcHandler::kReportRequestRpcName
, rpc_name_
);
281 EXPECT_EQ("CreateRequestHeader App API Key", api_key_
);
282 EXPECT_EQ("CreateRequestHeader Auth Token", auth_token_
);
283 const ReportRequest
* report
= static_cast<ReportRequest
*>(request_protos_
[0]);
284 EXPECT_EQ(kChromeVersion
,
285 report
->header().framework_version().version_name());
286 EXPECT_EQ("CreateRequestHeader App",
287 report
->header().client_version().client());
288 EXPECT_EQ("CreateRequestHeader Device ID",
289 report
->header().registered_device_id());
290 EXPECT_EQ(CHROME_PLATFORM_TYPE
,
291 report
->header().device_fingerprint().type());
294 TEST_F(RpcHandlerTest
, ReportTokens
) {
295 std::vector
<AudioToken
> test_tokens
;
296 test_tokens
.push_back(AudioToken("token 1", false));
297 test_tokens
.push_back(AudioToken("token 2", false));
298 test_tokens
.push_back(AudioToken("token 3", true));
299 AddInvalidToken("token 2");
301 device_id_by_auth_state_
[false] = "ReportTokens Anonymous Device";
302 device_id_by_auth_state_
[true] = "ReportTokens Auth Device";
303 SetAuthToken("ReportTokens Auth");
305 rpc_handler_
.ReportTokens(test_tokens
);
306 EXPECT_EQ(RpcHandler::kReportRequestRpcName
, rpc_name_
);
307 EXPECT_EQ(" API Key", api_key_
);
308 EXPECT_THAT(request_protos_
, SizeIs(2));
309 const ReportRequest
* report
= static_cast<ReportRequest
*>(request_protos_
[0]);
310 RepeatedPtrField
<TokenObservation
> tokens_sent
=
311 report
->update_signals_request().token_observation();
312 EXPECT_THAT(tokens_sent
, ElementsAre(
313 Property(&TokenObservation::token_id
, "token 1"),
314 Property(&TokenObservation::token_id
, "token 3"),
315 Property(&TokenObservation::token_id
, "current audible"),
316 Property(&TokenObservation::token_id
, "current inaudible")));
319 TEST_F(RpcHandlerTest
, ReportResponseHandler
) {
320 // Fail on HTTP status != 200.
321 scoped_ptr
<ReportResponse
> response(new ReportResponse
);
323 SendReportResponse(net::HTTP_BAD_REQUEST
, response
.Pass());
324 EXPECT_EQ(FAIL
, status_
);
326 // Construct a test ReportResponse.
327 response
.reset(new ReportResponse
);
328 response
->mutable_header()->mutable_status()->set_code(OK
);
329 UpdateSignalsResponse
* update_response
=
330 response
->mutable_update_signals_response();
331 update_response
->set_status(util::error::OK
);
332 Token
* invalid_token
= update_response
->add_token();
333 invalid_token
->set_id("bad token");
334 invalid_token
->set_status(INVALID
);
335 update_response
->add_directive()->set_subscription_id("Subscription 1");
336 update_response
->add_directive()->set_subscription_id("Subscription 2");
340 SendReportResponse(net::HTTP_OK
, response
.Pass());
341 EXPECT_EQ(SUCCESS
, status_
);
342 EXPECT_TRUE(TokenIsInvalid("bad token"));
343 EXPECT_THAT(directive_handler_
.added_directives(),
344 ElementsAre("Subscription 1", "Subscription 2"));
347 } // namespace copresence