Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / copresence / rpc / rpc_handler_unittest.cc
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/copresence/rpc/rpc_handler.h"
6
7 #include <map>
8 #include <string>
9 #include <vector>
10
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"
24
25 using google::protobuf::MessageLite;
26 using google::protobuf::RepeatedPtrField;
27
28 using testing::ElementsAre;
29 using testing::Property;
30 using testing::SizeIs;
31
32 namespace copresence {
33
34 namespace {
35
36 const char kChromeVersion[] = "Chrome Version String";
37
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);
44   }
45 }
46
47 }  // namespace
48
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) {}
59
60   // CopresenceDelegate implementation
61
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());
68     }
69   }
70
71   void HandleStatusUpdate(CopresenceStatus /* status */) override {}
72
73   net::URLRequestContextGetter* GetRequestContext() const override {
74     return nullptr;
75   }
76
77   const std::string GetPlatformVersionString() const override {
78     return kChromeVersion;
79   }
80
81   const std::string GetAPIKey(const std::string& app_id) const override {
82     return app_id + " API Key";
83   }
84
85   WhispernetClient* GetWhispernetClient() override {
86     return whispernet_client_.get();
87   }
88
89   // TODO(ckehoe): Add GCM tests.
90   gcm::GCMDriver* GetGCMDriver() override {
91     return nullptr;
92   }
93
94  protected:
95
96   // Send test input to RpcHandler
97
98   void RegisterForToken(const std::string& auth_token) {
99     rpc_handler_.RegisterForToken(auth_token);
100   }
101
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);
107
108     std::string serialized_response;
109     response.SerializeToString(&serialized_response);
110     rpc_handler_.RegisterResponseHandler(
111         auth_token, false, nullptr, net::HTTP_OK, serialized_response);
112   }
113
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());
119   }
120
121   void SendReportResponse(int status_code,
122                           scoped_ptr<ReportResponse> response) {
123     response->mutable_header()->mutable_status()->set_code(OK);
124
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);
132   }
133
134   // Read and modify RpcHandler state
135
136   const ScopedVector<RpcHandler::PendingRequest>& request_queue() const {
137     return rpc_handler_.pending_requests_queue_;
138   }
139
140   std::map<std::string, std::string>& device_id_by_auth_token() {
141     return rpc_handler_.device_id_by_auth_token_;
142   }
143
144   void AddInvalidToken(const std::string& token) {
145     rpc_handler_.invalid_audio_token_cache_.Add(token, true);
146   }
147
148   bool TokenIsInvalid(const std::string& token) {
149     return rpc_handler_.invalid_audio_token_cache_.HasKey(token);
150   }
151
152   // For rpc_handler_.invalid_audio_token_cache_
153   base::MessageLoop message_loop_;
154
155   scoped_ptr<WhispernetClient> whispernet_client_;
156   FakeDirectiveHandler directive_handler_;
157   RpcHandler rpc_handler_;
158
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_;
165
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());
178   }
179
180   void CaptureStatus(CopresenceStatus status) {
181     status_ = status;
182   }
183 };
184
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());
193
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());
198 }
199
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);
207
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_);
214
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);
223
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);
231
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_);
237
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"]);
241
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));
252
253   // Respond to the second registration.
254   SendRegisterResponse("", "Q Anonymous Device ID");
255   EXPECT_EQ("Q Anonymous Device ID", device_id_by_auth_token()[""]);
256
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());
263 }
264
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");
271
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());
284 }
285
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");
292
293   device_id_by_auth_token()[""] = "ReportTokens Anonymous Device";
294   device_id_by_auth_token()["ReportTokens Auth"] = "ReportTokens Auth Device";
295
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")));
308 }
309
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_);
316
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");
323
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");
341
342   // Process it.
343   messages_by_subscription_.clear();
344   status_ = FAIL;
345   SendReportResponse(net::HTTP_OK, response.Pass());
346
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"));
356 }
357
358 }  // namespace copresence