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.
12 #include "base/basictypes.h"
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/file_util.h"
16 #include "base/files/scoped_file.h"
17 #include "base/logging.h"
18 #include "base/posix/eintr_wrapper.h"
19 #include "base/threading/platform_thread.h"
20 #include "base/time/time.h"
21 #include "sandbox/linux/services/scoped_process.h"
22 #include "sandbox/linux/tests/unit_tests.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 void DoExit() { _exit(0); }
31 void ExitWithCode(int exit_code
) { _exit(exit_code
); }
33 void RaiseAndExit(int signal
) {
34 PCHECK(0 == raise(signal
));
40 TEST(ScopedProcess
, ScopedProcessNormalExit
) {
41 const int kCustomExitCode
= 12;
42 ScopedProcess
process(base::Bind(&ExitWithCode
, kCustomExitCode
));
43 bool got_signaled
= true;
44 int exit_code
= process
.WaitForExit(&got_signaled
);
45 EXPECT_FALSE(got_signaled
);
46 EXPECT_EQ(kCustomExitCode
, exit_code
);
48 // Verify that WaitForExit() can be called multiple times on the same
50 bool got_signaled2
= true;
51 int exit_code2
= process
.WaitForExit(&got_signaled2
);
52 EXPECT_FALSE(got_signaled2
);
53 EXPECT_EQ(kCustomExitCode
, exit_code2
);
56 // Disable this test on Android, SIGABRT is funky there.
57 TEST(ScopedProcess
, DISABLE_ON_ANDROID(ScopedProcessAbort
)) {
58 PCHECK(SIG_ERR
!= signal(SIGABRT
, SIG_DFL
));
59 ScopedProcess
process(base::Bind(&RaiseAndExit
, SIGABRT
));
60 bool got_signaled
= false;
61 int exit_code
= process
.WaitForExit(&got_signaled
);
62 EXPECT_TRUE(got_signaled
);
63 EXPECT_EQ(SIGABRT
, exit_code
);
66 TEST(ScopedProcess
, ScopedProcessSignaled
) {
67 ScopedProcess
process(base::Bind(&DoNothing
));
68 bool got_signaled
= false;
69 ASSERT_EQ(0, kill(process
.GetPid(), SIGKILL
));
70 int exit_code
= process
.WaitForExit(&got_signaled
);
71 EXPECT_TRUE(got_signaled
);
72 EXPECT_EQ(SIGKILL
, exit_code
);
75 TEST(ScopedProcess
, DiesForReal
) {
77 ASSERT_EQ(0, pipe(pipe_fds
));
78 base::ScopedFD
read_end_closer(pipe_fds
[0]);
79 base::ScopedFD
write_end_closer(pipe_fds
[1]);
81 { ScopedProcess
process(base::Bind(&DoExit
)); }
83 // Close writing end of the pipe.
84 write_end_closer
.reset();
87 ASSERT_EQ(0, fcntl(pipe_fds
[0], F_SETFL
, O_NONBLOCK
));
89 // If the child process is dead for real, there will be no writing end
90 // for this pipe left and read will EOF instead of returning EWOULDBLOCK.
91 ASSERT_EQ(0, read(pipe_fds
[0], &c
, 1));
94 TEST(ScopedProcess
, SynchronizationBasic
) {
95 ScopedProcess
process1(base::Bind(&DoNothing
));
96 EXPECT_TRUE(process1
.WaitForClosureToRun());
98 ScopedProcess
process2(base::Bind(&DoExit
));
99 // The closure didn't finish running normally. This case is simple enough
100 // that process.WaitForClosureToRun() should return false, even though the
101 // API does not guarantees that it will return at all.
102 EXPECT_FALSE(process2
.WaitForClosureToRun());
105 void SleepInMsAndWriteOneByte(int time_to_sleep
, int fd
) {
106 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(time_to_sleep
));
107 CHECK(1 == write(fd
, "1", 1));
110 TEST(ScopedProcess
, SynchronizationWorks
) {
112 ASSERT_EQ(0, pipe(pipe_fds
));
113 base::ScopedFD
read_end_closer(pipe_fds
[0]);
114 base::ScopedFD
write_end_closer(pipe_fds
[1]);
116 // Start a process with a closure that takes a little bit to run.
117 ScopedProcess
process(
118 base::Bind(&SleepInMsAndWriteOneByte
, 100, pipe_fds
[1]));
119 EXPECT_TRUE(process
.WaitForClosureToRun());
121 // Verify that the closure did, indeed, run.
122 ASSERT_EQ(0, fcntl(pipe_fds
[0], F_SETFL
, O_NONBLOCK
));
124 EXPECT_EQ(1, read(pipe_fds
[0], &c
, 1));
130 } // namespace sandbox