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.
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/copresence/handlers/directive_handler.h"
16 #include "components/copresence/mediums/audio/audio_manager.h"
17 #include "components/copresence/proto/data.pb.h"
18 #include "components/copresence/proto/enums.pb.h"
19 #include "components/copresence/proto/rpcs.pb.h"
20 #include "components/copresence/test/fake_directive_handler.h"
21 #include "components/copresence/test/stub_whispernet_client.h"
22 #include "net/http/http_status_code.h"
23 #include "testing/gmock/include/gmock/gmock.h"
25 using google::protobuf::MessageLite
;
26 using google::protobuf::RepeatedPtrField
;
28 using testing::ElementsAre
;
29 using testing::Property
;
30 using testing::SizeIs
;
32 namespace copresence
{
36 const char kChromeVersion
[] = "Chrome Version String";
38 void CreateSubscribedMessage(const std::vector
<std::string
>& subscription_ids
,
39 const std::string
& message_string
,
40 SubscribedMessage
* message_proto
) {
41 message_proto
->mutable_published_message()->set_payload(message_string
);
42 for (const std::string
& subscription_id
: subscription_ids
) {
43 message_proto
->add_subscription_id(subscription_id
);
49 class RpcHandlerTest
: public testing::Test
, public CopresenceDelegate
{
52 : whispernet_client_(new StubWhispernetClient
),
56 base::Bind(&RpcHandlerTest::CaptureHttpPost
,
57 base::Unretained(this))),
60 // CopresenceDelegate implementation
62 void HandleMessages(const std::string
& /* app_id */,
63 const std::string
& subscription_id
,
64 const std::vector
<Message
>& messages
) override
{
65 // app_id is unused for now, pending a server fix.
66 for (const Message
& message
: messages
) {
67 messages_by_subscription_
[subscription_id
].push_back(message
.payload());
71 void HandleStatusUpdate(CopresenceStatus
/* status */) override
{}
73 net::URLRequestContextGetter
* GetRequestContext() const override
{
77 const std::string
GetPlatformVersionString() const override
{
78 return kChromeVersion
;
81 const std::string
GetAPIKey(const std::string
& app_id
) const override
{
82 return app_id
+ " API Key";
85 WhispernetClient
* GetWhispernetClient() override
{
86 return whispernet_client_
.get();
89 // TODO(ckehoe): Add GCM tests.
90 gcm::GCMDriver
* GetGCMDriver() override
{
96 // Send test input to RpcHandler
98 void RegisterForToken(const std::string
& auth_token
) {
99 rpc_handler_
.RegisterForToken(auth_token
);
102 void SendRegisterResponse(const std::string
& auth_token
,
103 const std::string
& device_id
) {
104 RegisterDeviceResponse response
;
105 response
.set_registered_device_id(device_id
);
106 response
.mutable_header()->mutable_status()->set_code(OK
);
108 std::string serialized_response
;
109 response
.SerializeToString(&serialized_response
);
110 rpc_handler_
.RegisterResponseHandler(
111 auth_token
, false, nullptr, net::HTTP_OK
, serialized_response
);
114 void SendReport(scoped_ptr
<ReportRequest
> request
,
115 const std::string
& app_id
,
116 const std::string
& auth_token
) {
117 rpc_handler_
.SendReportRequest(
118 request
.Pass(), app_id
, auth_token
, StatusCallback());
121 void SendReportResponse(int status_code
,
122 scoped_ptr
<ReportResponse
> response
) {
123 response
->mutable_header()->mutable_status()->set_code(OK
);
125 std::string serialized_response
;
126 response
->SerializeToString(&serialized_response
);
127 rpc_handler_
.ReportResponseHandler(
128 base::Bind(&RpcHandlerTest::CaptureStatus
, base::Unretained(this)),
131 serialized_response
);
134 // Read and modify RpcHandler state
136 const ScopedVector
<RpcHandler::PendingRequest
>& request_queue() const {
137 return rpc_handler_
.pending_requests_queue_
;
140 std::map
<std::string
, std::string
>& device_id_by_auth_token() {
141 return rpc_handler_
.device_id_by_auth_token_
;
144 void AddInvalidToken(const std::string
& token
) {
145 rpc_handler_
.invalid_audio_token_cache_
.Add(token
, true);
148 bool TokenIsInvalid(const std::string
& token
) {
149 return rpc_handler_
.invalid_audio_token_cache_
.HasKey(token
);
152 // For rpc_handler_.invalid_audio_token_cache_
153 base::MessageLoop message_loop_
;
155 scoped_ptr
<WhispernetClient
> whispernet_client_
;
156 FakeDirectiveHandler directive_handler_
;
157 RpcHandler rpc_handler_
;
159 CopresenceStatus status_
;
160 std::string rpc_name_
;
161 std::string api_key_
;
162 std::string auth_token_
;
163 ScopedVector
<MessageLite
> request_protos_
;
164 std::map
<std::string
, std::vector
<std::string
>> messages_by_subscription_
;
167 void CaptureHttpPost(
168 net::URLRequestContextGetter
* url_context_getter
,
169 const std::string
& rpc_name
,
170 const std::string
& api_key
,
171 const std::string
& auth_token
,
172 scoped_ptr
<MessageLite
> request_proto
,
173 const RpcHandler::PostCleanupCallback
& response_callback
) {
174 rpc_name_
= rpc_name
;
176 auth_token_
= auth_token
;
177 request_protos_
.push_back(request_proto
.release());
180 void CaptureStatus(CopresenceStatus status
) {
185 TEST_F(RpcHandlerTest
, RegisterForToken
) {
186 RegisterForToken("");
187 EXPECT_THAT(request_protos_
, SizeIs(1));
188 const RegisterDeviceRequest
* registration
=
189 static_cast<RegisterDeviceRequest
*>(request_protos_
[0]);
190 Identity identity
= registration
->device_identifiers().registrant();
191 EXPECT_EQ(CHROME
, identity
.type());
192 EXPECT_FALSE(identity
.chrome_id().empty());
194 RegisterForToken("abc");
195 EXPECT_THAT(request_protos_
, SizeIs(2));
196 registration
= static_cast<RegisterDeviceRequest
*>(request_protos_
[1]);
197 EXPECT_FALSE(registration
->has_device_identifiers());
200 TEST_F(RpcHandlerTest
, RequestQueuing
) {
202 ReportRequest
* report
= new ReportRequest
;
203 report
->mutable_manage_messages_request()->add_id_to_unpublish("unpublish");
204 SendReport(make_scoped_ptr(report
), "Q App ID", "Q Auth Token");
205 EXPECT_THAT(request_queue(), SizeIs(1));
206 EXPECT_EQ("Q Auth Token", request_queue()[0]->auth_token
);
208 // Check for registration request.
209 EXPECT_THAT(request_protos_
, SizeIs(1));
210 const RegisterDeviceRequest
* registration
=
211 static_cast<RegisterDeviceRequest
*>(request_protos_
[0]);
212 EXPECT_FALSE(registration
->device_identifiers().has_registrant());
213 EXPECT_EQ("Q Auth Token", auth_token_
);
215 // Send a second report.
216 report
= new ReportRequest
;
217 report
->mutable_manage_subscriptions_request()->add_id_to_unsubscribe(
219 SendReport(make_scoped_ptr(report
), "Q App ID", "Q Auth Token");
220 EXPECT_THAT(request_protos_
, SizeIs(1));
221 EXPECT_THAT(request_queue(), SizeIs(2));
222 EXPECT_EQ("Q Auth Token", request_queue()[1]->auth_token
);
224 // Send an anonymous report.
225 report
= new ReportRequest
;
226 report
->mutable_update_signals_request()->add_token_observation()
227 ->set_token_id("Q Audio Token");
228 SendReport(make_scoped_ptr(report
), "Q App ID", "");
229 EXPECT_THAT(request_queue(), SizeIs(3));
230 EXPECT_EQ("", request_queue()[2]->auth_token
);
232 // Check for another registration request.
233 EXPECT_THAT(request_protos_
, SizeIs(2));
234 registration
= static_cast<RegisterDeviceRequest
*>(request_protos_
[1]);
235 EXPECT_TRUE(registration
->device_identifiers().has_registrant());
236 EXPECT_EQ("", auth_token_
);
238 // Respond to the first registration.
239 SendRegisterResponse("Q Auth Token", "Q Auth Device ID");
240 EXPECT_EQ("Q Auth Device ID", device_id_by_auth_token()["Q Auth Token"]);
242 // Check that queued reports are sent.
243 EXPECT_THAT(request_protos_
, SizeIs(4));
244 EXPECT_THAT(request_queue(), SizeIs(1));
245 EXPECT_THAT(directive_handler_
.removed_directives(),
246 ElementsAre("unpublish", "unsubscribe"));
247 report
= static_cast<ReportRequest
*>(request_protos_
[2]);
248 EXPECT_EQ("unpublish", report
->manage_messages_request().id_to_unpublish(0));
249 report
= static_cast<ReportRequest
*>(request_protos_
[3]);
250 EXPECT_EQ("unsubscribe",
251 report
->manage_subscriptions_request().id_to_unsubscribe(0));
253 // Respond to the second registration.
254 SendRegisterResponse("", "Q Anonymous Device ID");
255 EXPECT_EQ("Q Anonymous Device ID", device_id_by_auth_token()[""]);
257 // Check for last report.
258 EXPECT_THAT(request_protos_
, SizeIs(5));
259 EXPECT_TRUE(request_queue().empty());
260 report
= static_cast<ReportRequest
*>(request_protos_
[4]);
261 EXPECT_EQ("Q Audio Token",
262 report
->update_signals_request().token_observation(0).token_id());
265 TEST_F(RpcHandlerTest
, CreateRequestHeader
) {
266 device_id_by_auth_token()["CreateRequestHeader Auth Token"] =
267 "CreateRequestHeader Device ID";
268 SendReport(make_scoped_ptr(new ReportRequest
),
269 "CreateRequestHeader App",
270 "CreateRequestHeader Auth Token");
272 EXPECT_EQ(RpcHandler::kReportRequestRpcName
, rpc_name_
);
273 EXPECT_EQ("CreateRequestHeader App API Key", api_key_
);
274 EXPECT_EQ("CreateRequestHeader Auth Token", auth_token_
);
275 const ReportRequest
* report
= static_cast<ReportRequest
*>(request_protos_
[0]);
276 EXPECT_EQ(kChromeVersion
,
277 report
->header().framework_version().version_name());
278 EXPECT_EQ("CreateRequestHeader App",
279 report
->header().client_version().client());
280 EXPECT_EQ("CreateRequestHeader Device ID",
281 report
->header().registered_device_id());
282 EXPECT_EQ(CHROME_PLATFORM_TYPE
,
283 report
->header().device_fingerprint().type());
286 TEST_F(RpcHandlerTest
, ReportTokens
) {
287 std::vector
<AudioToken
> test_tokens
;
288 test_tokens
.push_back(AudioToken("token 1", false));
289 test_tokens
.push_back(AudioToken("token 2", false));
290 test_tokens
.push_back(AudioToken("token 3", true));
291 AddInvalidToken("token 2");
293 device_id_by_auth_token()[""] = "ReportTokens Anonymous Device";
294 device_id_by_auth_token()["ReportTokens Auth"] = "ReportTokens Auth Device";
296 rpc_handler_
.ReportTokens(test_tokens
);
297 EXPECT_EQ(RpcHandler::kReportRequestRpcName
, rpc_name_
);
298 EXPECT_EQ(" API Key", api_key_
);
299 EXPECT_THAT(request_protos_
, SizeIs(2));
300 const ReportRequest
* report
= static_cast<ReportRequest
*>(request_protos_
[0]);
301 RepeatedPtrField
<TokenObservation
> tokens_sent
=
302 report
->update_signals_request().token_observation();
303 EXPECT_THAT(tokens_sent
, ElementsAre(
304 Property(&TokenObservation::token_id
, "token 1"),
305 Property(&TokenObservation::token_id
, "token 3"),
306 Property(&TokenObservation::token_id
, "current audible"),
307 Property(&TokenObservation::token_id
, "current inaudible")));
310 TEST_F(RpcHandlerTest
, ReportResponseHandler
) {
311 // Fail on HTTP status != 200.
312 scoped_ptr
<ReportResponse
> response(new ReportResponse
);
314 SendReportResponse(net::HTTP_BAD_REQUEST
, response
.Pass());
315 EXPECT_EQ(FAIL
, status_
);
317 // Construct test subscriptions.
318 std::vector
<std::string
> subscription_1(1, "Subscription 1");
319 std::vector
<std::string
> subscription_2(1, "Subscription 2");
320 std::vector
<std::string
> both_subscriptions
;
321 both_subscriptions
.push_back("Subscription 1");
322 both_subscriptions
.push_back("Subscription 2");
324 // Construct a test ReportResponse.
325 response
.reset(new ReportResponse
);
326 response
->mutable_header()->mutable_status()->set_code(OK
);
327 UpdateSignalsResponse
* update_response
=
328 response
->mutable_update_signals_response();
329 update_response
->set_status(util::error::OK
);
330 Token
* invalid_token
= update_response
->add_token();
331 invalid_token
->set_id("bad token");
332 invalid_token
->set_status(INVALID
);
333 CreateSubscribedMessage(
334 subscription_1
, "Message A", update_response
->add_message());
335 CreateSubscribedMessage(
336 subscription_2
, "Message B", update_response
->add_message());
337 CreateSubscribedMessage(
338 both_subscriptions
, "Message C", update_response
->add_message());
339 update_response
->add_directive()->set_subscription_id("Subscription 1");
340 update_response
->add_directive()->set_subscription_id("Subscription 2");
343 messages_by_subscription_
.clear();
345 SendReportResponse(net::HTTP_OK
, response
.Pass());
348 EXPECT_EQ(SUCCESS
, status_
);
349 EXPECT_TRUE(TokenIsInvalid("bad token"));
350 EXPECT_THAT(messages_by_subscription_
["Subscription 1"],
351 ElementsAre("Message A", "Message C"));
352 EXPECT_THAT(messages_by_subscription_
["Subscription 2"],
353 ElementsAre("Message B", "Message C"));
354 EXPECT_THAT(directive_handler_
.added_directives(),
355 ElementsAre("Subscription 1", "Subscription 2"));
358 } // namespace copresence