Chromium Code Reviews| Index: base/process/process_unittest.cc |
| diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1f0f51be8120dcff4045c07ba2bee91aae278838 |
| --- /dev/null |
| +++ b/base/process/process_unittest.cc |
| @@ -0,0 +1,158 @@ |
| +// Copyright 2014 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 "base/process/process.h" |
| + |
| +#include "base/process/kill.h" |
| +#include "base/test/multiprocess_test.h" |
| +#include "base/test/test_timeouts.h" |
| +#include "base/threading/platform_thread.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "testing/multiprocess_func_list.h" |
| + |
| + |
| +namespace { |
| + |
| +#if defined(OS_WIN) |
| +const int kExpectedStillRunningExitCode = 0x102; |
| +#else |
| +const int kExpectedStillRunningExitCode = 0; |
| +#endif |
| + |
| +} // namespace |
| + |
| +class ProcessTest : public base::MultiProcessTest { |
| +}; |
| + |
| +TEST_F(ProcessTest, Create) { |
| + base::Process process(SpawnChild("SimpleChildProcess")); |
|
Lei Zhang
2014/10/16 02:50:08
nit: put the entire test in namespace base.
rvargas (doing something else)
2014/10/16 19:06:10
:( I like to treat tests as consumers of the code
|
| + ASSERT_TRUE(process.IsValid()); |
| + ASSERT_FALSE(process.is_current()); |
| + process.Close(); |
| + ASSERT_FALSE(process.IsValid()); |
| +} |
| + |
| +TEST_F(ProcessTest, CreateCurrent) { |
| + base::Process process = base::Process::Current(); |
| + ASSERT_TRUE(process.IsValid()); |
| + ASSERT_TRUE(process.is_current()); |
| + process.Close(); |
| + ASSERT_FALSE(process.IsValid()); |
| +} |
| + |
| +TEST_F(ProcessTest, Move) { |
| + base::Process process1(SpawnChild("SimpleChildProcess")); |
| + EXPECT_TRUE(process1.IsValid()); |
| + |
| + base::Process process2; |
| + EXPECT_FALSE(process2.IsValid()); |
| + |
| + process2 = process1.Pass(); |
| + EXPECT_TRUE(process2.IsValid()); |
| + EXPECT_FALSE(process1.IsValid()); |
| + EXPECT_FALSE(process2.is_current()); |
| + |
| + base::Process process3 = base::Process::Current(); |
| + process2 = process3.Pass(); |
| + EXPECT_TRUE(process2.is_current()); |
| + EXPECT_TRUE(process2.IsValid()); |
| + EXPECT_FALSE(process3.IsValid()); |
| +} |
| + |
| +TEST_F(ProcessTest, Duplicate) { |
| + base::Process process1(SpawnChild("SimpleChildProcess")); |
| + ASSERT_TRUE(process1.IsValid()); |
| + |
| + base::Process process2 = process1.Duplicate(); |
| + ASSERT_TRUE(process1.IsValid()); |
| + ASSERT_TRUE(process2.IsValid()); |
| + EXPECT_EQ(process1.pid(), process2.pid()); |
| + EXPECT_FALSE(process1.is_current()); |
| + EXPECT_FALSE(process2.is_current()); |
| + |
| + process1.Close(); |
| + ASSERT_TRUE(process2.IsValid()); |
| +} |
| + |
| +TEST_F(ProcessTest, DuplicateCurrent) { |
| + base::Process process1 = base::Process::Current(); |
| + ASSERT_TRUE(process1.IsValid()); |
| + |
| + base::Process process2 = process1.Duplicate(); |
| + ASSERT_TRUE(process1.IsValid()); |
| + ASSERT_TRUE(process2.IsValid()); |
| + EXPECT_EQ(process1.pid(), process2.pid()); |
| + EXPECT_TRUE(process1.is_current()); |
| + EXPECT_TRUE(process2.is_current()); |
| + |
| + process1.Close(); |
| + ASSERT_TRUE(process2.IsValid()); |
| +} |
| + |
| +MULTIPROCESS_TEST_MAIN(SleepyChildProcess) { |
| + base::PlatformThread::Sleep(TestTimeouts::action_max_timeout()); |
| + return 0; |
| +} |
| + |
| +TEST_F(ProcessTest, Terminate) { |
| + base::Process process(SpawnChild("SleepyChildProcess")); |
| + ASSERT_TRUE(process.IsValid()); |
| + |
| + const int kDummyExitCode = 42; |
| + int exit_code = kDummyExitCode; |
| + EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, |
| + base::GetTerminationStatus(process.Handle(), &exit_code)); |
| + EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); |
| + |
| + exit_code = kDummyExitCode; |
| + int kExpectedExitCode = 250; |
| + process.Terminate(kExpectedExitCode); |
| + base::WaitForSingleProcess(process.Handle(), |
| + TestTimeouts::action_max_timeout()); |
| + |
| + EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, |
| + base::GetTerminationStatus(process.Handle(), &exit_code)); |
| +#if !defined(OS_POSIX) |
| + // The POSIX implementation actually ignores the exit_code. |
| + EXPECT_EQ(kExpectedExitCode, exit_code); |
| +#endif |
| +} |
| + |
| +// Ensure that the priority of a process is restored correctly after |
| +// backgrounding and restoring. |
| +// Note: a platform may not be willing or able to lower the priority of |
| +// a process. The calls to SetProcessBackground should be noops then. |
| +TEST_F(ProcessTest, SetProcessBackgrounded) { |
| + base::Process process(SpawnChild("SimpleChildProcess")); |
| + int old_priority = process.GetPriority(); |
| +#if defined(OS_WIN) |
| + EXPECT_TRUE(process.SetProcessBackgrounded(true)); |
| + EXPECT_TRUE(process.IsProcessBackgrounded()); |
| + EXPECT_TRUE(process.SetProcessBackgrounded(false)); |
| + EXPECT_FALSE(process.IsProcessBackgrounded()); |
| +#else |
| + process.SetProcessBackgrounded(true); |
| + process.SetProcessBackgrounded(false); |
| +#endif |
| + int new_priority = process.GetPriority(); |
| + EXPECT_EQ(old_priority, new_priority); |
| +} |
| + |
| +// Same as SetProcessBackgrounded but to this very process. It uses |
| +// a different code path at least for Windows. |
| +TEST_F(ProcessTest, SetProcessBackgroundedSelf) { |
| + base::Process process = base::Process::Current(); |
| + int old_priority = process.GetPriority(); |
| +#if defined(OS_WIN) |
| + EXPECT_TRUE(process.SetProcessBackgrounded(true)); |
| + EXPECT_TRUE(process.IsProcessBackgrounded()); |
| + EXPECT_TRUE(process.SetProcessBackgrounded(false)); |
| + EXPECT_FALSE(process.IsProcessBackgrounded()); |
| +#else |
| + process.SetProcessBackgrounded(true); |
| + process.SetProcessBackgrounded(false); |
| +#endif |
| + int new_priority = process.GetPriority(); |
| + EXPECT_EQ(old_priority, new_priority); |
| +} |