| Index: chrome/browser/process_singleton_linux_unittest.cc
|
| diff --git a/chrome/browser/process_singleton_linux_unittest.cc b/chrome/browser/process_singleton_linux_unittest.cc
|
| deleted file mode 100644
|
| index 689a2dfaf1e0c0e07d07f8c6dc564c3fa191cccf..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/process_singleton_linux_unittest.cc
|
| +++ /dev/null
|
| @@ -1,393 +0,0 @@
|
| -// Copyright (c) 2012 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.
|
| -
|
| -#include "chrome/browser/process_singleton.h"
|
| -
|
| -#include <signal.h>
|
| -#include <sys/types.h>
|
| -#include <sys/wait.h>
|
| -#include <unistd.h>
|
| -
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/command_line.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/files/scoped_temp_dir.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| -#include "base/test/test_timeouts.h"
|
| -#include "base/test/thread_test_helper.h"
|
| -#include "base/threading/thread.h"
|
| -#include "chrome/common/chrome_constants.h"
|
| -#include "content/public/test/test_browser_thread.h"
|
| -#include "net/base/net_util.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -using content::BrowserThread;
|
| -
|
| -namespace {
|
| -
|
| -class ProcessSingletonLinuxTest : public testing::Test {
|
| - public:
|
| - // A ProcessSingleton exposing some protected methods for testing.
|
| - class TestableProcessSingleton : public ProcessSingleton {
|
| - public:
|
| - explicit TestableProcessSingleton(const base::FilePath& user_data_dir)
|
| - : ProcessSingleton(
|
| - user_data_dir,
|
| - base::Bind(&TestableProcessSingleton::NotificationCallback,
|
| - base::Unretained(this))) {}
|
| -
|
| -
|
| - std::vector<CommandLine::StringVector> callback_command_lines_;
|
| -
|
| - using ProcessSingleton::NotifyOtherProcessWithTimeout;
|
| - using ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate;
|
| - using ProcessSingleton::OverrideCurrentPidForTesting;
|
| - using ProcessSingleton::OverrideKillCallbackForTesting;
|
| -
|
| - private:
|
| - bool NotificationCallback(const CommandLine& command_line,
|
| - const base::FilePath& current_directory) {
|
| - callback_command_lines_.push_back(command_line.argv());
|
| - return true;
|
| - }
|
| - };
|
| -
|
| - ProcessSingletonLinuxTest()
|
| - : kill_callbacks_(0),
|
| - io_thread_(BrowserThread::IO),
|
| - wait_event_(true, false),
|
| - signal_event_(true, false),
|
| - process_singleton_on_thread_(NULL) {
|
| - io_thread_.StartIOThread();
|
| - }
|
| -
|
| - virtual void SetUp() {
|
| - testing::Test::SetUp();
|
| -
|
| - ProcessSingleton::DisablePromptForTesting();
|
| - // Put the lock in a temporary directory. Doesn't need to be a
|
| - // full profile to test this code.
|
| - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| - lock_path_ = temp_dir_.path().Append(chrome::kSingletonLockFilename);
|
| - socket_path_ = temp_dir_.path().Append(chrome::kSingletonSocketFilename);
|
| - cookie_path_ = temp_dir_.path().Append(chrome::kSingletonCookieFilename);
|
| - }
|
| -
|
| - virtual void TearDown() {
|
| - scoped_refptr<base::ThreadTestHelper> io_helper(new base::ThreadTestHelper(
|
| - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
|
| - ASSERT_TRUE(io_helper->Run());
|
| -
|
| - // Destruct the ProcessSingleton object before the IO thread so that its
|
| - // internals are destructed properly.
|
| - if (process_singleton_on_thread_) {
|
| - worker_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ProcessSingletonLinuxTest::DestructProcessSingleton,
|
| - base::Unretained(this)));
|
| -
|
| - scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
|
| - worker_thread_->message_loop_proxy().get()));
|
| - ASSERT_TRUE(helper->Run());
|
| - }
|
| -
|
| - io_thread_.Stop();
|
| - testing::Test::TearDown();
|
| - }
|
| -
|
| - void CreateProcessSingletonOnThread() {
|
| - ASSERT_EQ(NULL, worker_thread_.get());
|
| - worker_thread_.reset(new base::Thread("BlockingThread"));
|
| - worker_thread_->Start();
|
| -
|
| - worker_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ProcessSingletonLinuxTest::
|
| - CreateProcessSingletonInternal,
|
| - base::Unretained(this)));
|
| -
|
| - scoped_refptr<base::ThreadTestHelper> helper(
|
| - new base::ThreadTestHelper(worker_thread_->message_loop_proxy().get()));
|
| - ASSERT_TRUE(helper->Run());
|
| - }
|
| -
|
| - TestableProcessSingleton* CreateProcessSingleton() {
|
| - return new TestableProcessSingleton(temp_dir_.path());
|
| - }
|
| -
|
| - ProcessSingleton::NotifyResult NotifyOtherProcess(
|
| - bool override_kill,
|
| - base::TimeDelta timeout) {
|
| - scoped_ptr<TestableProcessSingleton> process_singleton(
|
| - CreateProcessSingleton());
|
| - CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram());
|
| - command_line.AppendArg("about:blank");
|
| - if (override_kill) {
|
| - process_singleton->OverrideCurrentPidForTesting(
|
| - base::GetCurrentProcId() + 1);
|
| - process_singleton->OverrideKillCallbackForTesting(
|
| - base::Bind(&ProcessSingletonLinuxTest::KillCallback,
|
| - base::Unretained(this)));
|
| - }
|
| -
|
| - return process_singleton->NotifyOtherProcessWithTimeout(
|
| - command_line, timeout.InSeconds(), true);
|
| - }
|
| -
|
| - // A helper method to call ProcessSingleton::NotifyOtherProcessOrCreate().
|
| - ProcessSingleton::NotifyResult NotifyOtherProcessOrCreate(
|
| - const std::string& url,
|
| - base::TimeDelta timeout) {
|
| - scoped_ptr<TestableProcessSingleton> process_singleton(
|
| - CreateProcessSingleton());
|
| - CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram());
|
| - command_line.AppendArg(url);
|
| - return process_singleton->NotifyOtherProcessWithTimeoutOrCreate(
|
| - command_line, timeout.InSeconds());
|
| - }
|
| -
|
| - void CheckNotified() {
|
| - ASSERT_TRUE(process_singleton_on_thread_ != NULL);
|
| - ASSERT_EQ(1u, process_singleton_on_thread_->callback_command_lines_.size());
|
| - bool found = false;
|
| - for (size_t i = 0;
|
| - i < process_singleton_on_thread_->callback_command_lines_[0].size();
|
| - ++i) {
|
| - if (process_singleton_on_thread_->callback_command_lines_[0][i] ==
|
| - "about:blank") {
|
| - found = true;
|
| - break;
|
| - }
|
| - }
|
| - ASSERT_TRUE(found);
|
| - ASSERT_EQ(0, kill_callbacks_);
|
| - }
|
| -
|
| - void BlockWorkerThread() {
|
| - worker_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ProcessSingletonLinuxTest::BlockThread,
|
| - base::Unretained(this)));
|
| - }
|
| -
|
| - void UnblockWorkerThread() {
|
| - wait_event_.Signal(); // Unblock the worker thread for shutdown.
|
| - signal_event_.Wait(); // Ensure thread unblocks before continuing.
|
| - }
|
| -
|
| - void BlockThread() {
|
| - wait_event_.Wait();
|
| - signal_event_.Signal();
|
| - }
|
| -
|
| - base::FilePath lock_path_;
|
| - base::FilePath socket_path_;
|
| - base::FilePath cookie_path_;
|
| - int kill_callbacks_;
|
| -
|
| - private:
|
| - void CreateProcessSingletonInternal() {
|
| - ASSERT_TRUE(!process_singleton_on_thread_);
|
| - process_singleton_on_thread_ = CreateProcessSingleton();
|
| - ASSERT_EQ(ProcessSingleton::PROCESS_NONE,
|
| - process_singleton_on_thread_->NotifyOtherProcessOrCreate());
|
| - }
|
| -
|
| - void DestructProcessSingleton() {
|
| - ASSERT_TRUE(process_singleton_on_thread_);
|
| - delete process_singleton_on_thread_;
|
| - }
|
| -
|
| - void KillCallback(int pid) {
|
| - kill_callbacks_++;
|
| - }
|
| -
|
| - content::TestBrowserThread io_thread_;
|
| - base::ScopedTempDir temp_dir_;
|
| - base::WaitableEvent wait_event_;
|
| - base::WaitableEvent signal_event_;
|
| -
|
| - scoped_ptr<base::Thread> worker_thread_;
|
| - TestableProcessSingleton* process_singleton_on_thread_;
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -// Test if the socket file and symbol link created by ProcessSingletonLinux
|
| -// are valid.
|
| -// If this test flakes, use http://crbug.com/74554.
|
| -TEST_F(ProcessSingletonLinuxTest, CheckSocketFile) {
|
| - CreateProcessSingletonOnThread();
|
| - struct stat statbuf;
|
| - ASSERT_EQ(0, lstat(lock_path_.value().c_str(), &statbuf));
|
| - ASSERT_TRUE(S_ISLNK(statbuf.st_mode));
|
| - char buf[PATH_MAX];
|
| - ssize_t len = readlink(lock_path_.value().c_str(), buf, PATH_MAX);
|
| - ASSERT_GT(len, 0);
|
| -
|
| - ASSERT_EQ(0, lstat(socket_path_.value().c_str(), &statbuf));
|
| - ASSERT_TRUE(S_ISLNK(statbuf.st_mode));
|
| -
|
| - len = readlink(socket_path_.value().c_str(), buf, PATH_MAX);
|
| - ASSERT_GT(len, 0);
|
| - base::FilePath socket_target_path = base::FilePath(std::string(buf, len));
|
| -
|
| - ASSERT_EQ(0, lstat(socket_target_path.value().c_str(), &statbuf));
|
| - ASSERT_TRUE(S_ISSOCK(statbuf.st_mode));
|
| -
|
| - len = readlink(cookie_path_.value().c_str(), buf, PATH_MAX);
|
| - ASSERT_GT(len, 0);
|
| - std::string cookie(buf, len);
|
| -
|
| - base::FilePath remote_cookie_path = socket_target_path.DirName().
|
| - Append(chrome::kSingletonCookieFilename);
|
| - len = readlink(remote_cookie_path.value().c_str(), buf, PATH_MAX);
|
| - ASSERT_GT(len, 0);
|
| - EXPECT_EQ(cookie, std::string(buf, len));
|
| -}
|
| -
|
| -// TODO(james.su@gmail.com): port following tests to Windows.
|
| -// Test success case of NotifyOtherProcess().
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessSuccess) {
|
| - CreateProcessSingletonOnThread();
|
| - EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED,
|
| - NotifyOtherProcess(true, TestTimeouts::action_timeout()));
|
| - CheckNotified();
|
| -}
|
| -
|
| -// Test failure case of NotifyOtherProcess().
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessFailure) {
|
| - CreateProcessSingletonOnThread();
|
| -
|
| - BlockWorkerThread();
|
| - EXPECT_EQ(ProcessSingleton::PROCESS_NONE,
|
| - NotifyOtherProcess(true, TestTimeouts::action_timeout()));
|
| -
|
| - ASSERT_EQ(1, kill_callbacks_);
|
| - UnblockWorkerThread();
|
| -}
|
| -
|
| -// Test that we don't kill ourselves by accident if a lockfile with the same pid
|
| -// happens to exist.
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessNoSuicide) {
|
| - CreateProcessSingletonOnThread();
|
| - // Replace lockfile with one containing our own pid.
|
| - EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
|
| - std::string symlink_content = base::StringPrintf(
|
| - "%s%c%u",
|
| - net::GetHostName().c_str(),
|
| - '-',
|
| - base::GetCurrentProcId());
|
| - EXPECT_EQ(0, symlink(symlink_content.c_str(), lock_path_.value().c_str()));
|
| -
|
| - // Remove socket so that we will not be able to notify the existing browser.
|
| - EXPECT_EQ(0, unlink(socket_path_.value().c_str()));
|
| -
|
| - EXPECT_EQ(ProcessSingleton::PROCESS_NONE,
|
| - NotifyOtherProcess(false, TestTimeouts::action_timeout()));
|
| - // If we've gotten to this point without killing ourself, the test succeeded.
|
| -}
|
| -
|
| -// Test that we can still notify a process on the same host even after the
|
| -// hostname changed.
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessHostChanged) {
|
| - CreateProcessSingletonOnThread();
|
| - EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
|
| - EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
|
| -
|
| - EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED,
|
| - NotifyOtherProcess(false, TestTimeouts::action_timeout()));
|
| - CheckNotified();
|
| -}
|
| -
|
| -// Test that we fail when lock says process is on another host and we can't
|
| -// notify it over the socket.
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessDifferingHost) {
|
| - CreateProcessSingletonOnThread();
|
| -
|
| - BlockWorkerThread();
|
| -
|
| - EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
|
| - EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
|
| -
|
| - EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
|
| - NotifyOtherProcess(false, TestTimeouts::action_timeout()));
|
| -
|
| - ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
|
| -
|
| - UnblockWorkerThread();
|
| -}
|
| -
|
| -// Test that we fail when lock says process is on another host and we can't
|
| -// notify it over the socket.
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessOrCreate_DifferingHost) {
|
| - CreateProcessSingletonOnThread();
|
| -
|
| - BlockWorkerThread();
|
| -
|
| - EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
|
| - EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
|
| -
|
| - std::string url("about:blank");
|
| - EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
|
| - NotifyOtherProcessOrCreate(url, TestTimeouts::action_timeout()));
|
| -
|
| - ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
|
| -
|
| - UnblockWorkerThread();
|
| -}
|
| -
|
| -// Test that Create fails when another browser is using the profile directory.
|
| -TEST_F(ProcessSingletonLinuxTest, CreateFailsWithExistingBrowser) {
|
| - CreateProcessSingletonOnThread();
|
| -
|
| - scoped_ptr<TestableProcessSingleton> process_singleton(
|
| - CreateProcessSingleton());
|
| - process_singleton->OverrideCurrentPidForTesting(base::GetCurrentProcId() + 1);
|
| - EXPECT_FALSE(process_singleton->Create());
|
| -}
|
| -
|
| -// Test that Create fails when another browser is using the profile directory
|
| -// but with the old socket location.
|
| -TEST_F(ProcessSingletonLinuxTest, CreateChecksCompatibilitySocket) {
|
| - CreateProcessSingletonOnThread();
|
| - scoped_ptr<TestableProcessSingleton> process_singleton(
|
| - CreateProcessSingleton());
|
| - process_singleton->OverrideCurrentPidForTesting(base::GetCurrentProcId() + 1);
|
| -
|
| - // Do some surgery so as to look like the old configuration.
|
| - char buf[PATH_MAX];
|
| - ssize_t len = readlink(socket_path_.value().c_str(), buf, sizeof(buf));
|
| - ASSERT_GT(len, 0);
|
| - base::FilePath socket_target_path = base::FilePath(std::string(buf, len));
|
| - ASSERT_EQ(0, unlink(socket_path_.value().c_str()));
|
| - ASSERT_EQ(0, rename(socket_target_path.value().c_str(),
|
| - socket_path_.value().c_str()));
|
| - ASSERT_EQ(0, unlink(cookie_path_.value().c_str()));
|
| -
|
| - EXPECT_FALSE(process_singleton->Create());
|
| -}
|
| -
|
| -// Test that we fail when lock says process is on another host and we can't
|
| -// notify it over the socket before of a bad cookie.
|
| -TEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessOrCreate_BadCookie) {
|
| - CreateProcessSingletonOnThread();
|
| - // Change the cookie.
|
| - EXPECT_EQ(0, unlink(cookie_path_.value().c_str()));
|
| - EXPECT_EQ(0, symlink("INCORRECTCOOKIE", cookie_path_.value().c_str()));
|
| -
|
| - // Also change the hostname, so the remote does not retry.
|
| - EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
|
| - EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
|
| -
|
| - std::string url("about:blank");
|
| - EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
|
| - NotifyOtherProcessOrCreate(url, TestTimeouts::action_timeout()));
|
| -}
|
| -
|
|
|