Index: chrome/browser/process_singleton_uitest.cc |
=================================================================== |
--- chrome/browser/process_singleton_uitest.cc (revision 49343) |
+++ chrome/browser/process_singleton_uitest.cc (working copy) |
@@ -1,27 +1,27 @@ |
-// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
// This test validates that the ProcessSingleton class properly makes sure |
// that there is only one main browser process. |
// |
-// It is currently compiled and ran on the windows platform only but has been |
-// written in a platform independent way (using the process/threads/sync |
-// routines from base). So it does compile fine on Mac and Linux but fails to |
-// launch the app and thus have not been tested for success/failures. Since it |
-// was written to validate a change made to fix a bug only seen on Windows, it |
-// was left as is until it gets to be needed on the other platforms. |
+// It is currently compiled and run on Windows and Posix(non-Mac) platforms. |
+// Mac uses system services and ProcessSingletonMac is a noop. (Maybe it still |
+// makes sense to test that the system services are giving the behavior we |
+// want?) |
- |
#include <list> |
#include "base/file_path.h" |
#include "base/file_util.h" |
+#include "base/path_service.h" |
#include "base/process_util.h" |
#include "base/ref_counted.h" |
#include "base/thread.h" |
#include "base/waitable_event.h" |
+#include "chrome/common/chrome_paths.h" |
#include "chrome/common/chrome_constants.h" |
+#include "chrome/common/chrome_switches.h" |
#include "chrome/test/ui/ui_test.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -46,19 +46,30 @@ |
void Reset() { |
ready_event_.Reset(); |
done_event_.Reset(); |
- if (process_handle_ != NULL) |
+ if (process_handle_ != base::kNullProcessHandle) |
base::CloseProcessHandle(process_handle_); |
- process_handle_ = NULL; |
+ process_handle_ = base::kNullProcessHandle; |
process_terminated_ = false; |
} |
- void StartChrome(base::WaitableEvent* start_event) { |
- // TODO(port): For some reason the LaunchApp call below fails even though |
- // we use the platform independent constant for the executable path. |
- // This is the current blocker for running this test on Mac & Linux. |
- CommandLine command_line(FilePath::FromWStringHack( |
- chrome::kBrowserProcessExecutablePath)); |
+ void StartChrome(base::WaitableEvent* start_event, bool first_run) { |
+ // TODO(mattm): maybe stuff should be refactored to use |
+ // UITest::LaunchBrowserHelper somehow? |
+ FilePath browser_directory; |
+ PathService::Get(chrome::DIR_APP, &browser_directory); |
+ CommandLine command_line(browser_directory.Append( |
+ FilePath::FromWStringHack(chrome::kBrowserProcessExecutablePath))); |
+ FilePath user_data_directory; |
+ PathService::Get(chrome::DIR_USER_DATA, &user_data_directory); |
+ command_line.AppendSwitchWithValue(switches::kUserDataDir, |
+ user_data_directory.ToWStringHack()); |
+ |
+ if (first_run) |
+ command_line.AppendSwitch(switches::kFirstRun); |
+ else |
+ command_line.AppendSwitch(switches::kNoFirstRun); |
+ |
// Try to get all threads to launch the app at the same time. |
// So let the test know we are ready. |
ready_event_.Signal(); |
@@ -71,7 +82,7 @@ |
// wait here, we would never get a handle to the main process... |
base::LaunchApp(command_line, false /* wait */, |
false /* hidden */, &process_handle_); |
- ASSERT_NE(static_cast<base::ProcessHandle>(NULL), process_handle_); |
+ ASSERT_NE(base::kNullProcessHandle, process_handle_); |
// We can wait on the handle here, we should get stuck on one and only |
// one process. The test below will take care of killing that process |
@@ -92,7 +103,7 @@ |
friend class base::RefCountedThreadSafe<ChromeStarter>; |
~ChromeStarter() { |
- if (process_handle_ != NULL) |
+ if (process_handle_ != base::kNullProcessHandle) |
base::CloseProcessHandle(process_handle_); |
} |
@@ -102,9 +113,9 @@ |
}; |
// Our test fixture that initializes and holds onto a few global vars. |
-class ProcessSingletonWinTest : public UITest { |
+class ProcessSingletonTest : public UITest { |
public: |
- ProcessSingletonWinTest() |
+ ProcessSingletonTest() |
// We use a manual reset so that all threads wake up at once when signaled |
// and thus we must manually reset it for each attempt. |
: threads_waker_(true /* manual */, false /* signaled */) { |
@@ -182,8 +193,7 @@ |
base::WaitableEvent threads_waker_; |
}; |
-// http://crbug.com/38572 |
-TEST_F(ProcessSingletonWinTest, FAILS_StartupRaceCondition) { |
+TEST_F(ProcessSingletonTest, StartupRaceCondition) { |
// We use this to stop the attempts loop on the first failure. |
bool failed = false; |
for (size_t attempt = 0; attempt < kNbAttempts && !failed; ++attempt) { |
@@ -192,6 +202,20 @@ |
// time... |
threads_waker_.Reset(); |
+ // Test both with and without the first-run dialog, since they exercise |
+ // different paths. |
+#if defined(OS_POSIX) |
+ // TODO(mattm): test first run dialog singleton handling on linux too. |
+ // On posix if we test the first run dialog, GracefulShutdownHandler gets |
+ // the TERM signal, but since the message loop isn't running during the gtk |
+ // first run dialog, the ShutdownDetector never handles it, and KillProcess |
+ // has to time out (60 sec!) and SIGKILL. |
+ bool first_run = false; |
+#else |
+ // Test for races in both regular start up and first run start up cases. |
+ bool first_run = attempt % 2; |
+#endif |
+ |
// Here we prime all the threads with a ChromeStarter that will wait for |
// our signal to launch its chrome process. |
for (size_t i = 0; i < kNbThreads; ++i) { |
@@ -205,7 +229,8 @@ |
chrome_starter_threads_[i]->message_loop()->PostTask( |
FROM_HERE, NewRunnableMethod(chrome_starters_[i].get(), |
&ChromeStarter::StartChrome, |
- &threads_waker_)); |
+ &threads_waker_, |
+ first_run)); |
} |
// Wait for all the starters to be ready. |
@@ -249,7 +274,8 @@ |
failed = true; |
// But we let the last loop turn finish so that we can properly |
// kill all remaining processes. Starting with this one... |
- if (chrome_starters_[starter_index]->process_handle_ != NULL) { |
+ if (chrome_starters_[starter_index]->process_handle_ != |
+ base::kNullProcessHandle) { |
KillProcessTree(chrome_starters_[starter_index]->process_handle_); |
} |
} |
@@ -260,7 +286,8 @@ |
ASSERT_EQ(static_cast<size_t>(1), pending_starters.size()); |
size_t last_index = pending_starters.front(); |
pending_starters.empty(); |
- if (chrome_starters_[last_index]->process_handle_ != NULL) { |
+ if (chrome_starters_[last_index]->process_handle_ != |
+ base::kNullProcessHandle) { |
KillProcessTree(chrome_starters_[last_index]->process_handle_); |
chrome_starters_[last_index]->done_event_.Wait(); |
} |
Property changes on: chrome/browser/process_singleton_uitest.cc |
___________________________________________________________________ |
Added: svn:mergeinfo |