Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chrome_frame / test / automation_client_mock.cc
blob347a04160c1d0364048c4d5efaed16f221f76ef3
1 // Copyright (c) 2012 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 "chrome_frame/test/automation_client_mock.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "chrome/common/automation_messages.h"
10 #include "chrome_frame/custom_sync_call_context.h"
11 #include "chrome_frame/navigation_constraints.h"
12 #include "chrome_frame/test/chrome_frame_test_utils.h"
13 #include "chrome_frame/test/test_scrubber.h"
14 #include "net/base/net_errors.h"
16 #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
17 #include "testing/gmock_mutant.h"
19 using testing::_;
20 using testing::CreateFunctor;
21 using testing::Return;
23 namespace {
25 #ifndef NDEBUG
26 const base::TimeDelta kChromeLaunchTimeout = base::TimeDelta::FromSeconds(15);
27 #else
28 const base::TimeDelta kChromeLaunchTimeout = base::TimeDelta::FromSeconds(10);
29 #endif
31 const int kSaneAutomationTimeoutMs = 10 * 1000;
33 } // namespace
35 MATCHER_P(LaunchParamProfileEq, profile_name, "Check for profile name") {
36 return arg->profile_name().compare(profile_name) == 0;
39 void MockProxyFactory::GetServerImpl(ChromeFrameAutomationProxy* pxy,
40 void* proxy_id,
41 AutomationLaunchResult result,
42 LaunchDelegate* d,
43 ChromeFrameLaunchParams* params,
44 void** automation_server_id) {
45 *automation_server_id = proxy_id;
46 loop_->PostDelayedTask(FROM_HERE,
47 base::Bind(&LaunchDelegate::LaunchComplete,
48 base::Unretained(d), pxy, result),
49 base::TimeDelta::FromMilliseconds(params->launch_timeout()) / 2);
52 void CFACMockTest::SetAutomationServerOk(int times) {
53 EXPECT_CALL(factory_, GetAutomationServer(testing::NotNull(),
54 LaunchParamProfileEq(profile_path_.BaseName().value()),
55 testing::NotNull()))
56 .Times(times)
57 .WillRepeatedly(testing::Invoke(CreateFunctor(&factory_,
58 &MockProxyFactory::GetServerImpl, get_proxy(), id_,
59 AUTOMATION_SUCCESS)));
61 EXPECT_CALL(factory_,
62 ReleaseAutomationServer(testing::Eq(id_), testing::NotNull()))
63 .Times(times);
66 void CFACMockTest::Set_CFD_LaunchFailed(AutomationLaunchResult result) {
67 EXPECT_CALL(cfd_, OnAutomationServerLaunchFailed(testing::Eq(result),
68 testing::_))
69 .Times(1)
70 .WillOnce(QUIT_LOOP(loop_));
73 MATCHER_P(MsgType, msg_type, "IPC::Message::type()") {
74 const IPC::Message& m = arg;
75 return (m.type() == msg_type);
78 MATCHER_P(EqNavigationInfoUrl, url, "IPC::NavigationInfo matcher") {
79 if (url.is_valid() && url != arg.url)
80 return false;
81 // TODO(stevet): other members
82 return true;
85 // Could be implemented as MockAutomationProxy member (we have WithArgs<>!)
86 ACTION_P4(HandleCreateTab, tab_handle, external_tab_container, tab_wnd,
87 session_id) {
88 // arg0 - message
89 // arg1 - callback
90 // arg2 - key
91 CreateExternalTabContext::output_type input_args(tab_wnd,
92 external_tab_container,
93 tab_handle,
94 session_id);
95 CreateExternalTabContext* context =
96 reinterpret_cast<CreateExternalTabContext*>(arg1);
97 DispatchToMethod(context, &CreateExternalTabContext::Completed, input_args);
98 delete context;
101 ACTION_P4(InitiateNavigation, client, url, referrer, constraints) {
102 client->InitiateNavigation(url, referrer, constraints);
105 // ChromeFrameAutomationClient tests that launch Chrome.
106 class CFACWithChrome : public testing::Test {
107 protected:
108 static void SetUpTestCase();
109 static void TearDownTestCase();
111 virtual void SetUp() OVERRIDE;
112 virtual void TearDown() OVERRIDE;
114 static base::FilePath profile_path_;
115 MockCFDelegate cfd_;
116 scoped_refptr<ChromeFrameAutomationClient> client_;
117 scoped_refptr<ChromeFrameLaunchParams> launch_params_;
118 chrome_frame_test::TimedMsgLoop loop_;
121 // static
122 base::FilePath CFACWithChrome::profile_path_;
124 // static
125 void CFACWithChrome::SetUpTestCase() {
126 GetChromeFrameProfilePath(L"Adam.N.Epilinter", &profile_path_);
129 // static
130 void CFACWithChrome::TearDownTestCase() {
131 profile_path_.clear();
134 void CFACWithChrome::SetUp() {
135 chrome_frame_test::OverrideDataDirectoryForThisTest(profile_path_.value());
136 client_ = new ChromeFrameAutomationClient();
137 GURL empty;
138 launch_params_ = new ChromeFrameLaunchParams(
139 empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
140 false, false, false, false);
141 launch_params_->set_version_check(false);
142 launch_params_->set_launch_timeout(kSaneAutomationTimeoutMs);
145 void CFACWithChrome::TearDown() {
146 client_->Uninitialize();
149 // We mock ChromeFrameDelegate only. The rest is with real AutomationProxy
150 TEST_F(CFACWithChrome, CreateTooFast) {
151 int timeout = 0; // Chrome cannot send Hello message so fast.
153 EXPECT_CALL(cfd_, OnAutomationServerLaunchFailed(AUTOMATION_TIMEOUT, _))
154 .WillOnce(QUIT_LOOP(loop_));
156 launch_params_->set_launch_timeout(timeout);
157 EXPECT_TRUE(client_->Initialize(&cfd_, launch_params_));
158 loop_.RunFor(kChromeLaunchTimeout);
161 // This test may fail if Chrome take more that 10 seconds (timeout var) to
162 // launch. In this case GMock shall print something like "unexpected call to
163 // OnAutomationServerLaunchFailed". I'm yet to find out how to specify
164 // that this is an unexpected call, and still to execute an action.
165 TEST_F(CFACWithChrome, CreateNotSoFast) {
166 EXPECT_CALL(cfd_, OnAutomationServerReady())
167 .WillOnce(QUIT_LOOP(loop_));
169 EXPECT_CALL(cfd_, OnAutomationServerLaunchFailed(_, _))
170 .Times(0);
172 EXPECT_TRUE(client_->Initialize(&cfd_, launch_params_));
174 loop_.RunFor(kChromeLaunchTimeout);
177 TEST_F(CFACWithChrome, NavigateOk) {
178 NavigationConstraintsImpl navigation_constraints;
180 const std::string url = "about:version";
182 EXPECT_CALL(cfd_, OnAutomationServerReady())
183 .WillOnce(InitiateNavigation(client_.get(), url, std::string(),
184 &navigation_constraints));
186 EXPECT_CALL(cfd_, GetBounds(_)).Times(testing::AnyNumber());
188 EXPECT_CALL(cfd_, OnNavigationStateChanged(_))
189 .Times(testing::AnyNumber());
192 testing::InSequence s;
194 EXPECT_CALL(cfd_, OnDidNavigate(EqNavigationInfoUrl(GURL())))
195 .Times(1);
197 EXPECT_CALL(cfd_, OnUpdateTargetUrl(_)).Times(testing::AtMost(1));
199 EXPECT_CALL(cfd_, OnLoad(_))
200 .WillOnce(QUIT_LOOP(loop_));
203 EXPECT_TRUE(client_->Initialize(&cfd_, launch_params_));
204 loop_.RunFor(kChromeLaunchTimeout);
207 TEST_F(CFACWithChrome, NavigateFailed) {
208 NavigationConstraintsImpl navigation_constraints;
209 const std::string url = "http://127.0.0.3:65412/";
210 const net::URLRequestStatus connection_failed(net::URLRequestStatus::FAILED,
211 net::ERR_INVALID_URL);
213 cfd_.SetRequestDelegate(client_);
215 EXPECT_CALL(cfd_, OnAutomationServerReady())
216 .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
217 client_.get(), &ChromeFrameAutomationClient::InitiateNavigation,
218 url, std::string(), &navigation_constraints))));
220 EXPECT_CALL(cfd_, GetBounds(_)).Times(testing::AnyNumber());
221 EXPECT_CALL(cfd_, OnNavigationStateChanged(_)).Times(testing::AnyNumber());
223 EXPECT_CALL(cfd_, OnRequestStart(_, _))
224 // Often there's another request for the error page
225 .Times(testing::Between(1, 2))
226 .WillRepeatedly(testing::WithArgs<0>(testing::Invoke(CreateFunctor(&cfd_,
227 &MockCFDelegate::Reply, connection_failed))));
229 EXPECT_CALL(cfd_, OnUpdateTargetUrl(_)).Times(testing::AnyNumber());
230 EXPECT_CALL(cfd_, OnLoad(_)).Times(testing::AtMost(1));
232 EXPECT_CALL(cfd_, OnNavigationFailed(_, GURL(url)))
233 .Times(1)
234 .WillOnce(QUIT_LOOP_SOON(loop_, base::TimeDelta::FromSeconds(2)));
236 EXPECT_TRUE(client_->Initialize(&cfd_, launch_params_));
238 loop_.RunFor(kChromeLaunchTimeout);
241 TEST_F(CFACMockTest, MockedCreateTabOk) {
242 int timeout = 500;
243 CreateTab();
244 SetAutomationServerOk(1);
246 EXPECT_CALL(mock_proxy_, server_version()).Times(testing::AnyNumber())
247 .WillRepeatedly(Return(""));
249 // We need some valid HWNDs, when responding to CreateExternalTab
250 HWND h1 = ::GetDesktopWindow();
251 HWND h2 = ::GetDesktopWindow();
252 EXPECT_CALL(mock_proxy_, SendAsAsync(testing::Property(
253 &IPC::SyncMessage::type, AutomationMsg_CreateExternalTab::ID),
254 testing::NotNull(), _))
255 .Times(1).WillOnce(HandleCreateTab(tab_handle_, h1, h2, 99));
257 EXPECT_CALL(mock_proxy_, CreateTabProxy(testing::Eq(tab_handle_)))
258 .WillOnce(Return(tab_));
260 EXPECT_CALL(cfd_, OnAutomationServerReady())
261 .WillOnce(QUIT_LOOP(loop_));
263 EXPECT_CALL(mock_proxy_, CancelAsync(_)).Times(testing::AnyNumber());
265 // Here we go!
266 GURL empty;
267 scoped_refptr<ChromeFrameLaunchParams> clp(new ChromeFrameLaunchParams(
268 empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
269 false, false, false, false));
270 clp->set_launch_timeout(timeout);
271 clp->set_version_check(false);
272 EXPECT_TRUE(client_->Initialize(&cfd_, clp));
273 loop_.RunFor(base::TimeDelta::FromSeconds(10));
275 EXPECT_CALL(mock_proxy_, ReleaseTabProxy(testing::Eq(tab_handle_))).Times(1);
276 client_->Uninitialize();
279 TEST_F(CFACMockTest, MockedCreateTabFailed) {
280 HWND null_wnd = NULL;
281 SetAutomationServerOk(1);
283 EXPECT_CALL(mock_proxy_, server_version()).Times(testing::AnyNumber())
284 .WillRepeatedly(Return(""));
286 EXPECT_CALL(mock_proxy_, SendAsAsync(testing::Property(
287 &IPC::SyncMessage::type, AutomationMsg_CreateExternalTab::ID),
288 testing::NotNull(), _))
289 .Times(1).WillOnce(HandleCreateTab(tab_handle_, null_wnd, null_wnd,
290 99));
292 EXPECT_CALL(mock_proxy_, CreateTabProxy(_)).Times(0);
294 EXPECT_CALL(mock_proxy_, CancelAsync(_)).Times(testing::AnyNumber());
296 Set_CFD_LaunchFailed(AUTOMATION_CREATE_TAB_FAILED);
298 // Here we go!
299 GURL empty;
300 scoped_refptr<ChromeFrameLaunchParams> clp(new ChromeFrameLaunchParams(
301 empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
302 false, false, false, false));
303 clp->set_launch_timeout(timeout_);
304 clp->set_version_check(false);
305 EXPECT_TRUE(client_->Initialize(&cfd_, clp));
306 loop_.RunFor(base::TimeDelta::FromSeconds(4));
307 client_->Uninitialize();
310 class TestChromeFrameAutomationProxyImpl
311 : public ChromeFrameAutomationProxyImpl {
312 public:
313 TestChromeFrameAutomationProxyImpl()
314 // 1 is an unneeded timeout.
315 : ChromeFrameAutomationProxyImpl(
316 NULL,
317 AutomationProxy::GenerateChannelID(),
318 base::TimeDelta::FromMilliseconds(1)) {
320 MOCK_METHOD3(
321 SendAsAsync,
322 void(IPC::SyncMessage* msg,
323 SyncMessageReplyDispatcher::SyncMessageCallContext* context,
324 void* key));
325 void FakeChannelError() {
326 reinterpret_cast<IPC::ChannelProxy::MessageFilter*>(message_filter_.get())->
327 OnChannelError();
331 TEST_F(CFACMockTest, OnChannelErrorEmpty) {
332 TestChromeFrameAutomationProxyImpl proxy;
334 // No tabs should do nothing yet still not fail either.
335 proxy.FakeChannelError();
338 TEST_F(CFACMockTest, OnChannelError) {
339 const base::TimeDelta loop_duration = base::TimeDelta::FromSeconds(11);
340 TestChromeFrameAutomationProxyImpl proxy;
341 returned_proxy_ = &proxy;
343 GURL empty;
344 scoped_refptr<ChromeFrameLaunchParams> clp(new ChromeFrameLaunchParams(
345 empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
346 false, false, false, false));
347 clp->set_launch_timeout(1); // Unneeded timeout, but can't be 0.
348 clp->set_version_check(false);
350 HWND h1 = ::GetDesktopWindow();
351 HWND h2 = ::GetDesktopWindow();
352 EXPECT_CALL(proxy, SendAsAsync(testing::Property(
353 &IPC::SyncMessage::type, AutomationMsg_CreateExternalTab::ID),
354 testing::NotNull(), _)).Times(3)
355 .WillOnce(HandleCreateTab(tab_handle_, h1, h2, 99))
356 .WillOnce(HandleCreateTab(tab_handle_ * 2, h1, h2, 100))
357 .WillOnce(HandleCreateTab(tab_handle_ * 3, h1, h2, 101));
359 SetAutomationServerOk(3);
361 // First, try a single tab and make sure the notification find its way to the
362 // Chrome Frame Delegate.
363 StrictMock<MockCFDelegate> cfd1;
364 scoped_refptr<ChromeFrameAutomationClient> client1;
365 client1 = new ChromeFrameAutomationClient;
366 client1->set_proxy_factory(&factory_);
368 EXPECT_CALL(cfd1, OnAutomationServerReady()).WillOnce(QUIT_LOOP(loop_));
369 EXPECT_TRUE(client1->Initialize(&cfd1, clp));
370 // Wait for OnAutomationServerReady to be called in the UI thread.
371 loop_.RunFor(loop_duration);
373 proxy.FakeChannelError();
374 EXPECT_CALL(cfd1, OnChannelError()).WillOnce(QUIT_LOOP(loop_));
375 // Wait for OnChannelError to be propagated to delegate from the UI thread.
376 loop_.RunFor(loop_duration);
378 // Add a second tab using a different delegate.
379 StrictMock<MockCFDelegate> cfd2;
380 scoped_refptr<ChromeFrameAutomationClient> client2;
381 client2 = new ChromeFrameAutomationClient;
382 client2->set_proxy_factory(&factory_);
384 EXPECT_CALL(cfd2, OnAutomationServerReady()).WillOnce(QUIT_LOOP(loop_));
385 EXPECT_TRUE(client2->Initialize(&cfd2, clp));
386 // Wait for OnAutomationServerReady to be called in the UI thread.
387 loop_.RunFor(loop_duration);
389 EXPECT_CALL(cfd1, OnChannelError()).Times(1);
390 EXPECT_CALL(cfd2, OnChannelError()).WillOnce(QUIT_LOOP(loop_));
391 proxy.FakeChannelError();
392 // Wait for OnChannelError to be propagated to delegate from the UI thread.
393 loop_.RunFor(loop_duration);
395 // And now a 3rd tab using the first delegate.
396 scoped_refptr<ChromeFrameAutomationClient> client3;
397 client3 = new ChromeFrameAutomationClient;
398 client3->set_proxy_factory(&factory_);
400 EXPECT_CALL(cfd1, OnAutomationServerReady()).WillOnce(QUIT_LOOP(loop_));
401 EXPECT_TRUE(client3->Initialize(&cfd1, clp));
402 // Wait for OnAutomationServerReady to be called in the UI thread.
403 loop_.RunFor(loop_duration);
405 EXPECT_CALL(cfd2, OnChannelError()).Times(1);
406 EXPECT_CALL(cfd1, OnChannelError()).Times(2).WillOnce(Return())
407 .WillOnce(QUIT_LOOP(loop_));
408 proxy.FakeChannelError();
409 // Wait for OnChannelError to be propagated to delegate from the UI thread.
410 loop_.RunFor(loop_duration);
412 // Cleanup.
413 client1->Uninitialize();
414 client2->Uninitialize();
415 client3->Uninitialize();
416 client1 = NULL;
417 client2 = NULL;
418 client3 = NULL;
421 TEST_F(CFACMockTest, NavigateTwiceAfterInitToSameUrl) {
422 int timeout = 500;
423 NavigationConstraintsImpl navigation_constraints;
425 CreateTab();
426 SetAutomationServerOk(1);
428 EXPECT_CALL(mock_proxy_, server_version()).Times(testing::AnyNumber())
429 .WillRepeatedly(Return(""));
431 // We need some valid HWNDs, when responding to CreateExternalTab
432 HWND h1 = ::GetDesktopWindow();
433 HWND h2 = ::GetDesktopWindow();
434 EXPECT_CALL(mock_proxy_, SendAsAsync(testing::Property(
435 &IPC::SyncMessage::type, AutomationMsg_CreateExternalTab::ID),
436 testing::NotNull(), _))
437 .Times(1).WillOnce(HandleCreateTab(tab_handle_, h1, h2, 99));
439 EXPECT_CALL(mock_proxy_, CreateTabProxy(testing::Eq(tab_handle_)))
440 .WillOnce(Return(tab_));
442 EXPECT_CALL(cfd_, OnAutomationServerReady())
443 .WillOnce(InitiateNavigation(client_.get(),
444 std::string("http://www.nonexistent.com"),
445 std::string(), &navigation_constraints));
447 EXPECT_CALL(mock_proxy_, SendAsAsync(testing::Property(
448 &IPC::SyncMessage::type, AutomationMsg_NavigateInExternalTab::ID),
449 testing::NotNull(), _))
450 .Times(1).WillOnce(QUIT_LOOP(loop_));
452 EXPECT_CALL(mock_proxy_, CancelAsync(_)).Times(testing::AnyNumber());
454 EXPECT_CALL(mock_proxy_, Send(
455 testing::Property(&IPC::Message::type, AutomationMsg_TabReposition::ID)))
456 .Times(1)
457 .WillOnce(Return(true));
459 EXPECT_CALL(cfd_, GetBounds(_)).Times(1);
461 // Here we go!
462 GURL empty;
463 scoped_refptr<ChromeFrameLaunchParams> launch_params(
464 new ChromeFrameLaunchParams(
465 GURL("http://www.nonexistent.com"), empty, profile_path_,
466 profile_path_.BaseName().value(), L"", false, false, false, false));
467 launch_params->set_launch_timeout(timeout);
468 launch_params->set_version_check(false);
469 EXPECT_TRUE(client_->Initialize(&cfd_, launch_params));
470 loop_.RunFor(base::TimeDelta::FromSeconds(10));
472 EXPECT_CALL(mock_proxy_, ReleaseTabProxy(testing::Eq(tab_handle_))).Times(1);
473 client_->Uninitialize();