| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 // Create a service process that uses a Mock to respond to the browser in order | 5 // Create a service process that uses a Mock to respond to the browser in order |
| 6 // to test launching the browser using the cloud print policy check command | 6 // to test launching the browser using the cloud print policy check command |
| 7 // line switch. | 7 // line switch. |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/process_util.h" | 12 #include "base/process_util.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/test/multiprocess_test.h" | 14 #include "base/test/multiprocess_test.h" |
| 15 #include "base/test/test_timeouts.h" | 15 #include "base/test/test_timeouts.h" |
| 16 #include "base/time.h" | 16 #include "base/time.h" |
| 17 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" | 17 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" |
| 18 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.
h" | 18 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.
h" |
| 19 #include "chrome/browser/profiles/profile_keyed_service.h" | 19 #include "chrome/browser/profiles/profile_keyed_service.h" |
| 20 #include "chrome/browser/service/service_process_control.h" | 20 #include "chrome/browser/service/service_process_control.h" |
| 21 #include "chrome/browser/ui/browser_init.h" | 21 #include "chrome/browser/ui/browser_init.h" |
| 22 #include "chrome/common/chrome_notification_types.h" | |
| 23 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
| 24 #include "chrome/common/pref_names.h" | 23 #include "chrome/common/pref_names.h" |
| 25 #include "chrome/common/service_messages.h" | 24 #include "chrome/common/service_messages.h" |
| 26 #include "chrome/common/service_process_util.h" | 25 #include "chrome/common/service_process_util.h" |
| 27 #include "chrome/service/service_ipc_server.h" | 26 #include "chrome/service/service_ipc_server.h" |
| 28 #include "chrome/service/service_process.h" | 27 #include "chrome/service/service_process.h" |
| 29 #include "chrome/test/base/test_launcher_utils.h" | 28 #include "chrome/test/base/test_launcher_utils.h" |
| 30 #include "chrome/test/base/testing_browser_process.h" | 29 #include "chrome/test/base/testing_browser_process.h" |
| 31 #include "chrome/test/base/testing_pref_service.h" | 30 #include "chrome/test/base/testing_pref_service.h" |
| 32 #include "chrome/test/base/testing_profile.h" | 31 #include "chrome/test/base/testing_profile.h" |
| 33 #include "chrome/test/base/testing_profile_manager.h" | 32 #include "chrome/test/base/testing_profile_manager.h" |
| 34 #include "chrome/test/base/ui_test_utils.h" | 33 #include "chrome/test/base/ui_test_utils.h" |
| 35 #include "content/public/browser/notification_service.h" | 34 #include "content/public/browser/notification_service.h" |
| 36 #include "content/test/test_browser_thread.h" | 35 #include "content/test/test_browser_thread.h" |
| 37 #include "ipc/ipc_descriptors.h" | 36 #include "ipc/ipc_descriptors.h" |
| 38 #include "ipc/ipc_switches.h" | 37 #include "ipc/ipc_switches.h" |
| 39 #include "testing/gmock/include/gmock/gmock.h" | 38 #include "testing/gmock/include/gmock/gmock.h" |
| 40 #include "testing/gtest/include/gtest/gtest.h" | 39 #include "testing/gtest/include/gtest/gtest.h" |
| 41 #include "testing/multiprocess_func_list.h" | 40 #include "testing/multiprocess_func_list.h" |
| 42 | 41 |
| 42 #if defined(OS_MACOSX) |
| 43 #include "chrome/common/mac/mock_launchd.h" |
| 44 #endif |
| 43 #if defined(OS_POSIX) | 45 #if defined(OS_POSIX) |
| 44 #include "base/global_descriptors_posix.h" | 46 #include "base/global_descriptors_posix.h" |
| 45 #endif | 47 #endif |
| 46 | 48 |
| 47 using ::testing::AnyNumber; | 49 using ::testing::AnyNumber; |
| 48 using ::testing::Assign; | 50 using ::testing::Assign; |
| 49 using ::testing::AtLeast; | 51 using ::testing::AtLeast; |
| 50 using ::testing::DoAll; | 52 using ::testing::DoAll; |
| 51 using ::testing::Invoke; | 53 using ::testing::Invoke; |
| 52 using ::testing::Mock; | 54 using ::testing::Mock; |
| 53 using ::testing::Property; | 55 using ::testing::Property; |
| 54 using ::testing::Return; | 56 using ::testing::Return; |
| 55 using ::testing::WithoutArgs; | 57 using ::testing::WithoutArgs; |
| 56 using ::testing::_; | 58 using ::testing::_; |
| 57 | 59 |
| 58 namespace { | 60 namespace { |
| 59 | 61 |
| 62 enum MockServiceProcessExitCodes { |
| 63 kMissingSwitch = 1, |
| 64 kInitializationFailure, |
| 65 kExpectationsNotMet, |
| 66 kShutdownNotGood |
| 67 }; |
| 68 |
| 69 #if defined(OS_MACOSX) |
| 70 const char kTestExecutablePath[] = "test-executable-path"; |
| 71 #endif |
| 72 |
| 60 bool g_good_shutdown = false; | 73 bool g_good_shutdown = false; |
| 61 | 74 |
| 62 void ShutdownTask() { | 75 void ShutdownTask() { |
| 63 g_good_shutdown = true; | 76 g_good_shutdown = true; |
| 64 g_service_process->Shutdown(); | 77 g_service_process->Shutdown(); |
| 65 } | 78 } |
| 66 | 79 |
| 67 class TestStartupClientChannelListener : public IPC::Channel::Listener { | 80 class TestStartupClientChannelListener : public IPC::Channel::Listener { |
| 68 public: | 81 public: |
| 69 virtual bool OnMessageReceived(const IPC::Message& message) { return false; } | 82 virtual bool OnMessageReceived(const IPC::Message& message) { return false; } |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 info_.enabled = false; | 188 info_.enabled = false; |
| 176 info_.email = std::string(); | 189 info_.email = std::string(); |
| 177 EXPECT_TRUE(Send(new ServiceHostMsg_CloudPrintProxy_Info(info_))); | 190 EXPECT_TRUE(Send(new ServiceHostMsg_CloudPrintProxy_Info(info_))); |
| 178 } | 191 } |
| 179 return true; | 192 return true; |
| 180 } | 193 } |
| 181 | 194 |
| 182 typedef base::Callback<void(MockServiceIPCServer* server)> | 195 typedef base::Callback<void(MockServiceIPCServer* server)> |
| 183 SetExpectationsCallback; | 196 SetExpectationsCallback; |
| 184 | 197 |
| 198 // The return value from this routine is used as the exit code for the mock |
| 199 // service process. Any non-zero return value will be printed out and can help |
| 200 // determine the failure. |
| 185 int CloudPrintMockService_Main(SetExpectationsCallback set_expectations) { | 201 int CloudPrintMockService_Main(SetExpectationsCallback set_expectations) { |
| 186 MessageLoopForUI main_message_loop; | 202 MessageLoopForUI main_message_loop; |
| 187 main_message_loop.set_thread_name("Main Thread"); | 203 main_message_loop.set_thread_name("Main Thread"); |
| 188 | 204 |
| 205 #if defined(OS_MACOSX) |
| 206 CommandLine* cl = CommandLine::ForCurrentProcess(); |
| 207 if (!cl->HasSwitch(kTestExecutablePath)) |
| 208 return kMissingSwitch; |
| 209 FilePath executable_path = cl->GetSwitchValuePath(kTestExecutablePath); |
| 210 EXPECT_FALSE(executable_path.empty()); |
| 211 MockLaunchd mock_launchd(executable_path, &main_message_loop, true, true); |
| 212 Launchd::ScopedInstance use_mock(&mock_launchd); |
| 213 #endif |
| 214 |
| 189 ServiceProcessState* state(new ServiceProcessState); | 215 ServiceProcessState* state(new ServiceProcessState); |
| 190 EXPECT_TRUE(state->Initialize()); | 216 bool service_process_state_initialized = state->Initialize(); |
| 217 EXPECT_TRUE(service_process_state_initialized); |
| 218 if (!service_process_state_initialized) |
| 219 return kInitializationFailure; |
| 191 | 220 |
| 192 TestServiceProcess service_process; | 221 TestServiceProcess service_process; |
| 193 EXPECT_EQ(&service_process, g_service_process); | 222 EXPECT_EQ(&service_process, g_service_process); |
| 194 | 223 |
| 195 // Takes ownership of the pointer, but we can use it since we have the same | 224 // Takes ownership of the pointer, but we can use it since we have the same |
| 196 // lifetime. | 225 // lifetime. |
| 197 EXPECT_TRUE(service_process.Initialize(&main_message_loop, state)); | 226 EXPECT_TRUE(service_process.Initialize(&main_message_loop, state)); |
| 198 | 227 |
| 199 MockServiceIPCServer server(state->GetServiceProcessChannel()); | 228 MockServiceIPCServer server(state->GetServiceProcessChannel()); |
| 200 | 229 |
| 201 // Here is where the expectations/mock responses need to be set up. | 230 // Here is where the expectations/mock responses need to be set up. |
| 202 set_expectations.Run(&server); | 231 set_expectations.Run(&server); |
| 203 | 232 |
| 204 EXPECT_TRUE(server.Init()); | 233 EXPECT_TRUE(server.Init()); |
| 205 EXPECT_TRUE(state->SignalReady(service_process.IOMessageLoopProxy(), | 234 EXPECT_TRUE(state->SignalReady(service_process.IOMessageLoopProxy(), |
| 206 base::Bind(&ShutdownTask))); | 235 base::Bind(&ShutdownTask))); |
| 236 #if defined(OS_MACOSX) |
| 237 mock_launchd.SignalReady(); |
| 238 #endif |
| 207 | 239 |
| 208 // Connect up the parent/child IPC channel to signal that the test can | 240 // Connect up the parent/child IPC channel to signal that the test can |
| 209 // continue. | 241 // continue. |
| 210 TestStartupClientChannelListener listener; | 242 TestStartupClientChannelListener listener; |
| 211 EXPECT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch( | 243 EXPECT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch( |
| 212 switches::kProcessChannelID)); | 244 switches::kProcessChannelID)); |
| 213 std::string startup_channel_name = | 245 std::string startup_channel_name = |
| 214 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 246 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 215 switches::kProcessChannelID); | 247 switches::kProcessChannelID); |
| 216 scoped_ptr<IPC::ChannelProxy> startup_channel; | 248 scoped_ptr<IPC::ChannelProxy> startup_channel; |
| 217 startup_channel.reset( | 249 startup_channel.reset( |
| 218 new IPC::ChannelProxy(startup_channel_name, | 250 new IPC::ChannelProxy(startup_channel_name, |
| 219 IPC::Channel::MODE_CLIENT, | 251 IPC::Channel::MODE_CLIENT, |
| 220 &listener, | 252 &listener, |
| 221 service_process.IOMessageLoopProxy())); | 253 service_process.IOMessageLoopProxy())); |
| 222 | 254 |
| 223 main_message_loop.Run(); | 255 main_message_loop.Run(); |
| 224 if (!Mock::VerifyAndClearExpectations(&server)) | 256 if (!Mock::VerifyAndClearExpectations(&server)) |
| 225 return 1; | 257 return kExpectationsNotMet; |
| 226 if (!g_good_shutdown) | 258 if (!g_good_shutdown) |
| 227 return 2; | 259 return kShutdownNotGood; |
| 228 return 0; | 260 return 0; |
| 229 } | 261 } |
| 230 | 262 |
| 231 void SetServiceEnabledExpectations(MockServiceIPCServer* server) { | 263 void SetServiceEnabledExpectations(MockServiceIPCServer* server) { |
| 232 server->SetServiceEnabledExpectations(); | 264 server->SetServiceEnabledExpectations(); |
| 233 } | 265 } |
| 234 | 266 |
| 235 MULTIPROCESS_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit) { | 267 MULTIPROCESS_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit) { |
| 236 return CloudPrintMockService_Main( | 268 return CloudPrintMockService_Main( |
| 237 base::Bind(&SetServiceEnabledExpectations)); | 269 base::Bind(&SetServiceEnabledExpectations)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 } | 310 } |
| 279 | 311 |
| 280 protected: | 312 protected: |
| 281 MessageLoopForUI message_loop_; | 313 MessageLoopForUI message_loop_; |
| 282 content::TestBrowserThread ui_thread_; | 314 content::TestBrowserThread ui_thread_; |
| 283 base::Thread io_thread_; | 315 base::Thread io_thread_; |
| 284 | 316 |
| 285 std::string startup_channel_id_; | 317 std::string startup_channel_id_; |
| 286 scoped_ptr<IPC::ChannelProxy> startup_channel_; | 318 scoped_ptr<IPC::ChannelProxy> startup_channel_; |
| 287 | 319 |
| 320 #if defined(OS_MACOSX) |
| 321 ScopedTempDir temp_dir_; |
| 322 FilePath executable_path_, bundle_path_; |
| 323 scoped_ptr<MockLaunchd> mock_launchd_; |
| 324 scoped_ptr<Launchd::ScopedInstance> scoped_launchd_instance_; |
| 325 #endif |
| 326 |
| 288 private: | 327 private: |
| 289 class WindowedChannelConnectionObserver { | 328 class WindowedChannelConnectionObserver { |
| 290 public: | 329 public: |
| 291 WindowedChannelConnectionObserver() | 330 WindowedChannelConnectionObserver() |
| 292 : seen_(false), | 331 : seen_(false), |
| 293 running_(false) { } | 332 running_(false) { } |
| 294 | 333 |
| 295 void Wait() { | 334 void Wait() { |
| 296 if (seen_) | 335 if (seen_) |
| 297 return; | 336 return; |
| 298 running_ = true; | 337 running_ = true; |
| 299 ui_test_utils::RunMessageLoop(); | 338 ui_test_utils::RunMessageLoop(); |
| 300 } | 339 } |
| 301 | 340 |
| 302 void Notify() { | 341 void Notify() { |
| 303 seen_ = true; | 342 seen_ = true; |
| 304 if (running_) | 343 if (running_) |
| 305 MessageLoopForUI::current()->Quit(); | 344 MessageLoopForUI::current()->Quit(); |
| 306 } | 345 } |
| 307 | 346 |
| 308 private: | 347 private: |
| 309 bool seen_; | 348 bool seen_; |
| 310 bool running_; | 349 bool running_; |
| 311 }; | 350 }; |
| 312 | 351 |
| 313 WindowedChannelConnectionObserver observer_; | 352 WindowedChannelConnectionObserver observer_; |
| 314 }; | 353 }; |
| 315 | 354 |
| 316 | |
| 317 CloudPrintProxyPolicyStartupTest::CloudPrintProxyPolicyStartupTest() | 355 CloudPrintProxyPolicyStartupTest::CloudPrintProxyPolicyStartupTest() |
| 318 : ui_thread_(content::BrowserThread::UI, &message_loop_), | 356 : ui_thread_(content::BrowserThread::UI, &message_loop_), |
| 319 io_thread_("CloudPrintProxyPolicyTestThread") { | 357 io_thread_("CloudPrintProxyPolicyTestThread") { |
| 320 } | 358 } |
| 321 | 359 |
| 322 CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() { | 360 CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() { |
| 323 } | 361 } |
| 324 | 362 |
| 325 void CloudPrintProxyPolicyStartupTest::SetUp() { | 363 void CloudPrintProxyPolicyStartupTest::SetUp() { |
| 326 base::Thread::Options options(MessageLoop::TYPE_IO, 0); | 364 base::Thread::Options options(MessageLoop::TYPE_IO, 0); |
| 327 ASSERT_TRUE(io_thread_.StartWithOptions(options)); | 365 ASSERT_TRUE(io_thread_.StartWithOptions(options)); |
| 366 |
| 367 #if defined(OS_MACOSX) |
| 368 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 369 EXPECT_TRUE(MockLaunchd::MakeABundle(temp_dir_.path(), |
| 370 "CloudPrintProxyTest", |
| 371 &bundle_path_, |
| 372 &executable_path_)); |
| 373 mock_launchd_.reset(new MockLaunchd(executable_path_, &message_loop_, |
| 374 true, false)); |
| 375 scoped_launchd_instance_.reset( |
| 376 new Launchd::ScopedInstance(mock_launchd_.get())); |
| 377 #endif |
| 328 } | 378 } |
| 329 | 379 |
| 330 base::ProcessHandle CloudPrintProxyPolicyStartupTest::Launch( | 380 base::ProcessHandle CloudPrintProxyPolicyStartupTest::Launch( |
| 331 const std::string& name) { | 381 const std::string& name) { |
| 332 EXPECT_FALSE(CheckServiceProcessReady()); | 382 EXPECT_FALSE(CheckServiceProcessReady()); |
| 333 | 383 |
| 334 startup_channel_id_ = | 384 startup_channel_id_ = |
| 335 base::StringPrintf("%d.%p.%d", | 385 base::StringPrintf("%d.%p.%d", |
| 336 base::GetCurrentProcId(), this, | 386 base::GetCurrentProcId(), this, |
| 337 base::RandInt(0, std::numeric_limits<int>::max())); | 387 base::RandInt(0, std::numeric_limits<int>::max())); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 | 430 |
| 381 void CloudPrintProxyPolicyStartupTest::OnChannelConnected(int32 peer_pid) { | 431 void CloudPrintProxyPolicyStartupTest::OnChannelConnected(int32 peer_pid) { |
| 382 observer_.Notify(); | 432 observer_.Notify(); |
| 383 } | 433 } |
| 384 | 434 |
| 385 CommandLine CloudPrintProxyPolicyStartupTest::MakeCmdLine( | 435 CommandLine CloudPrintProxyPolicyStartupTest::MakeCmdLine( |
| 386 const std::string& procname, | 436 const std::string& procname, |
| 387 bool debug_on_start) { | 437 bool debug_on_start) { |
| 388 CommandLine cl = MultiProcessTest::MakeCmdLine(procname, debug_on_start); | 438 CommandLine cl = MultiProcessTest::MakeCmdLine(procname, debug_on_start); |
| 389 cl.AppendSwitchASCII(switches::kProcessChannelID, startup_channel_id_); | 439 cl.AppendSwitchASCII(switches::kProcessChannelID, startup_channel_id_); |
| 440 #if defined(OS_MACOSX) |
| 441 cl.AppendSwitchASCII(kTestExecutablePath, executable_path_.value()); |
| 442 #endif |
| 390 return cl; | 443 return cl; |
| 391 } | 444 } |
| 392 | 445 |
| 393 TEST_F(CloudPrintProxyPolicyStartupTest, StartAndShutdown) { | 446 TEST_F(CloudPrintProxyPolicyStartupTest, StartAndShutdown) { |
| 394 base::ProcessHandle handle = | 447 base::ProcessHandle handle = |
| 395 Launch("CloudPrintMockService_StartEnabledWaitForQuit"); | 448 Launch("CloudPrintMockService_StartEnabledWaitForQuit"); |
| 396 WaitForConnect(); | 449 WaitForConnect(); |
| 397 ShutdownAndWaitForExitWithTimeout(handle); | 450 ShutdownAndWaitForExitWithTimeout(handle); |
| 398 } | 451 } |
| 399 | 452 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 // No expectations on run_loop being true here; that would be a race | 532 // No expectations on run_loop being true here; that would be a race |
| 480 // condition. | 533 // condition. |
| 481 if (run_loop) | 534 if (run_loop) |
| 482 MessageLoop::current()->Run(); | 535 MessageLoop::current()->Run(); |
| 483 | 536 |
| 484 EXPECT_EQ("", prefs->GetString(prefs::kCloudPrintEmail)); | 537 EXPECT_EQ("", prefs->GetString(prefs::kCloudPrintEmail)); |
| 485 | 538 |
| 486 ShutdownAndWaitForExitWithTimeout(handle); | 539 ShutdownAndWaitForExitWithTimeout(handle); |
| 487 profile_manager.DeleteTestingProfile("StartBrowserWithPolicy"); | 540 profile_manager.DeleteTestingProfile("StartBrowserWithPolicy"); |
| 488 } | 541 } |
| OLD | NEW |