OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/copresence/rpc/rpc_handler.h" | 5 #include "components/copresence/rpc/rpc_handler.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/memory/scoped_vector.h" | 13 #include "base/memory/scoped_vector.h" |
14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
15 #include "components/copresence/handlers/directive_handler.h" | 15 #include "components/copresence/handlers/directive_handler.h" |
16 #include "components/copresence/mediums/audio/audio_manager.h" | 16 #include "components/copresence/mediums/audio/audio_manager.h" |
17 #include "components/copresence/proto/data.pb.h" | 17 #include "components/copresence/proto/data.pb.h" |
18 #include "components/copresence/proto/enums.pb.h" | 18 #include "components/copresence/proto/enums.pb.h" |
19 #include "components/copresence/proto/rpcs.pb.h" | 19 #include "components/copresence/proto/rpcs.pb.h" |
20 #include "net/http/http_status_code.h" | 20 #include "net/http/http_status_code.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gmock/include/gmock/gmock.h" |
22 | 22 |
23 using google::protobuf::MessageLite; | 23 using google::protobuf::MessageLite; |
24 using google::protobuf::RepeatedPtrField; | 24 using google::protobuf::RepeatedPtrField; |
25 | 25 |
| 26 using testing::Property; |
| 27 using testing::SizeIs; |
| 28 using testing::ElementsAre; |
| 29 |
26 namespace copresence { | 30 namespace copresence { |
27 | 31 |
28 namespace { | 32 namespace { |
29 | 33 |
30 const char kChromeVersion[] = "Chrome Version String"; | 34 const char kChromeVersion[] = "Chrome Version String"; |
31 | 35 |
32 void CreateSubscribedMessage(const std::vector<std::string>& subscription_ids, | 36 void CreateSubscribedMessage(const std::vector<std::string>& subscription_ids, |
33 const std::string& message_string, | 37 const std::string& message_string, |
34 SubscribedMessage* message_proto) { | 38 SubscribedMessage* message_proto) { |
35 message_proto->mutable_published_message()->set_payload(message_string); | 39 message_proto->mutable_published_message()->set_payload(message_string); |
36 for (const std::string& subscription_id : subscription_ids) { | 40 for (const std::string& subscription_id : subscription_ids) { |
37 message_proto->add_subscription_id(subscription_id); | 41 message_proto->add_subscription_id(subscription_id); |
38 } | 42 } |
39 } | 43 } |
40 | 44 |
41 // TODO(ckehoe): Make DirectiveHandler an interface. | 45 // TODO(ckehoe): Make DirectiveHandler an interface. |
42 class FakeDirectiveHandler : public DirectiveHandler { | 46 class FakeDirectiveHandler : public DirectiveHandler { |
43 public: | 47 public: |
44 FakeDirectiveHandler() {} | 48 FakeDirectiveHandler() {} |
45 ~FakeDirectiveHandler() override {} | 49 ~FakeDirectiveHandler() override {} |
46 | 50 |
47 const std::vector<Directive>& added_directives() const { | 51 const std::vector<Directive>& added_directives() const { |
48 return added_directives_; | 52 return added_directives_; |
49 } | 53 } |
50 | 54 |
51 void Initialize(const AudioManager::DecodeSamplesCallback& decode_cb, | 55 void Start(WhispernetClient* whispernet_client) override { |
52 const AudioManager::EncodeTokenCallback& encode_cb) override { | 56 NOTREACHED(); |
53 } | 57 } |
54 | 58 |
55 void AddDirective(const Directive& directive) override { | 59 void AddDirective(const Directive& directive) override { |
56 added_directives_.push_back(directive); | 60 added_directives_.push_back(directive); |
57 } | 61 } |
58 | 62 |
59 void RemoveDirectives(const std::string& op_id) override { | 63 void RemoveDirectives(const std::string& op_id) override { |
60 // TODO(ckehoe): Add a parallel implementation when prod has one. | 64 NOTREACHED(); |
| 65 } |
| 66 |
| 67 const std::string GetCurrentAudioToken(AudioType type) const override { |
| 68 return type == AUDIBLE ? "current audible" : "current inaudible"; |
61 } | 69 } |
62 | 70 |
63 private: | 71 private: |
64 std::vector<Directive> added_directives_; | 72 std::vector<Directive> added_directives_; |
65 | 73 |
66 DISALLOW_COPY_AND_ASSIGN(FakeDirectiveHandler); | 74 DISALLOW_COPY_AND_ASSIGN(FakeDirectiveHandler); |
67 }; | 75 }; |
68 | 76 |
69 } // namespace | 77 } // namespace |
70 | 78 |
71 class RpcHandlerTest : public testing::Test, public CopresenceDelegate { | 79 class RpcHandlerTest : public testing::Test, public CopresenceDelegate { |
72 public: | 80 public: |
73 RpcHandlerTest() : rpc_handler_(this), status_(SUCCESS) { | 81 RpcHandlerTest() : rpc_handler_(this, &directive_handler_), status_(SUCCESS) { |
74 rpc_handler_.server_post_callback_ = | 82 rpc_handler_.server_post_callback_ = |
75 base::Bind(&RpcHandlerTest::CaptureHttpPost, base::Unretained(this)); | 83 base::Bind(&RpcHandlerTest::CaptureHttpPost, base::Unretained(this)); |
76 } | 84 } |
77 | 85 |
78 // CopresenceDelegate implementation | 86 // CopresenceDelegate implementation |
79 | 87 |
80 void HandleMessages(const std::string& app_id, | 88 void HandleMessages(const std::string& app_id, |
81 const std::string& subscription_id, | 89 const std::string& subscription_id, |
82 const std::vector<Message>& messages) override { | 90 const std::vector<Message>& messages) override { |
83 // app_id is unused for now, pending a server fix. | 91 // app_id is unused for now, pending a server fix. |
(...skipping 21 matching lines...) Expand all Loading... |
105 protected: | 113 protected: |
106 void InvokeReportResponseHandler(int status_code, | 114 void InvokeReportResponseHandler(int status_code, |
107 const std::string& response) { | 115 const std::string& response) { |
108 rpc_handler_.ReportResponseHandler( | 116 rpc_handler_.ReportResponseHandler( |
109 base::Bind(&RpcHandlerTest::CaptureStatus, base::Unretained(this)), | 117 base::Bind(&RpcHandlerTest::CaptureStatus, base::Unretained(this)), |
110 nullptr, | 118 nullptr, |
111 status_code, | 119 status_code, |
112 response); | 120 response); |
113 } | 121 } |
114 | 122 |
115 FakeDirectiveHandler* InstallFakeDirectiveHandler() { | |
116 FakeDirectiveHandler* handler = new FakeDirectiveHandler; | |
117 rpc_handler_.directive_handler_.reset(handler); | |
118 return handler; | |
119 } | |
120 | |
121 void SetDeviceIdAndAuthToken(const std::string& device_id, | 123 void SetDeviceIdAndAuthToken(const std::string& device_id, |
122 const std::string& auth_token) { | 124 const std::string& auth_token) { |
123 rpc_handler_.device_id_by_auth_token_[auth_token] = device_id; | 125 rpc_handler_.device_id_by_auth_token_[auth_token] = device_id; |
124 auth_token_ = auth_token; | 126 auth_token_ = auth_token; |
125 } | 127 } |
126 | 128 |
127 void AddInvalidToken(const std::string& token) { | 129 void AddInvalidToken(const std::string& token) { |
128 rpc_handler_.invalid_audio_token_cache_.Add(token, true); | 130 rpc_handler_.invalid_audio_token_cache_.Add(token, true); |
129 } | 131 } |
130 | 132 |
131 bool TokenIsInvalid(const std::string& token) { | 133 bool TokenIsInvalid(const std::string& token) { |
132 return rpc_handler_.invalid_audio_token_cache_.HasKey(token); | 134 return rpc_handler_.invalid_audio_token_cache_.HasKey(token); |
133 } | 135 } |
134 | 136 |
135 // For rpc_handler_.invalid_audio_token_cache_ | 137 // For rpc_handler_.invalid_audio_token_cache_ |
136 base::MessageLoop message_loop_; | 138 base::MessageLoop message_loop_; |
137 | 139 |
| 140 FakeDirectiveHandler directive_handler_; |
138 RpcHandler rpc_handler_; | 141 RpcHandler rpc_handler_; |
139 CopresenceStatus status_; | 142 CopresenceStatus status_; |
140 | 143 |
141 std::string rpc_name_; | 144 std::string rpc_name_; |
142 std::string api_key_; | 145 std::string api_key_; |
143 std::string auth_token_; | 146 std::string auth_token_; |
144 ScopedVector<MessageLite> request_protos_; | 147 ScopedVector<MessageLite> request_protos_; |
145 std::map<std::string, std::vector<Message>> messages_by_subscription_; | 148 std::map<std::string, std::vector<Message>> messages_by_subscription_; |
146 | 149 |
147 private: | 150 private: |
(...skipping 11 matching lines...) Expand all Loading... |
159 } | 162 } |
160 | 163 |
161 void CaptureStatus(CopresenceStatus status) { | 164 void CaptureStatus(CopresenceStatus status) { |
162 status_ = status; | 165 status_ = status; |
163 } | 166 } |
164 }; | 167 }; |
165 | 168 |
166 TEST_F(RpcHandlerTest, RegisterDevice) { | 169 TEST_F(RpcHandlerTest, RegisterDevice) { |
167 EXPECT_FALSE(rpc_handler_.IsRegisteredForToken("")); | 170 EXPECT_FALSE(rpc_handler_.IsRegisteredForToken("")); |
168 rpc_handler_.RegisterForToken("", RpcHandler::SuccessCallback()); | 171 rpc_handler_.RegisterForToken("", RpcHandler::SuccessCallback()); |
169 EXPECT_EQ(1u, request_protos_.size()); | 172 EXPECT_THAT(request_protos_, SizeIs(1)); |
170 const RegisterDeviceRequest* registration = | 173 const RegisterDeviceRequest* registration = |
171 static_cast<RegisterDeviceRequest*>(request_protos_[0]); | 174 static_cast<RegisterDeviceRequest*>(request_protos_[0]); |
172 Identity identity = registration->device_identifiers().registrant(); | 175 Identity identity = registration->device_identifiers().registrant(); |
173 EXPECT_EQ(CHROME, identity.type()); | 176 EXPECT_EQ(CHROME, identity.type()); |
174 EXPECT_FALSE(identity.chrome_id().empty()); | 177 EXPECT_FALSE(identity.chrome_id().empty()); |
175 | 178 |
176 EXPECT_FALSE(rpc_handler_.IsRegisteredForToken("abc")); | 179 EXPECT_FALSE(rpc_handler_.IsRegisteredForToken("abc")); |
177 rpc_handler_.RegisterForToken("abc", RpcHandler::SuccessCallback()); | 180 rpc_handler_.RegisterForToken("abc", RpcHandler::SuccessCallback()); |
178 EXPECT_EQ(2u, request_protos_.size()); | 181 EXPECT_THAT(request_protos_, SizeIs(2)); |
179 registration = static_cast<RegisterDeviceRequest*>(request_protos_[1]); | 182 registration = static_cast<RegisterDeviceRequest*>(request_protos_[1]); |
180 EXPECT_FALSE(registration->has_device_identifiers()); | 183 EXPECT_FALSE(registration->has_device_identifiers()); |
181 } | 184 } |
182 | 185 |
183 // TODO(ckehoe): Add a test for RegisterResponseHandler. | 186 // TODO(ckehoe): Add a test for RegisterResponseHandler. |
184 | 187 |
185 TEST_F(RpcHandlerTest, CreateRequestHeader) { | 188 TEST_F(RpcHandlerTest, CreateRequestHeader) { |
186 SetDeviceIdAndAuthToken("CreateRequestHeader Device ID", | 189 SetDeviceIdAndAuthToken("CreateRequestHeader Device ID", |
187 "CreateRequestHeader Auth Token"); | 190 "CreateRequestHeader Auth Token"); |
188 rpc_handler_.SendReportRequest(make_scoped_ptr(new ReportRequest), | 191 rpc_handler_.SendReportRequest(make_scoped_ptr(new ReportRequest), |
(...skipping 10 matching lines...) Expand all Loading... |
199 report->header().client_version().client()); | 202 report->header().client_version().client()); |
200 EXPECT_EQ("CreateRequestHeader Device ID", | 203 EXPECT_EQ("CreateRequestHeader Device ID", |
201 report->header().registered_device_id()); | 204 report->header().registered_device_id()); |
202 EXPECT_EQ(CHROME_PLATFORM_TYPE, | 205 EXPECT_EQ(CHROME_PLATFORM_TYPE, |
203 report->header().device_fingerprint().type()); | 206 report->header().device_fingerprint().type()); |
204 } | 207 } |
205 | 208 |
206 TEST_F(RpcHandlerTest, ReportTokens) { | 209 TEST_F(RpcHandlerTest, ReportTokens) { |
207 std::vector<AudioToken> test_tokens; | 210 std::vector<AudioToken> test_tokens; |
208 test_tokens.push_back(AudioToken("token 1", false)); | 211 test_tokens.push_back(AudioToken("token 1", false)); |
209 test_tokens.push_back(AudioToken("token 2", true)); | 212 test_tokens.push_back(AudioToken("token 2", false)); |
210 test_tokens.push_back(AudioToken("token 3", false)); | 213 test_tokens.push_back(AudioToken("token 3", true)); |
211 AddInvalidToken("token 2"); | 214 AddInvalidToken("token 2"); |
212 | 215 |
213 SetDeviceIdAndAuthToken("ReportTokens Device 1", ""); | 216 SetDeviceIdAndAuthToken("ReportTokens Device 1", ""); |
214 SetDeviceIdAndAuthToken("ReportTokens Device 2", "ReportTokens Auth"); | 217 SetDeviceIdAndAuthToken("ReportTokens Device 2", "ReportTokens Auth"); |
215 | 218 |
216 rpc_handler_.ReportTokens(test_tokens); | 219 rpc_handler_.ReportTokens(test_tokens); |
217 EXPECT_EQ(RpcHandler::kReportRequestRpcName, rpc_name_); | 220 EXPECT_EQ(RpcHandler::kReportRequestRpcName, rpc_name_); |
218 EXPECT_EQ(" API Key", api_key_); | 221 EXPECT_EQ(" API Key", api_key_); |
219 EXPECT_EQ(2u, request_protos_.size()); | 222 EXPECT_THAT(request_protos_, SizeIs(2)); |
220 const ReportRequest* report = static_cast<ReportRequest*>(request_protos_[0]); | 223 const ReportRequest* report = static_cast<ReportRequest*>(request_protos_[0]); |
221 RepeatedPtrField<TokenObservation> tokens_sent = | 224 RepeatedPtrField<TokenObservation> tokens_sent = |
222 report->update_signals_request().token_observation(); | 225 report->update_signals_request().token_observation(); |
223 ASSERT_EQ(2, tokens_sent.size()); | 226 EXPECT_THAT(tokens_sent, ElementsAre( |
224 EXPECT_EQ("token 1", tokens_sent.Get(0).token_id()); | 227 Property(&TokenObservation::token_id, "token 1"), |
225 EXPECT_EQ("token 3", tokens_sent.Get(1).token_id()); | 228 Property(&TokenObservation::token_id, "token 3"), |
| 229 Property(&TokenObservation::token_id, "current audible"), |
| 230 Property(&TokenObservation::token_id, "current inaudible"))); |
226 } | 231 } |
227 | 232 |
228 TEST_F(RpcHandlerTest, ReportResponseHandler) { | 233 TEST_F(RpcHandlerTest, ReportResponseHandler) { |
229 // Fail on HTTP status != 200. | 234 // Fail on HTTP status != 200. |
230 ReportResponse empty_response; | 235 ReportResponse empty_response; |
231 empty_response.mutable_header()->mutable_status()->set_code(OK); | 236 empty_response.mutable_header()->mutable_status()->set_code(OK); |
232 std::string serialized_empty_response; | 237 std::string serialized_empty_response; |
233 ASSERT_TRUE(empty_response.SerializeToString(&serialized_empty_response)); | 238 ASSERT_TRUE(empty_response.SerializeToString(&serialized_empty_response)); |
234 status_ = SUCCESS; | 239 status_ = SUCCESS; |
235 InvokeReportResponseHandler(net::HTTP_BAD_REQUEST, serialized_empty_response); | 240 InvokeReportResponseHandler(net::HTTP_BAD_REQUEST, serialized_empty_response); |
(...skipping 16 matching lines...) Expand all Loading... |
252 CreateSubscribedMessage( | 257 CreateSubscribedMessage( |
253 subscription_1, "Message A", update_response->add_message()); | 258 subscription_1, "Message A", update_response->add_message()); |
254 CreateSubscribedMessage( | 259 CreateSubscribedMessage( |
255 subscription_2, "Message B", update_response->add_message()); | 260 subscription_2, "Message B", update_response->add_message()); |
256 CreateSubscribedMessage( | 261 CreateSubscribedMessage( |
257 both_subscriptions, "Message C", update_response->add_message()); | 262 both_subscriptions, "Message C", update_response->add_message()); |
258 update_response->add_directive()->set_subscription_id("Subscription 1"); | 263 update_response->add_directive()->set_subscription_id("Subscription 1"); |
259 update_response->add_directive()->set_subscription_id("Subscription 2"); | 264 update_response->add_directive()->set_subscription_id("Subscription 2"); |
260 | 265 |
261 messages_by_subscription_.clear(); | 266 messages_by_subscription_.clear(); |
262 FakeDirectiveHandler* directive_handler = InstallFakeDirectiveHandler(); | |
263 std::string serialized_proto; | 267 std::string serialized_proto; |
264 ASSERT_TRUE(test_response.SerializeToString(&serialized_proto)); | 268 ASSERT_TRUE(test_response.SerializeToString(&serialized_proto)); |
265 status_ = FAIL; | 269 status_ = FAIL; |
266 InvokeReportResponseHandler(net::HTTP_OK, serialized_proto); | 270 InvokeReportResponseHandler(net::HTTP_OK, serialized_proto); |
267 | 271 |
268 EXPECT_EQ(SUCCESS, status_); | 272 EXPECT_EQ(SUCCESS, status_); |
269 EXPECT_TRUE(TokenIsInvalid("bad token")); | 273 EXPECT_TRUE(TokenIsInvalid("bad token")); |
270 ASSERT_EQ(2U, messages_by_subscription_.size()); | |
271 ASSERT_EQ(2U, messages_by_subscription_["Subscription 1"].size()); | |
272 ASSERT_EQ(2U, messages_by_subscription_["Subscription 2"].size()); | |
273 EXPECT_EQ("Message A", | |
274 messages_by_subscription_["Subscription 1"][0].payload()); | |
275 EXPECT_EQ("Message B", | |
276 messages_by_subscription_["Subscription 2"][0].payload()); | |
277 EXPECT_EQ("Message C", | |
278 messages_by_subscription_["Subscription 1"][1].payload()); | |
279 EXPECT_EQ("Message C", | |
280 messages_by_subscription_["Subscription 2"][1].payload()); | |
281 | 274 |
282 ASSERT_EQ(2U, directive_handler->added_directives().size()); | 275 EXPECT_THAT(messages_by_subscription_["Subscription 1"], ElementsAre( |
283 EXPECT_EQ("Subscription 1", | 276 Property(&Message::payload, "Message A"), |
284 directive_handler->added_directives()[0].subscription_id()); | 277 Property(&Message::payload, "Message C"))); |
285 EXPECT_EQ("Subscription 2", | 278 |
286 directive_handler->added_directives()[1].subscription_id()); | 279 EXPECT_THAT(messages_by_subscription_["Subscription 2"], ElementsAre( |
| 280 Property(&Message::payload, "Message B"), |
| 281 Property(&Message::payload, "Message C"))); |
| 282 |
| 283 EXPECT_THAT(directive_handler_.added_directives(), ElementsAre( |
| 284 Property(&Directive::subscription_id, "Subscription 1"), |
| 285 Property(&Directive::subscription_id, "Subscription 2"))); |
287 } | 286 } |
288 | 287 |
289 } // namespace copresence | 288 } // namespace copresence |
OLD | NEW |