Roll src/third_party/WebKit bf18a82:a9cee16 (svn 185297:185304)
[chromium-blink-merge.git] / components / copresence / rpc / rpc_handler_unittest.cc
blob62fd56a9f9cba5ada50c540de91e2828870272e9
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"
7 #include <map>
8 #include <string>
9 #include <vector>
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 {
34 namespace {
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);
47 } // namespace
49 class RpcHandlerTest : public testing::Test, public CopresenceDelegate {
50 public:
51 RpcHandlerTest()
52 : whispernet_client_(new StubWhispernetClient),
53 rpc_handler_(this,
54 &directive_handler_,
55 nullptr,
56 base::Bind(&RpcHandlerTest::CaptureHttpPost,
57 base::Unretained(this))),
58 status_(SUCCESS) {}
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 {
74 return nullptr;
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 {
91 return nullptr;
94 protected:
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)),
129 nullptr,
130 status_code,
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_;
166 private:
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;
175 api_key_ = api_key;
176 auth_token_ = auth_token;
177 request_protos_.push_back(request_proto.release());
180 void CaptureStatus(CopresenceStatus status) {
181 status_ = 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) {
201 // Send a report.
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(
218 "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);
313 status_ = SUCCESS;
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");
342 // Process it.
343 messages_by_subscription_.clear();
344 status_ = FAIL;
345 SendReportResponse(net::HTTP_OK, response.Pass());
347 // Check processing.
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