1 // Copyright (c) 2012 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 <gtest/gtest.h>
10 #include "base/location.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/process/kill.h"
13 #include "base/process/process.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "chromeos/process_proxy/process_proxy_registry.h"
23 // The test line must have all distinct characters.
24 const char kTestLineToSend
[] = "abcdefgh\n";
25 const char kTestLineExpected
[] = "abcdefgh\r\n";
27 const char kCatCommand
[] = "cat";
28 const char kStdoutType
[] = "stdout";
29 const int kTestLineNum
= 100;
33 virtual ~TestRunner() {}
34 virtual void SetupExpectations(pid_t pid
) = 0;
35 virtual void OnSomeRead(pid_t pid
, const std::string
& type
,
36 const std::string
& output
) = 0;
37 virtual void StartRegistryTest(ProcessProxyRegistry
* registry
) = 0;
43 class RegistryTestRunner
: public TestRunner
{
45 ~RegistryTestRunner() override
{}
47 void SetupExpectations(pid_t pid
) override
{
49 left_to_check_index_
[0] = 0;
50 left_to_check_index_
[1] = 0;
51 // We consider that a line processing has started if a value in
52 // left_to_check__[index] is set to 0, thus -2.
53 lines_left_
= 2 * kTestLineNum
- 2;
54 expected_line_
= kTestLineExpected
;
57 // Method to test validity of received input. We will receive two streams of
58 // the same data. (input will be echoed twice by the testing process). Each
59 // stream will contain the same string repeated |kTestLineNum| times. So we
60 // have to match 2 * |kTestLineNum| lines. The problem is the received lines
61 // from different streams may be interleaved (e.g. we may receive
62 // abc|abcdef|defgh|gh). To deal with that, we allow to test received text
63 // against two lines. The lines MUST NOT have two same characters for this
65 void OnSomeRead(pid_t pid
,
66 const std::string
& type
,
67 const std::string
& output
) override
{
68 EXPECT_EQ(type
, kStdoutType
);
72 for (size_t i
= 0; i
< output
.length(); i
++) {
73 // The character output[i] should be next in at least one of the lines we
75 valid
= (ProcessReceivedCharacter(output
[i
], 0) ||
76 ProcessReceivedCharacter(output
[i
], 1));
77 EXPECT_TRUE(valid
) << "Received: " << output
;
80 if (!valid
|| TestSucceeded()) {
81 base::ThreadTaskRunnerHandle::Get()->PostTask(
82 FROM_HERE
, base::MessageLoop::QuitClosure());
86 void StartRegistryTest(ProcessProxyRegistry
* registry
) override
{
87 for (int i
= 0; i
< kTestLineNum
; i
++) {
88 EXPECT_TRUE(registry
->SendInput(pid_
, kTestLineToSend
));
93 bool ProcessReceivedCharacter(char received
, size_t stream
) {
94 if (stream
>= arraysize(left_to_check_index_
))
96 bool success
= left_to_check_index_
[stream
] < expected_line_
.length() &&
97 expected_line_
[left_to_check_index_
[stream
]] == received
;
99 left_to_check_index_
[stream
]++;
100 if (left_to_check_index_
[stream
] == expected_line_
.length() &&
102 // Take another line to test for this stream, if there are any lines left.
103 // If not, this stream is done.
104 left_to_check_index_
[stream
] = 0;
110 bool TestSucceeded() {
111 return left_to_check_index_
[0] == expected_line_
.length() &&
112 left_to_check_index_
[1] == expected_line_
.length() &&
116 size_t left_to_check_index_
[2];
118 std::string expected_line_
;
121 class RegistryNotifiedOnProcessExitTestRunner
: public TestRunner
{
123 ~RegistryNotifiedOnProcessExitTestRunner() override
{}
125 void SetupExpectations(pid_t pid
) override
{
126 output_received_
= false;
130 void OnSomeRead(pid_t pid
,
131 const std::string
& type
,
132 const std::string
& output
) override
{
133 EXPECT_EQ(pid_
, pid
);
134 if (!output_received_
) {
135 output_received_
= true;
136 EXPECT_EQ(type
, "stdout");
137 EXPECT_EQ(output
, "p");
138 base::Process process
=
139 base::Process::DeprecatedGetProcessFromHandle(pid_
);
140 process
.Terminate(0, true);
143 EXPECT_EQ("exit", type
);
144 base::ThreadTaskRunnerHandle::Get()->PostTask(
145 FROM_HERE
, base::MessageLoop::QuitClosure());
148 void StartRegistryTest(ProcessProxyRegistry
* registry
) override
{
149 EXPECT_TRUE(registry
->SendInput(pid_
, "p"));
153 bool output_received_
;
156 class SigIntTestRunner
: public TestRunner
{
158 ~SigIntTestRunner() override
{}
160 void SetupExpectations(pid_t pid
) override
{ pid_
= pid
; }
162 void OnSomeRead(pid_t pid
,
163 const std::string
& type
,
164 const std::string
& output
) override
{
165 EXPECT_EQ(pid_
, pid
);
166 // We may receive ^C on stdout, but we don't care about that, as long as we
167 // eventually received exit event.
168 if (type
== "exit") {
169 base::ThreadTaskRunnerHandle::Get()->PostTask(
170 FROM_HERE
, base::MessageLoop::QuitClosure());
174 void StartRegistryTest(ProcessProxyRegistry
* registry
) override
{
175 // Send SingInt and verify the process exited.
176 EXPECT_TRUE(registry
->SendInput(pid_
, "\003"));
182 class ProcessProxyTest
: public testing::Test
{
184 ProcessProxyTest() {}
185 ~ProcessProxyTest() override
{}
188 void InitRegistryTest() {
189 registry_
= ProcessProxyRegistry::Get();
191 EXPECT_TRUE(registry_
->OpenProcess(
193 base::Bind(&TestRunner::OnSomeRead
,
194 base::Unretained(test_runner_
.get()))));
196 test_runner_
->SetupExpectations(pid_
);
197 test_runner_
->StartRegistryTest(registry_
);
200 void EndRegistryTest() {
201 registry_
->CloseProcess(pid_
);
203 base::TerminationStatus status
= base::GetTerminationStatus(pid_
, NULL
);
204 EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING
, status
);
205 if (status
== base::TERMINATION_STATUS_STILL_RUNNING
) {
206 base::Process process
=
207 base::Process::DeprecatedGetProcessFromHandle(pid_
);
208 process
.Terminate(0, true);
211 registry_
->ShutDown();
213 base::ThreadTaskRunnerHandle::Get()->PostTask(
214 FROM_HERE
, base::MessageLoop::QuitClosure());
218 base::ThreadTaskRunnerHandle::Get()->PostTask(
219 FROM_HERE
, base::Bind(&ProcessProxyTest::InitRegistryTest
,
220 base::Unretained(this)));
222 // Wait until all data from output watcher is received (QuitTask will be
223 // fired on watcher thread).
224 base::MessageLoop::current()->Run();
226 base::ThreadTaskRunnerHandle::Get()->PostTask(
228 base::Bind(&ProcessProxyTest::EndRegistryTest
, base::Unretained(this)));
230 // Wait until we clean up the process proxy.
231 base::MessageLoop::current()->Run();
234 scoped_ptr
<TestRunner
> test_runner_
;
237 ProcessProxyRegistry
* registry_
;
240 base::MessageLoop message_loop_
;
243 // Test will open new process that will run cat command, and verify data we
244 // write to process gets echoed back.
245 TEST_F(ProcessProxyTest
, RegistryTest
) {
246 test_runner_
.reset(new RegistryTestRunner());
250 // Open new process, then kill it. Verifiy that we detect when the process dies.
251 TEST_F(ProcessProxyTest
, RegistryNotifiedOnProcessExit
) {
252 test_runner_
.reset(new RegistryNotifiedOnProcessExitTestRunner());
256 // Test verifies that \003 message send to process is processed as SigInt.
257 // Timing out on the waterfall: http://crbug.com/115064
258 TEST_F(ProcessProxyTest
, DISABLED_SigInt
) {
259 test_runner_
.reset(new SigIntTestRunner());
263 } // namespace chromeos