Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "base/process/process.h" | 5 #include "base/process/process.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
| 10 #include "base/process/kill.h" | 10 #include "base/process/kill.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 #endif | 35 #endif |
| 36 | 36 |
| 37 } // namespace | 37 } // namespace |
| 38 | 38 |
| 39 namespace base { | 39 namespace base { |
| 40 | 40 |
| 41 class ProcessTest : public MultiProcessTest { | 41 class ProcessTest : public MultiProcessTest { |
| 42 }; | 42 }; |
| 43 | 43 |
| 44 TEST_F(ProcessTest, Create) { | 44 TEST_F(ProcessTest, Create) { |
| 45 Process process(SpawnChild("SimpleChildProcess")); | 45 SpawnChildResult spawn_child = SpawnChild("SimpleChildProcess"); |
| 46 ASSERT_TRUE(process.IsValid()); | 46 ASSERT_TRUE(spawn_child.process.IsValid()); |
| 47 ASSERT_FALSE(process.is_current()); | 47 ASSERT_FALSE(spawn_child.process.is_current()); |
| 48 process.Close(); | 48 spawn_child.process.Close(); |
| 49 ASSERT_FALSE(process.IsValid()); | 49 ASSERT_FALSE(spawn_child.process.IsValid()); |
| 50 } | 50 } |
| 51 | 51 |
| 52 TEST_F(ProcessTest, CreateCurrent) { | 52 TEST_F(ProcessTest, CreateCurrent) { |
| 53 Process process = Process::Current(); | 53 Process process = Process::Current(); |
| 54 ASSERT_TRUE(process.IsValid()); | 54 ASSERT_TRUE(process.IsValid()); |
| 55 ASSERT_TRUE(process.is_current()); | 55 ASSERT_TRUE(process.is_current()); |
| 56 process.Close(); | 56 process.Close(); |
| 57 ASSERT_FALSE(process.IsValid()); | 57 ASSERT_FALSE(process.IsValid()); |
| 58 } | 58 } |
| 59 | 59 |
| 60 TEST_F(ProcessTest, Move) { | 60 TEST_F(ProcessTest, Move) { |
| 61 Process process1(SpawnChild("SimpleChildProcess")); | 61 SpawnChildResult spawn_result = SpawnChild("SimpleChildProcess"); |
| 62 Process process1(std::move(spawn_result.process)); | |
|
dcheng
2017/03/14 05:28:51
Ditto
Jay Civelli
2017/03/14 16:29:12
Aliasing here, since it makes the test clearer.
| |
| 62 EXPECT_TRUE(process1.IsValid()); | 63 EXPECT_TRUE(process1.IsValid()); |
| 63 | 64 |
| 64 Process process2; | 65 Process process2; |
| 65 EXPECT_FALSE(process2.IsValid()); | 66 EXPECT_FALSE(process2.IsValid()); |
| 66 | 67 |
| 67 process2 = std::move(process1); | 68 process2 = std::move(process1); |
| 68 EXPECT_TRUE(process2.IsValid()); | 69 EXPECT_TRUE(process2.IsValid()); |
| 69 EXPECT_FALSE(process1.IsValid()); | 70 EXPECT_FALSE(process1.IsValid()); |
| 70 EXPECT_FALSE(process2.is_current()); | 71 EXPECT_FALSE(process2.is_current()); |
| 71 | 72 |
| 72 Process process3 = Process::Current(); | 73 Process process3 = Process::Current(); |
| 73 process2 = std::move(process3); | 74 process2 = std::move(process3); |
| 74 EXPECT_TRUE(process2.is_current()); | 75 EXPECT_TRUE(process2.is_current()); |
| 75 EXPECT_TRUE(process2.IsValid()); | 76 EXPECT_TRUE(process2.IsValid()); |
| 76 EXPECT_FALSE(process3.IsValid()); | 77 EXPECT_FALSE(process3.IsValid()); |
| 77 } | 78 } |
| 78 | 79 |
| 79 TEST_F(ProcessTest, Duplicate) { | 80 TEST_F(ProcessTest, Duplicate) { |
| 80 Process process1(SpawnChild("SimpleChildProcess")); | 81 SpawnChildResult spawn_result = SpawnChild("SimpleChildProcess"); |
| 82 Process process1(std::move(spawn_result.process)); | |
| 81 ASSERT_TRUE(process1.IsValid()); | 83 ASSERT_TRUE(process1.IsValid()); |
| 82 | 84 |
| 83 Process process2 = process1.Duplicate(); | 85 Process process2 = process1.Duplicate(); |
| 84 ASSERT_TRUE(process1.IsValid()); | 86 ASSERT_TRUE(process1.IsValid()); |
| 85 ASSERT_TRUE(process2.IsValid()); | 87 ASSERT_TRUE(process2.IsValid()); |
| 86 EXPECT_EQ(process1.Pid(), process2.Pid()); | 88 EXPECT_EQ(process1.Pid(), process2.Pid()); |
| 87 EXPECT_FALSE(process1.is_current()); | 89 EXPECT_FALSE(process1.is_current()); |
| 88 EXPECT_FALSE(process2.is_current()); | 90 EXPECT_FALSE(process2.is_current()); |
| 89 | 91 |
| 90 process1.Close(); | 92 process1.Close(); |
| 91 ASSERT_TRUE(process2.IsValid()); | 93 ASSERT_TRUE(process2.IsValid()); |
| 92 } | 94 } |
| 93 | 95 |
| 94 TEST_F(ProcessTest, DuplicateCurrent) { | 96 TEST_F(ProcessTest, DuplicateCurrent) { |
| 95 Process process1 = Process::Current(); | 97 Process process1 = Process::Current(); |
| 96 ASSERT_TRUE(process1.IsValid()); | 98 ASSERT_TRUE(process1.IsValid()); |
| 97 | 99 |
| 98 Process process2 = process1.Duplicate(); | 100 Process process2 = process1.Duplicate(); |
| 99 ASSERT_TRUE(process1.IsValid()); | 101 ASSERT_TRUE(process1.IsValid()); |
| 100 ASSERT_TRUE(process2.IsValid()); | 102 ASSERT_TRUE(process2.IsValid()); |
| 101 EXPECT_EQ(process1.Pid(), process2.Pid()); | 103 EXPECT_EQ(process1.Pid(), process2.Pid()); |
| 102 EXPECT_TRUE(process1.is_current()); | 104 EXPECT_TRUE(process1.is_current()); |
| 103 EXPECT_TRUE(process2.is_current()); | 105 EXPECT_TRUE(process2.is_current()); |
| 104 | 106 |
| 105 process1.Close(); | 107 process1.Close(); |
| 106 ASSERT_TRUE(process2.IsValid()); | 108 ASSERT_TRUE(process2.IsValid()); |
| 107 } | 109 } |
| 108 | 110 |
| 109 TEST_F(ProcessTest, DeprecatedGetProcessFromHandle) { | 111 TEST_F(ProcessTest, DeprecatedGetProcessFromHandle) { |
| 110 Process process1(SpawnChild("SimpleChildProcess")); | 112 SpawnChildResult spawn_result = SpawnChild("SimpleChildProcess"); |
| 113 Process process1(std::move(spawn_result.process)); | |
| 111 ASSERT_TRUE(process1.IsValid()); | 114 ASSERT_TRUE(process1.IsValid()); |
| 112 | 115 |
| 113 Process process2 = Process::DeprecatedGetProcessFromHandle(process1.Handle()); | 116 Process process2 = Process::DeprecatedGetProcessFromHandle(process1.Handle()); |
| 114 ASSERT_TRUE(process1.IsValid()); | 117 ASSERT_TRUE(process1.IsValid()); |
| 115 ASSERT_TRUE(process2.IsValid()); | 118 ASSERT_TRUE(process2.IsValid()); |
| 116 EXPECT_EQ(process1.Pid(), process2.Pid()); | 119 EXPECT_EQ(process1.Pid(), process2.Pid()); |
| 117 EXPECT_FALSE(process1.is_current()); | 120 EXPECT_FALSE(process1.is_current()); |
| 118 EXPECT_FALSE(process2.is_current()); | 121 EXPECT_FALSE(process2.is_current()); |
| 119 | 122 |
| 120 process1.Close(); | 123 process1.Close(); |
| 121 ASSERT_TRUE(process2.IsValid()); | 124 ASSERT_TRUE(process2.IsValid()); |
| 122 } | 125 } |
| 123 | 126 |
| 124 MULTIPROCESS_TEST_MAIN(SleepyChildProcess) { | 127 MULTIPROCESS_TEST_MAIN(SleepyChildProcess) { |
| 125 PlatformThread::Sleep(TestTimeouts::action_max_timeout()); | 128 PlatformThread::Sleep(TestTimeouts::action_max_timeout()); |
| 126 return 0; | 129 return 0; |
| 127 } | 130 } |
| 128 | 131 |
| 129 TEST_F(ProcessTest, Terminate) { | 132 TEST_F(ProcessTest, Terminate) { |
| 130 Process process(SpawnChild("SleepyChildProcess")); | 133 SpawnChildResult spawn_result = SpawnChild("SleepyChildProcess"); |
| 134 Process process(std::move(spawn_result.process)); | |
| 131 ASSERT_TRUE(process.IsValid()); | 135 ASSERT_TRUE(process.IsValid()); |
| 132 | 136 |
| 133 const int kDummyExitCode = 42; | 137 const int kDummyExitCode = 42; |
| 134 int exit_code = kDummyExitCode; | 138 int exit_code = kDummyExitCode; |
| 135 EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING, | 139 EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING, |
| 136 GetTerminationStatus(process.Handle(), &exit_code)); | 140 GetTerminationStatus(process.Handle(), &exit_code)); |
| 137 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); | 141 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); |
| 138 | 142 |
| 139 exit_code = kDummyExitCode; | 143 exit_code = kDummyExitCode; |
| 140 int kExpectedExitCode = 250; | 144 int kExpectedExitCode = 250; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 166 | 170 |
| 167 MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0) { | 171 MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0) { |
| 168 base::ThreadLocalPointer<ThreadLocalObject> object; | 172 base::ThreadLocalPointer<ThreadLocalObject> object; |
| 169 base::AtExitManager::RegisterCallback(&AtExitHandler, NULL); | 173 base::AtExitManager::RegisterCallback(&AtExitHandler, NULL); |
| 170 Process::TerminateCurrentProcessImmediately(0); | 174 Process::TerminateCurrentProcessImmediately(0); |
| 171 NOTREACHED(); | 175 NOTREACHED(); |
| 172 return 42; | 176 return 42; |
| 173 } | 177 } |
| 174 | 178 |
| 175 TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithZeroExitCode) { | 179 TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithZeroExitCode) { |
| 176 Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode0")); | 180 SpawnChildResult spawn_child = |
| 177 ASSERT_TRUE(process.IsValid()); | 181 SpawnChild("TerminateCurrentProcessImmediatelyWithCode0"); |
| 182 ASSERT_TRUE(spawn_child.process.IsValid()); | |
| 178 int exit_code = 42; | 183 int exit_code = 42; |
| 179 ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), | 184 ASSERT_TRUE(spawn_child.process.WaitForExitWithTimeout( |
| 180 &exit_code)); | 185 TestTimeouts::action_max_timeout(), &exit_code)); |
| 181 EXPECT_EQ(0, exit_code); | 186 EXPECT_EQ(0, exit_code); |
| 182 } | 187 } |
| 183 | 188 |
| 184 MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250) { | 189 MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250) { |
| 185 Process::TerminateCurrentProcessImmediately(250); | 190 Process::TerminateCurrentProcessImmediately(250); |
| 186 NOTREACHED(); | 191 NOTREACHED(); |
| 187 return 42; | 192 return 42; |
| 188 } | 193 } |
| 189 | 194 |
| 190 TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithNonZeroExitCode) { | 195 TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithNonZeroExitCode) { |
| 191 Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode250")); | 196 SpawnChildResult spawn_child = |
| 192 ASSERT_TRUE(process.IsValid()); | 197 SpawnChild("TerminateCurrentProcessImmediatelyWithCode250"); |
| 198 ASSERT_TRUE(spawn_child.process.IsValid()); | |
| 193 int exit_code = 42; | 199 int exit_code = 42; |
| 194 ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), | 200 ASSERT_TRUE(spawn_child.process.WaitForExitWithTimeout( |
| 195 &exit_code)); | 201 TestTimeouts::action_max_timeout(), &exit_code)); |
| 196 EXPECT_EQ(250, exit_code); | 202 EXPECT_EQ(250, exit_code); |
| 197 } | 203 } |
| 198 | 204 |
| 199 MULTIPROCESS_TEST_MAIN(FastSleepyChildProcess) { | 205 MULTIPROCESS_TEST_MAIN(FastSleepyChildProcess) { |
| 200 PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 10); | 206 PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 10); |
| 201 return 0; | 207 return 0; |
| 202 } | 208 } |
| 203 | 209 |
| 204 TEST_F(ProcessTest, WaitForExit) { | 210 TEST_F(ProcessTest, WaitForExit) { |
| 205 Process process(SpawnChild("FastSleepyChildProcess")); | 211 SpawnChildResult spawn_child = SpawnChild("FastSleepyChildProcess"); |
| 206 ASSERT_TRUE(process.IsValid()); | 212 ASSERT_TRUE(spawn_child.process.IsValid()); |
| 207 | 213 |
| 208 const int kDummyExitCode = 42; | 214 const int kDummyExitCode = 42; |
| 209 int exit_code = kDummyExitCode; | 215 int exit_code = kDummyExitCode; |
| 210 EXPECT_TRUE(process.WaitForExit(&exit_code)); | 216 EXPECT_TRUE(spawn_child.process.WaitForExit(&exit_code)); |
| 211 EXPECT_EQ(0, exit_code); | 217 EXPECT_EQ(0, exit_code); |
| 212 } | 218 } |
| 213 | 219 |
| 214 TEST_F(ProcessTest, WaitForExitWithTimeout) { | 220 TEST_F(ProcessTest, WaitForExitWithTimeout) { |
| 215 Process process(SpawnChild("SleepyChildProcess")); | 221 SpawnChildResult spawn_child = SpawnChild("SleepyChildProcess"); |
| 216 ASSERT_TRUE(process.IsValid()); | 222 ASSERT_TRUE(spawn_child.process.IsValid()); |
| 217 | 223 |
| 218 const int kDummyExitCode = 42; | 224 const int kDummyExitCode = 42; |
| 219 int exit_code = kDummyExitCode; | 225 int exit_code = kDummyExitCode; |
| 220 TimeDelta timeout = TestTimeouts::tiny_timeout(); | 226 TimeDelta timeout = TestTimeouts::tiny_timeout(); |
| 221 EXPECT_FALSE(process.WaitForExitWithTimeout(timeout, &exit_code)); | 227 EXPECT_FALSE(spawn_child.process.WaitForExitWithTimeout(timeout, &exit_code)); |
| 222 EXPECT_EQ(kDummyExitCode, exit_code); | 228 EXPECT_EQ(kDummyExitCode, exit_code); |
| 223 | 229 |
| 224 process.Terminate(kDummyExitCode, false); | 230 spawn_child.process.Terminate(kDummyExitCode, false); |
| 225 } | 231 } |
| 226 | 232 |
| 227 // Ensure that the priority of a process is restored correctly after | 233 // Ensure that the priority of a process is restored correctly after |
| 228 // backgrounding and restoring. | 234 // backgrounding and restoring. |
| 229 // Note: a platform may not be willing or able to lower the priority of | 235 // Note: a platform may not be willing or able to lower the priority of |
| 230 // a process. The calls to SetProcessBackground should be noops then. | 236 // a process. The calls to SetProcessBackground should be noops then. |
| 231 TEST_F(ProcessTest, SetProcessBackgrounded) { | 237 TEST_F(ProcessTest, SetProcessBackgrounded) { |
| 232 if (!Process::CanBackgroundProcesses()) | 238 if (!Process::CanBackgroundProcesses()) |
| 233 return; | 239 return; |
| 234 Process process(SpawnChild("SimpleChildProcess")); | 240 SpawnChildResult spawn_child = SpawnChild("SimpleChildProcess"); |
| 235 int old_priority = process.GetPriority(); | 241 int old_priority = spawn_child.process.GetPriority(); |
| 236 #if defined(OS_WIN) | 242 #if defined(OS_WIN) |
| 237 EXPECT_TRUE(process.SetProcessBackgrounded(true)); | 243 EXPECT_TRUE(spawn_child.process.SetProcessBackgrounded(true)); |
| 238 EXPECT_TRUE(process.IsProcessBackgrounded()); | 244 EXPECT_TRUE(spawn_child.process.IsProcessBackgrounded()); |
| 239 EXPECT_TRUE(process.SetProcessBackgrounded(false)); | 245 EXPECT_TRUE(spawn_child.process.SetProcessBackgrounded(false)); |
| 240 EXPECT_FALSE(process.IsProcessBackgrounded()); | 246 EXPECT_FALSE(spawn_child.process.IsProcessBackgrounded()); |
| 241 #elif defined(OS_MACOSX) | 247 #elif defined(OS_MACOSX) |
| 242 // On the Mac, backgrounding a process requires a port to that process. | 248 // On the Mac, backgrounding a process requires a port to that process. |
| 243 // In the browser it's available through the MachBroker class, which is not | 249 // In the browser it's available through the MachBroker class, which is not |
| 244 // part of base. Additionally, there is an indefinite amount of time between | 250 // part of base. Additionally, there is an indefinite amount of time between |
| 245 // spawning a process and receiving its port. Because this test just checks | 251 // spawning a process and receiving its port. Because this test just checks |
| 246 // the ability to background/foreground a process, we can use the current | 252 // the ability to background/foreground a process, we can use the current |
| 247 // process's port instead. | 253 // process's port instead. |
| 248 FakePortProvider provider; | 254 FakePortProvider provider; |
| 249 EXPECT_TRUE(process.SetProcessBackgrounded(&provider, true)); | 255 EXPECT_TRUE(spawn_child.process.SetProcessBackgrounded(&provider, true)); |
| 250 EXPECT_TRUE(process.IsProcessBackgrounded(&provider)); | 256 EXPECT_TRUE(spawn_child.process.IsProcessBackgrounded(&provider)); |
| 251 EXPECT_TRUE(process.SetProcessBackgrounded(&provider, false)); | 257 EXPECT_TRUE(spawn_child.process.SetProcessBackgrounded(&provider, false)); |
| 252 EXPECT_FALSE(process.IsProcessBackgrounded(&provider)); | 258 EXPECT_FALSE(spawn_child.process.IsProcessBackgrounded(&provider)); |
| 253 | 259 |
| 254 #else | 260 #else |
| 255 process.SetProcessBackgrounded(true); | 261 spawn_child.process.SetProcessBackgrounded(true); |
| 256 process.SetProcessBackgrounded(false); | 262 spawn_child.process.SetProcessBackgrounded(false); |
| 257 #endif | 263 #endif |
| 258 int new_priority = process.GetPriority(); | 264 int new_priority = spawn_child.process.GetPriority(); |
| 259 EXPECT_EQ(old_priority, new_priority); | 265 EXPECT_EQ(old_priority, new_priority); |
| 260 } | 266 } |
| 261 | 267 |
| 262 // Same as SetProcessBackgrounded but to this very process. It uses | 268 // Same as SetProcessBackgrounded but to this very process. It uses |
| 263 // a different code path at least for Windows. | 269 // a different code path at least for Windows. |
| 264 TEST_F(ProcessTest, SetProcessBackgroundedSelf) { | 270 TEST_F(ProcessTest, SetProcessBackgroundedSelf) { |
| 265 if (!Process::CanBackgroundProcesses()) | 271 if (!Process::CanBackgroundProcesses()) |
| 266 return; | 272 return; |
| 267 Process process = Process::Current(); | 273 Process process = Process::Current(); |
| 268 int old_priority = process.GetPriority(); | 274 int old_priority = process.GetPriority(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 295 "2:freezer:/chrome_renderers/to_be_frozen\n" | 301 "2:freezer:/chrome_renderers/to_be_frozen\n" |
| 296 "1:cpu:/chrome_renderers/background\n"; | 302 "1:cpu:/chrome_renderers/background\n"; |
| 297 | 303 |
| 298 EXPECT_FALSE(IsProcessBackgroundedCGroup(kNotBackgrounded)); | 304 EXPECT_FALSE(IsProcessBackgroundedCGroup(kNotBackgrounded)); |
| 299 EXPECT_TRUE(IsProcessBackgroundedCGroup(kBackgrounded)); | 305 EXPECT_TRUE(IsProcessBackgroundedCGroup(kBackgrounded)); |
| 300 } | 306 } |
| 301 | 307 |
| 302 #endif // defined(OS_CHROMEOS) | 308 #endif // defined(OS_CHROMEOS) |
| 303 | 309 |
| 304 } // namespace base | 310 } // namespace base |
| OLD | NEW |