Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / copresence / rpc / rpc_handler_unittest.cc
blob3737eaf15d3001559cbd015d04d887ec8979df18
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"
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/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 {
38 namespace {
40 const char kChromeVersion[] = "Chrome Version String";
42 void IgnoreMessages(
43 const RepeatedPtrField<SubscribedMessage>& /* messages */) {}
45 } // namespace
47 class RpcHandlerTest : public testing::Test, public CopresenceDelegate {
48 public:
49 RpcHandlerTest()
50 : whispernet_client_(new audio_modem::StubWhispernetClient),
51 // TODO(ckehoe): Use a FakeCopresenceState here
52 // and test that it gets called correctly.
53 rpc_handler_(this,
54 &directive_handler_,
55 nullptr,
56 nullptr,
57 base::Bind(&IgnoreMessages),
58 base::Bind(&RpcHandlerTest::CaptureHttpPost,
59 base::Unretained(this))),
60 status_(SUCCESS) {}
62 // CopresenceDelegate implementation
64 void HandleMessages(const std::string& /* app_id */,
65 const std::string& subscription_id,
66 const std::vector<Message>& messages) override {
67 NOTREACHED();
70 void HandleStatusUpdate(CopresenceStatus /* status */) override {
71 NOTREACHED();
74 net::URLRequestContextGetter* GetRequestContext() const override {
75 return nullptr;
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 {
92 return nullptr;
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;
103 protected:
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)),
138 nullptr,
139 status_code,
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_;
176 private:
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;
185 api_key_ = api_key;
186 auth_token_ = auth_token;
187 request_protos_.push_back(request_proto.release());
190 void CaptureStatus(CopresenceStatus status) {
191 status_ = 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) {
210 // Send a report.
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(
227 "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);
322 status_ = SUCCESS;
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");
338 // Check processing.
339 status_ = FAIL;
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