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
3 // found in the LICENSE file.
5 #include "sandbox/linux/services/scoped_process.h"
10 #include <sys/types.h>
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/callback.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_file.h"
19 #include "base/logging.h"
20 #include "base/posix/eintr_wrapper.h"
21 #include "base/threading/platform_thread.h"
22 #include "base/time/time.h"
23 #include "sandbox/linux/tests/unit_tests.h"
24 #include "testing/gtest/include/gtest/gtest.h"
30 void DoExit() { _exit(0); }
32 void ExitWithCode(int exit_code
) { _exit(exit_code
); }
34 void RaiseAndExit(int signal
) {
35 PCHECK(0 == raise(signal
));
39 TEST(ScopedProcess
, ScopedProcessNormalExit
) {
40 const int kCustomExitCode
= 12;
41 ScopedProcess
process(base::Bind(&ExitWithCode
, kCustomExitCode
));
42 bool got_signaled
= true;
43 int exit_code
= process
.WaitForExit(&got_signaled
);
44 EXPECT_FALSE(got_signaled
);
45 EXPECT_EQ(kCustomExitCode
, exit_code
);
47 // Verify that WaitForExit() can be called multiple times on the same
49 bool got_signaled2
= true;
50 int exit_code2
= process
.WaitForExit(&got_signaled2
);
51 EXPECT_FALSE(got_signaled2
);
52 EXPECT_EQ(kCustomExitCode
, exit_code2
);
55 // Disable this test on Android, SIGABRT is funky there.
56 TEST(ScopedProcess
, DISABLE_ON_ANDROID(ScopedProcessAbort
)) {
57 PCHECK(SIG_ERR
!= signal(SIGABRT
, SIG_DFL
));
58 ScopedProcess
process(base::Bind(&RaiseAndExit
, SIGABRT
));
59 bool got_signaled
= false;
60 int exit_code
= process
.WaitForExit(&got_signaled
);
61 EXPECT_TRUE(got_signaled
);
62 EXPECT_EQ(SIGABRT
, exit_code
);
65 TEST(ScopedProcess
, ScopedProcessSignaled
) {
66 ScopedProcess
process(base::Bind(&base::DoNothing
));
67 bool got_signaled
= false;
68 ASSERT_EQ(0, kill(process
.GetPid(), SIGKILL
));
69 int exit_code
= process
.WaitForExit(&got_signaled
);
70 EXPECT_TRUE(got_signaled
);
71 EXPECT_EQ(SIGKILL
, exit_code
);
74 TEST(ScopedProcess
, DiesForReal
) {
76 ASSERT_EQ(0, pipe(pipe_fds
));
77 base::ScopedFD
read_end_closer(pipe_fds
[0]);
78 base::ScopedFD
write_end_closer(pipe_fds
[1]);
80 { ScopedProcess
process(base::Bind(&DoExit
)); }
82 // Close writing end of the pipe.
83 write_end_closer
.reset();
86 ASSERT_EQ(0, fcntl(pipe_fds
[0], F_SETFL
, O_NONBLOCK
));
88 // If the child process is dead for real, there will be no writing end
89 // for this pipe left and read will EOF instead of returning EWOULDBLOCK.
90 ASSERT_EQ(0, read(pipe_fds
[0], &c
, 1));
93 TEST(ScopedProcess
, SynchronizationBasic
) {
94 ScopedProcess
process1(base::Bind(&base::DoNothing
));
95 EXPECT_TRUE(process1
.WaitForClosureToRun());
97 ScopedProcess
process2(base::Bind(&DoExit
));
98 // The closure didn't finish running normally. This case is simple enough
99 // that process.WaitForClosureToRun() should return false, even though the
100 // API does not guarantees that it will return at all.
101 EXPECT_FALSE(process2
.WaitForClosureToRun());
104 void SleepInMsAndWriteOneByte(int time_to_sleep
, int fd
) {
105 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(time_to_sleep
));
106 CHECK(1 == write(fd
, "1", 1));
109 TEST(ScopedProcess
, SynchronizationWorks
) {
111 ASSERT_EQ(0, pipe(pipe_fds
));
112 base::ScopedFD
read_end_closer(pipe_fds
[0]);
113 base::ScopedFD
write_end_closer(pipe_fds
[1]);
115 // Start a process with a closure that takes a little bit to run.
116 ScopedProcess
process(
117 base::Bind(&SleepInMsAndWriteOneByte
, 100, pipe_fds
[1]));
118 EXPECT_TRUE(process
.WaitForClosureToRun());
120 // Verify that the closure did, indeed, run.
121 ASSERT_EQ(0, fcntl(pipe_fds
[0], F_SETFL
, O_NONBLOCK
));
123 EXPECT_EQ(1, read(pipe_fds
[0], &c
, 1));
129 } // namespace sandbox