Give names to all utility processes.
[chromium-blink-merge.git] / components / copresence / rpc / rpc_handler_unittest.cc
blobe4ff7309289e1318e1a59a2a07dc1d0ef9a07e57
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/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 state_(new CopresenceStateImpl),
54 rpc_handler_(this,
55 state_.get(),
56 &directive_handler_,
57 nullptr,
58 base::Bind(&IgnoreMessages),
59 base::Bind(&RpcHandlerTest::CaptureHttpPost,
60 base::Unretained(this))),
61 status_(SUCCESS) {}
63 // CopresenceDelegate implementation
65 void HandleMessages(const std::string& /* app_id */,
66 const std::string& subscription_id,
67 const std::vector<Message>& messages) override {
68 NOTREACHED();
71 void HandleStatusUpdate(CopresenceStatus /* status */) override {
72 NOTREACHED();
75 net::URLRequestContextGetter* GetRequestContext() const override {
76 return nullptr;
79 const std::string GetPlatformVersionString() const override {
80 return kChromeVersion;
83 const std::string GetAPIKey(const std::string& app_id) const override {
84 return app_id + " API Key";
87 WhispernetClient* GetWhispernetClient() override {
88 return whispernet_client_.get();
91 // TODO(ckehoe): Add GCM tests.
92 gcm::GCMDriver* GetGCMDriver() override {
93 return nullptr;
96 const std::string GetDeviceId(bool authenticated) override {
97 return device_id_by_auth_state_[authenticated];
100 void SaveDeviceId(bool authenticated, const std::string& device_id) override {
101 device_id_by_auth_state_[authenticated] = device_id;
104 protected:
106 // Send test input to RpcHandler
108 void RegisterDevice(bool authenticated) {
109 rpc_handler_.RegisterDevice(authenticated);
112 void SendRegisterResponse(bool authenticated,
113 const std::string& device_id) {
114 RegisterDeviceResponse response;
115 response.set_registered_device_id(device_id);
116 response.mutable_header()->mutable_status()->set_code(OK);
118 std::string serialized_response;
119 response.SerializeToString(&serialized_response);
120 rpc_handler_.RegisterResponseHandler(
121 authenticated, false, nullptr, net::HTTP_OK, serialized_response);
124 void SendReport(scoped_ptr<ReportRequest> request,
125 const std::string& app_id,
126 const std::string& auth_token) {
127 rpc_handler_.SendReportRequest(
128 request.Pass(), app_id, auth_token, StatusCallback());
131 void SendReportResponse(int status_code,
132 scoped_ptr<ReportResponse> response) {
133 response->mutable_header()->mutable_status()->set_code(OK);
135 std::string serialized_response;
136 response->SerializeToString(&serialized_response);
137 rpc_handler_.ReportResponseHandler(
138 base::Bind(&RpcHandlerTest::CaptureStatus, base::Unretained(this)),
139 nullptr,
140 status_code,
141 serialized_response);
144 // Read and modify RpcHandler state
146 void SetAuthToken(const std::string& auth_token) {
147 rpc_handler_.auth_token_ = auth_token;
150 const ScopedVector<RpcHandler::PendingRequest>& request_queue() const {
151 return rpc_handler_.pending_requests_queue_;
154 void AddInvalidToken(const std::string& token) {
155 rpc_handler_.invalid_audio_token_cache_.Add(token, true);
158 bool TokenIsInvalid(const std::string& token) {
159 return rpc_handler_.invalid_audio_token_cache_.HasKey(token);
162 // For rpc_handler_.invalid_audio_token_cache_
163 base::MessageLoop message_loop_;
165 scoped_ptr<WhispernetClient> whispernet_client_;
166 FakeDirectiveHandler directive_handler_;
167 scoped_ptr<CopresenceStateImpl> state_;
168 RpcHandler rpc_handler_;
170 std::map<bool, std::string> device_id_by_auth_state_;
172 CopresenceStatus status_;
173 std::string rpc_name_;
174 std::string api_key_;
175 std::string auth_token_;
176 ScopedVector<MessageLite> request_protos_;
178 private:
179 void CaptureHttpPost(
180 net::URLRequestContextGetter* url_context_getter,
181 const std::string& rpc_name,
182 const std::string& api_key,
183 const std::string& auth_token,
184 scoped_ptr<MessageLite> request_proto,
185 const RpcHandler::PostCleanupCallback& response_callback) {
186 rpc_name_ = rpc_name;
187 api_key_ = api_key;
188 auth_token_ = auth_token;
189 request_protos_.push_back(request_proto.release());
192 void CaptureStatus(CopresenceStatus status) {
193 status_ = status;
197 TEST_F(RpcHandlerTest, RegisterDevice) {
198 RegisterDevice(false);
199 EXPECT_THAT(request_protos_, SizeIs(1));
200 const RegisterDeviceRequest* registration =
201 static_cast<RegisterDeviceRequest*>(request_protos_[0]);
202 EXPECT_EQ(CHROME, registration->device_identifiers().registrant().type());
204 SetAuthToken("Register auth");
205 RegisterDevice(true);
206 EXPECT_THAT(request_protos_, SizeIs(2));
207 registration = static_cast<RegisterDeviceRequest*>(request_protos_[1]);
208 EXPECT_FALSE(registration->has_device_identifiers());
211 TEST_F(RpcHandlerTest, RequestQueuing) {
212 // Send a report.
213 ReportRequest* report = new ReportRequest;
214 report->mutable_manage_messages_request()->add_id_to_unpublish("unpublish");
215 SendReport(make_scoped_ptr(report), "Q App ID", "Q Auth Token");
216 EXPECT_THAT(request_queue(), SizeIs(1));
217 EXPECT_TRUE(request_queue()[0]->authenticated);
219 // Check for registration request.
220 EXPECT_THAT(request_protos_, SizeIs(1));
221 const RegisterDeviceRequest* registration =
222 static_cast<RegisterDeviceRequest*>(request_protos_[0]);
223 EXPECT_FALSE(registration->device_identifiers().has_registrant());
224 EXPECT_EQ("Q Auth Token", auth_token_);
226 // Send a second report.
227 report = new ReportRequest;
228 report->mutable_manage_subscriptions_request()->add_id_to_unsubscribe(
229 "unsubscribe");
230 SendReport(make_scoped_ptr(report), "Q App ID", "Q Auth Token");
231 EXPECT_THAT(request_protos_, SizeIs(1));
232 EXPECT_THAT(request_queue(), SizeIs(2));
233 EXPECT_TRUE(request_queue()[1]->authenticated);
235 // Send an anonymous report.
236 report = new ReportRequest;
237 report->mutable_update_signals_request()->add_token_observation()
238 ->set_token_id("Q Audio Token");
239 SendReport(make_scoped_ptr(report), "Q App ID", "");
240 EXPECT_THAT(request_queue(), SizeIs(3));
241 EXPECT_FALSE(request_queue()[2]->authenticated);
243 // Check for another registration request.
244 EXPECT_THAT(request_protos_, SizeIs(2));
245 registration = static_cast<RegisterDeviceRequest*>(request_protos_[1]);
246 EXPECT_TRUE(registration->device_identifiers().has_registrant());
247 EXPECT_EQ("", auth_token_);
249 // Respond to the first registration.
250 SendRegisterResponse(true, "Q Auth Device ID");
251 EXPECT_EQ("Q Auth Device ID", device_id_by_auth_state_[true]);
253 // Check that queued reports are sent.
254 EXPECT_THAT(request_protos_, SizeIs(4));
255 EXPECT_THAT(request_queue(), SizeIs(1));
256 EXPECT_THAT(directive_handler_.removed_directives(),
257 ElementsAre("unpublish", "unsubscribe"));
258 report = static_cast<ReportRequest*>(request_protos_[2]);
259 EXPECT_EQ("unpublish", report->manage_messages_request().id_to_unpublish(0));
260 report = static_cast<ReportRequest*>(request_protos_[3]);
261 EXPECT_EQ("unsubscribe",
262 report->manage_subscriptions_request().id_to_unsubscribe(0));
264 // Respond to the second registration.
265 SendRegisterResponse(false, "Q Anonymous Device ID");
266 EXPECT_EQ("Q Anonymous Device ID", device_id_by_auth_state_[false]);
268 // Check for last report.
269 EXPECT_THAT(request_protos_, SizeIs(5));
270 EXPECT_TRUE(request_queue().empty());
271 report = static_cast<ReportRequest*>(request_protos_[4]);
272 EXPECT_EQ("Q Audio Token",
273 report->update_signals_request().token_observation(0).token_id());
276 TEST_F(RpcHandlerTest, CreateRequestHeader) {
277 device_id_by_auth_state_[true] = "CreateRequestHeader Device ID";
278 SendReport(make_scoped_ptr(new ReportRequest),
279 "CreateRequestHeader App",
280 "CreateRequestHeader Auth Token");
282 EXPECT_EQ(RpcHandler::kReportRequestRpcName, rpc_name_);
283 EXPECT_EQ("CreateRequestHeader App API Key", api_key_);
284 EXPECT_EQ("CreateRequestHeader Auth Token", auth_token_);
285 const ReportRequest* report = static_cast<ReportRequest*>(request_protos_[0]);
286 EXPECT_EQ(kChromeVersion,
287 report->header().framework_version().version_name());
288 EXPECT_EQ("CreateRequestHeader App",
289 report->header().client_version().client());
290 EXPECT_EQ("CreateRequestHeader Device ID",
291 report->header().registered_device_id());
292 EXPECT_EQ(CHROME_PLATFORM_TYPE,
293 report->header().device_fingerprint().type());
296 TEST_F(RpcHandlerTest, ReportTokens) {
297 std::vector<AudioToken> test_tokens;
298 test_tokens.push_back(AudioToken("token 1", false));
299 test_tokens.push_back(AudioToken("token 2", false));
300 test_tokens.push_back(AudioToken("token 3", true));
301 AddInvalidToken("token 2");
303 device_id_by_auth_state_[false] = "ReportTokens Anonymous Device";
304 device_id_by_auth_state_[true] = "ReportTokens Auth Device";
305 SetAuthToken("ReportTokens Auth");
307 rpc_handler_.ReportTokens(test_tokens);
308 EXPECT_EQ(RpcHandler::kReportRequestRpcName, rpc_name_);
309 EXPECT_EQ(" API Key", api_key_);
310 EXPECT_THAT(request_protos_, SizeIs(2));
311 const ReportRequest* report = static_cast<ReportRequest*>(request_protos_[0]);
312 RepeatedPtrField<TokenObservation> tokens_sent =
313 report->update_signals_request().token_observation();
314 EXPECT_THAT(tokens_sent, ElementsAre(
315 Property(&TokenObservation::token_id, "token 1"),
316 Property(&TokenObservation::token_id, "token 3"),
317 Property(&TokenObservation::token_id, "current audible"),
318 Property(&TokenObservation::token_id, "current inaudible")));
321 TEST_F(RpcHandlerTest, ReportResponseHandler) {
322 // Fail on HTTP status != 200.
323 scoped_ptr<ReportResponse> response(new ReportResponse);
324 status_ = SUCCESS;
325 SendReportResponse(net::HTTP_BAD_REQUEST, response.Pass());
326 EXPECT_EQ(FAIL, status_);
328 // Construct a test ReportResponse.
329 response.reset(new ReportResponse);
330 response->mutable_header()->mutable_status()->set_code(OK);
331 UpdateSignalsResponse* update_response =
332 response->mutable_update_signals_response();
333 update_response->set_status(util::error::OK);
334 Token* invalid_token = update_response->add_token();
335 invalid_token->set_id("bad token");
336 invalid_token->set_status(INVALID);
337 update_response->add_directive()->set_subscription_id("Subscription 1");
338 update_response->add_directive()->set_subscription_id("Subscription 2");
340 // Check processing.
341 status_ = FAIL;
342 SendReportResponse(net::HTTP_OK, response.Pass());
343 EXPECT_EQ(SUCCESS, status_);
344 EXPECT_TRUE(TokenIsInvalid("bad token"));
345 EXPECT_THAT(directive_handler_.added_directives(),
346 ElementsAre("Subscription 1", "Subscription 2"));
349 } // namespace copresence