Index: chrome/test/base/ui_test_utils.cc |
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc |
index 44aed98add084ddcb03d67a39670b0c2d9c6c975..c0e136d8eaa2fd12a2619d292dfb62a0a21ed364 100644 |
--- a/chrome/test/base/ui_test_utils.cc |
+++ b/chrome/test/base/ui_test_utils.cc |
@@ -4,6 +4,10 @@ |
#include "chrome/test/base/ui_test_utils.h" |
+#if defined(OS_WIN) |
+#include <windows.h> |
+#endif |
+ |
#include <vector> |
#include "base/bind.h" |
@@ -16,6 +20,7 @@ |
#include "base/message_loop.h" |
#include "base/path_service.h" |
#include "base/process_util.h" |
+#include "base/string_number_conversions.h" |
#include "base/utf_string_conversions.h" |
#include "base/values.h" |
#include "chrome/browser/automation/ui_controls.h" |
@@ -62,6 +67,8 @@ |
#include "ui/aura/desktop.h" |
#endif |
+static const int kDefaultWsPort = 8880; |
+ |
namespace ui_test_utils { |
namespace { |
@@ -727,7 +734,50 @@ void AppendToPythonPath(const FilePath& dir) { |
} // anonymous namespace |
-TestWebSocketServer::TestWebSocketServer() : started_(false) { |
+#if defined(OS_POSIX) |
+class OrphanedWebSocketServerFilter : public base::ProcessFilter { |
+ public: |
+ OrphanedWebSocketServerFilter(std::string script_name, std::string port) |
Yuta Kitamura
2011/11/23 06:06:09
Arguments should be typed as const std::string&, b
Takashi Toyoshima
2011/11/23 08:53:32
Done.
|
+ : script_name_(script_name), |
+ port_(port) {} |
+ |
+ virtual bool Includes(const base::ProcessEntry& entry) const { |
+ // The parent process of orphaned WebSocket servers must be root process. |
+ if (entry.parent_pid() != 1) |
+ return false; |
+ |
+ // Python script name must be ended with specified script name. |
+ const std::string &script_name = entry.cmd_line_args()[2]; |
+ if (script_name.find_last_of(script_name_) != script_name.size() - 1) |
+ return false; |
+ |
+ // Check if an argument sequence like "--port 8880" exist. |
Yuta Kitamura
2011/11/23 06:06:09
nit: exist -> exists.
Takashi Toyoshima
2011/11/23 08:53:32
Done.
|
+ bool found = false; |
+ for (std::vector<std::string>::const_iterator it = |
+ entry.cmd_line_args().begin(); |
+ it != entry.cmd_line_args().end(); |
+ ++it) { |
+ if (*it == "--port") { |
+ ++it; |
+ if (it == entry.cmd_line_args().end() && *it == port_) { |
+ found = true; |
+ break; |
+ } |
+ } |
+ } |
+ return found; |
+ } |
+ |
+ private: |
+ std::string script_name_; |
+ std::string port_; |
+ DISALLOW_COPY_AND_ASSIGN(OrphanedWebSocketServerFilter); |
+}; |
+#endif |
+ |
+TestWebSocketServer::TestWebSocketServer() |
+ : started_(false), |
+ process_handle_(base::kNullProcessHandle) { |
Yuta Kitamura
2011/11/23 06:06:09
Don't you have to guard process_handle_ with #if d
Takashi Toyoshima
2011/11/23 08:53:32
Oh, right!
Nice catch.
|
} |
bool TestWebSocketServer::Start(const FilePath& root_directory) { |
@@ -740,6 +790,7 @@ bool TestWebSocketServer::Start(const FilePath& root_directory) { |
cmd_line->AppendArg("--register_cygwin"); |
cmd_line->AppendArgNative(FILE_PATH_LITERAL("--root=") + |
root_directory.value()); |
+ cmd_line->AppendArg("--port=" + base::IntToString(kDefaultWsPort)); |
if (!temp_dir_.CreateUniqueTempDir()) { |
LOG(ERROR) << "Unable to create a temporary directory."; |
return false; |
@@ -748,9 +799,41 @@ bool TestWebSocketServer::Start(const FilePath& root_directory) { |
cmd_line->AppendArgNative(FILE_PATH_LITERAL("--pidfile=") + |
websocket_pid_file_.value()); |
SetPythonPath(); |
+ |
base::LaunchOptions options; |
+ |
+#if defined(OS_POSIX) |
+ // Try to kill any orphaned WebSocket server processes that may be running. |
+ OrphanedWebSocketServerFilter filter("standalone.py", |
+ base::IntToString(kDefaultWsPort)); |
+ if (!base::KillProcesses("python", -1, &filter)) |
Yuta Kitamura
2011/11/23 06:06:09
nit: Add curly braces if the content of a block sp
Takashi Toyoshima
2011/11/23 08:53:32
Done.
|
+ LOG(WARNING) << |
+ "Failed to clean up older orphaned WebSocket server instance."; |
+ |
+ options.new_process_group = true; |
+#elif defined(OS_WIN) |
+ job_handle_.Set(CreateJobObject(NULL, NULL)); |
+ if (!job_handle_.IsValid()) { |
+ LOG(ERROR) << "Could not create JobObject."; |
+ return false; |
+ } |
+ |
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; |
+ limit_info.BasicLimitInformation.LimitFlags = |
+ JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; |
+ if (0 == SetInformationJobObject(job_handle_.Get(), |
Yuta Kitamura
2011/11/23 06:06:09
nit: Prefer (x == 0) over (0 == x). Maybe it's bet
Takashi Toyoshima
2011/11/23 08:53:32
For now, other four place use this exactly same id
|
+ JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info))) { |
+ LOG(ERROR) << "Could not SetInformationJobObject."; |
+ return false; |
+ } |
+ |
+ options.inherit_handles = true; |
+ options.job_handle = job_handle_.Get(); |
+#endif |
+ |
+ // Launch a new WebSocket server process. |
options.wait = true; |
- if (!base::LaunchProcess(*cmd_line.get(), options, NULL)) { |
+ if (!base::LaunchProcess(*cmd_line.get(), options, &process_handle_)) { |
Yuta Kitamura
2011/11/23 06:06:09
Same here for #if defined(OS_POSIX) for process_ha
Takashi Toyoshima
2011/11/23 08:53:32
Done.
|
LOG(ERROR) << "Unable to launch websocket server."; |
return false; |
} |
@@ -805,6 +888,9 @@ TestWebSocketServer::~TestWebSocketServer() { |
base::LaunchOptions options; |
options.wait = true; |
base::LaunchProcess(*cmd_line.get(), options, NULL); |
+ |
+ // Just to make sure that the server process terminates certainly. |
+ base::KillProcessGroup(process_handle_); |
Yuta Kitamura
2011/11/23 06:06:09
Ditto.
Takashi Toyoshima
2011/11/23 08:53:32
Done.
|
} |
TestNotificationObserver::TestNotificationObserver() |