Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: chrome/browser/extensions/api/cast_channel/cast_channel_apitest.cc

Issue 395333003: Extensions: Move cast_channel and hid APIs to extensions/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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 "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/files/file_path.h"
8 #include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h"
9 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/extension_function_test_utils.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/common/extensions/api/cast_channel.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "extensions/common/switches.h"
17 #include "net/base/capturing_net_log.h"
18 #include "net/base/completion_callback.h"
19 #include "net/base/net_errors.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gmock_mutant.h"
22
23 namespace cast_channel = extensions::api::cast_channel;
24 using cast_channel::CastSocket;
25 using cast_channel::ChannelError;
26 using cast_channel::MessageInfo;
27 using cast_channel::ReadyState;
28 using extensions::Extension;
29
30 namespace utils = extension_function_test_utils;
31
32 using ::testing::_;
33 using ::testing::A;
34 using ::testing::DoAll;
35 using ::testing::Invoke;
36 using ::testing::InSequence;
37 using ::testing::Return;
38
39 namespace {
40
41 const char kTestExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
42 const int64 kTimeoutMs = 10000;
43
44 static void FillMessageInfo(MessageInfo* message_info,
45 const std::string& message) {
46 message_info->namespace_ = "foo";
47 message_info->source_id = "src";
48 message_info->destination_id = "dest";
49 message_info->data.reset(new base::StringValue(message));
50 }
51
52 ACTION_TEMPLATE(InvokeCompletionCallback,
53 HAS_1_TEMPLATE_PARAMS(int, k),
54 AND_1_VALUE_PARAMS(result)) {
55 ::std::tr1::get<k>(args).Run(result);
56 }
57
58 ACTION_P2(InvokeDelegateOnError, api_test, api) {
59 api_test->CallOnError(api);
60 }
61
62 class MockCastSocket : public CastSocket {
63 public:
64 explicit MockCastSocket(CastSocket::Delegate* delegate,
65 net::IPEndPoint ip_endpoint,
66 net::NetLog* net_log)
67 : CastSocket(kTestExtensionId, ip_endpoint,
68 cast_channel::CHANNEL_AUTH_TYPE_SSL, delegate, net_log,
69 base::TimeDelta::FromMilliseconds(kTimeoutMs)) {}
70 virtual ~MockCastSocket() {}
71
72 virtual bool CalledOnValidThread() const OVERRIDE {
73 // Always return true in testing.
74 return true;
75 }
76
77 MOCK_METHOD1(Connect, void(const net::CompletionCallback& callback));
78 MOCK_METHOD2(SendMessage, void(const MessageInfo& message,
79 const net::CompletionCallback& callback));
80 MOCK_METHOD1(Close, void(const net::CompletionCallback& callback));
81 MOCK_CONST_METHOD0(ready_state, cast_channel::ReadyState());
82 MOCK_CONST_METHOD0(error_state, cast_channel::ChannelError());
83 };
84
85 } // namespace
86
87 class CastChannelAPITest : public ExtensionApiTest {
88 public:
89 CastChannelAPITest() {}
90
91 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
92 ExtensionApiTest::SetUpCommandLine(command_line);
93 command_line->AppendSwitchASCII(
94 extensions::switches::kWhitelistedExtensionID,
95 kTestExtensionId);
96 }
97
98 void SetUpMockCastSocket() {
99 extensions::CastChannelAPI* api = GetApi();
100 net::IPAddressNumber ip_number;
101 net::ParseIPLiteralToNumber("192.168.1.1", &ip_number);
102 net::IPEndPoint ip_endpoint(ip_number, 8009);
103 mock_cast_socket_ = new MockCastSocket(api, ip_endpoint,
104 &capturing_net_log_);
105 // Transfers ownership of the socket.
106 api->SetSocketForTest(
107 make_scoped_ptr<CastSocket>(mock_cast_socket_).Pass());
108
109 // Set expectations on error_state().
110 EXPECT_CALL(*mock_cast_socket_, error_state())
111 .WillRepeatedly(Return(cast_channel::CHANNEL_ERROR_NONE));
112 }
113
114 extensions::CastChannelAPI* GetApi() {
115 return extensions::CastChannelAPI::Get(profile());
116 }
117
118 void CallOnError(extensions::CastChannelAPI* api) {
119 api->OnError(mock_cast_socket_,
120 cast_channel::CHANNEL_ERROR_CONNECT_ERROR);
121 }
122
123 protected:
124 void CallOnMessage(const std::string& message) {
125 content::BrowserThread::PostTask(
126 content::BrowserThread::IO,
127 FROM_HERE,
128 base::Bind(&CastChannelAPITest::DoCallOnMessage, this,
129 GetApi(), mock_cast_socket_, message));
130 }
131
132 void DoCallOnMessage(extensions::CastChannelAPI* api,
133 MockCastSocket* cast_socket,
134 const std::string& message) {
135 MessageInfo message_info;
136 FillMessageInfo(&message_info, message);
137 api->OnMessage(cast_socket, message_info);
138 }
139
140 extensions::CastChannelOpenFunction* CreateOpenFunction(
141 scoped_refptr<Extension> extension) {
142 extensions::CastChannelOpenFunction* cast_channel_open_function =
143 new extensions::CastChannelOpenFunction;
144 cast_channel_open_function->set_extension(extension.get());
145 return cast_channel_open_function;
146 }
147
148 extensions::CastChannelSendFunction* CreateSendFunction(
149 scoped_refptr<Extension> extension) {
150 extensions::CastChannelSendFunction* cast_channel_send_function =
151 new extensions::CastChannelSendFunction;
152 cast_channel_send_function->set_extension(extension.get());
153 return cast_channel_send_function;
154 }
155
156 MockCastSocket* mock_cast_socket_;
157 net::CapturingNetLog capturing_net_log_;
158 };
159
160 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
161 // always return true without actually running the test. Remove when fixed.
162 #if defined(OS_WIN) && !defined(NDEBUG)
163 #define MAYBE_TestOpenSendClose DISABLED_TestOpenSendClose
164 #else
165 #define MAYBE_TestOpenSendClose TestOpenSendClose
166 #endif
167 // Test loading extension, opening a channel with ConnectInfo, adding a
168 // listener, writing, reading, and closing.
169 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenSendClose) {
170 SetUpMockCastSocket();
171
172 {
173 InSequence dummy;
174 EXPECT_CALL(*mock_cast_socket_, Connect(_))
175 .WillOnce(InvokeCompletionCallback<0>(net::OK));
176 EXPECT_CALL(*mock_cast_socket_, ready_state())
177 .WillOnce(Return(cast_channel::READY_STATE_OPEN));
178 EXPECT_CALL(*mock_cast_socket_, SendMessage(A<const MessageInfo&>(), _))
179 .WillOnce(InvokeCompletionCallback<1>(net::OK));
180 EXPECT_CALL(*mock_cast_socket_, ready_state())
181 .WillOnce(Return(cast_channel::READY_STATE_OPEN));
182 EXPECT_CALL(*mock_cast_socket_, Close(_))
183 .WillOnce(InvokeCompletionCallback<0>(net::OK));
184 EXPECT_CALL(*mock_cast_socket_, ready_state())
185 .WillOnce(Return(cast_channel::READY_STATE_CLOSED));
186 }
187
188 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
189 "test_open_send_close.html"));
190 }
191
192 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
193 // always return true without actually running the test. Remove when fixed.
194 #if defined(OS_WIN) && !defined(NDEBUG)
195 #define MAYBE_TestOpenSendCloseWithUrl DISABLED_TestOpenSendCloseWithUrl
196 #else
197 #define MAYBE_TestOpenSendCloseWithUrl TestOpenSendCloseWithUrl
198 #endif
199 // Test loading extension, opening a channel with a URL, adding a listener,
200 // writing, reading, and closing.
201 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenSendCloseWithUrl) {
202 SetUpMockCastSocket();
203
204 {
205 InSequence dummy;
206 EXPECT_CALL(*mock_cast_socket_, Connect(_))
207 .WillOnce(InvokeCompletionCallback<0>(net::OK));
208 EXPECT_CALL(*mock_cast_socket_, ready_state())
209 .WillOnce(Return(cast_channel::READY_STATE_OPEN));
210 EXPECT_CALL(*mock_cast_socket_, SendMessage(A<const MessageInfo&>(), _))
211 .WillOnce(InvokeCompletionCallback<1>(net::OK));
212 EXPECT_CALL(*mock_cast_socket_, ready_state())
213 .WillOnce(Return(cast_channel::READY_STATE_OPEN));
214 EXPECT_CALL(*mock_cast_socket_, Close(_))
215 .WillOnce(InvokeCompletionCallback<0>(net::OK));
216 EXPECT_CALL(*mock_cast_socket_, ready_state())
217 .WillOnce(Return(cast_channel::READY_STATE_CLOSED));
218 }
219
220 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
221 "test_open_send_close_url.html"));
222 }
223
224 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
225 // always return true without actually running the test. Remove when fixed.
226 #if defined(OS_WIN) && !defined(NDEBUG)
227 #define MAYBE_TestOpenReceiveClose DISABLED_TestOpenReceiveClose
228 #else
229 #define MAYBE_TestOpenReceiveClose TestOpenReceiveClose
230 #endif
231 // Test loading extension, opening a channel, adding a listener,
232 // writing, reading, and closing.
233 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenReceiveClose) {
234 SetUpMockCastSocket();
235
236 {
237 InSequence dummy;
238 EXPECT_CALL(*mock_cast_socket_, Connect(_))
239 .WillOnce(InvokeCompletionCallback<0>(net::OK));
240 EXPECT_CALL(*mock_cast_socket_, ready_state())
241 .Times(3)
242 .WillRepeatedly(Return(cast_channel::READY_STATE_OPEN));
243 EXPECT_CALL(*mock_cast_socket_, Close(_))
244 .WillOnce(InvokeCompletionCallback<0>(net::OK));
245 EXPECT_CALL(*mock_cast_socket_, ready_state())
246 .WillOnce(Return(cast_channel::READY_STATE_CLOSED));
247 }
248
249 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
250 "test_open_receive_close.html"));
251
252 ResultCatcher catcher;
253 CallOnMessage("some-message");
254 CallOnMessage("some-message");
255 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
256 }
257
258 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
259 // always return true without actually running the test. Remove when fixed.
260 // Flaky on mac: crbug.com/393969
261 #if (defined(OS_WIN) && !defined(NDEBUG)) || defined(OS_MACOSX)
262 #define MAYBE_TestOpenError DISABLED_TestOpenError
263 #else
264 #define MAYBE_TestOpenError TestOpenError
265 #endif
266 // Test the case when socket open results in an error.
267 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenError) {
268 SetUpMockCastSocket();
269
270 EXPECT_CALL(*mock_cast_socket_, Connect(_))
271 .WillOnce(DoAll(
272 InvokeDelegateOnError(this, GetApi()),
273 InvokeCompletionCallback<0>(net::ERR_FAILED)));
274 EXPECT_CALL(*mock_cast_socket_, ready_state())
275 .WillRepeatedly(Return(cast_channel::READY_STATE_CLOSED));
276 EXPECT_CALL(*mock_cast_socket_, Close(_));
277
278 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
279 "test_open_error.html"));
280
281 ResultCatcher catcher;
282 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
283 }
284
285 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, TestOpenInvalidConnectInfo) {
286 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension());
287 scoped_refptr<extensions::CastChannelOpenFunction> cast_channel_open_function;
288
289 // Invalid URL
290 // TODO(mfoltz): Remove this test case when fixing crbug.com/331905
291 cast_channel_open_function = CreateOpenFunction(empty_extension);
292 std::string error(utils::RunFunctionAndReturnError(
293 cast_channel_open_function.get(), "[\"blargh\"]", browser()));
294 EXPECT_EQ(error, "Invalid connect_info (invalid Cast URL blargh)");
295
296 // Wrong type
297 // TODO(mfoltz): Remove this test case when fixing crbug.com/331905
298 cast_channel_open_function = CreateOpenFunction(empty_extension);
299 error = utils::RunFunctionAndReturnError(
300 cast_channel_open_function.get(),
301 "[123]", browser());
302 EXPECT_EQ(error, "Invalid connect_info (unknown type)");
303
304 // Invalid IP address
305 cast_channel_open_function = CreateOpenFunction(empty_extension);
306 error = utils::RunFunctionAndReturnError(
307 cast_channel_open_function.get(),
308 "[{\"ipAddress\": \"invalid_ip\", \"port\": 8009, \"auth\": \"ssl\"}]",
309 browser());
310 EXPECT_EQ(error, "Invalid connect_info (invalid IP address)");
311
312 // Invalid port
313 cast_channel_open_function = CreateOpenFunction(empty_extension);
314 error = utils::RunFunctionAndReturnError(
315 cast_channel_open_function.get(),
316 "[{\"ipAddress\": \"127.0.0.1\", \"port\": -200, \"auth\": \"ssl\"}]",
317 browser());
318 EXPECT_EQ(error, "Invalid connect_info (invalid port)");
319
320 // Auth not set
321 cast_channel_open_function = CreateOpenFunction(empty_extension);
322 error = utils::RunFunctionAndReturnError(
323 cast_channel_open_function.get(),
324 "[{\"ipAddress\": \"127.0.0.1\", \"port\": 8009}]",
325 browser());
326 EXPECT_EQ(error, "connect_info.auth is required");
327 }
328
329 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, TestSendInvalidMessageInfo) {
330 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension());
331 scoped_refptr<extensions::CastChannelSendFunction> cast_channel_send_function;
332
333 // Numbers are not supported
334 cast_channel_send_function = CreateSendFunction(empty_extension);
335 std::string error(utils::RunFunctionAndReturnError(
336 cast_channel_send_function.get(),
337 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
338 "\"connectInfo\": "
339 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
340 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
341 "{\"namespace_\": \"foo\", \"sourceId\": \"src\", "
342 "\"destinationId\": \"dest\", \"data\": 1235}]",
343 browser()));
344 EXPECT_EQ(error, "Invalid type of message_info.data");
345
346 // Missing namespace_
347 cast_channel_send_function = CreateSendFunction(empty_extension);
348 error = utils::RunFunctionAndReturnError(
349 cast_channel_send_function.get(),
350 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
351 "\"connectInfo\": "
352 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
353 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
354 "{\"namespace_\": \"\", \"sourceId\": \"src\", "
355 "\"destinationId\": \"dest\", \"data\": \"data\"}]",
356 browser());
357 EXPECT_EQ(error, "message_info.namespace_ is required");
358
359 // Missing source_id
360 cast_channel_send_function = CreateSendFunction(empty_extension);
361 error = utils::RunFunctionAndReturnError(
362 cast_channel_send_function.get(),
363 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
364 "\"connectInfo\": "
365 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
366 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
367 "{\"namespace_\": \"foo\", \"sourceId\": \"\", "
368 "\"destinationId\": \"dest\", \"data\": \"data\"}]",
369 browser());
370 EXPECT_EQ(error, "message_info.source_id is required");
371
372 // Missing destination_id
373 cast_channel_send_function = CreateSendFunction(empty_extension);
374 error = utils::RunFunctionAndReturnError(
375 cast_channel_send_function.get(),
376 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
377 "\"connectInfo\": "
378 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
379 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
380 "{\"namespace_\": \"foo\", \"sourceId\": \"src\", "
381 "\"destinationId\": \"\", \"data\": \"data\"}]",
382 browser());
383 EXPECT_EQ(error, "message_info.destination_id is required");
384 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698