Add a nacl module args file.
[chromium-blink-merge.git] / chromeos / process_proxy / process_proxy_unittest.cc
blob20221c2918686c5c51596bf74f428f583259ee32
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>
7 #include <string>
9 #include "base/bind.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"
19 namespace chromeos {
21 namespace {
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;
31 class TestRunner {
32 public:
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;
39 protected:
40 pid_t pid_;
43 class RegistryTestRunner : public TestRunner {
44 public:
45 ~RegistryTestRunner() override {}
47 void SetupExpectations(pid_t pid) override {
48 pid_ = pid;
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
64 // algorithm to work.
65 void OnSomeRead(pid_t pid,
66 const std::string& type,
67 const std::string& output) override {
68 EXPECT_EQ(type, kStdoutType);
69 EXPECT_EQ(pid_, pid);
71 bool valid = true;
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
74 // are testing.
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));
92 private:
93 bool ProcessReceivedCharacter(char received, size_t stream) {
94 if (stream >= arraysize(left_to_check_index_))
95 return false;
96 bool success = left_to_check_index_[stream] < expected_line_.length() &&
97 expected_line_[left_to_check_index_[stream]] == received;
98 if (success)
99 left_to_check_index_[stream]++;
100 if (left_to_check_index_[stream] == expected_line_.length() &&
101 lines_left_ > 0) {
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;
105 lines_left_--;
107 return success;
110 bool TestSucceeded() {
111 return left_to_check_index_[0] == expected_line_.length() &&
112 left_to_check_index_[1] == expected_line_.length() &&
113 lines_left_ == 0;
116 size_t left_to_check_index_[2];
117 size_t lines_left_;
118 std::string expected_line_;
121 class RegistryNotifiedOnProcessExitTestRunner : public TestRunner {
122 public:
123 ~RegistryNotifiedOnProcessExitTestRunner() override {}
125 void SetupExpectations(pid_t pid) override {
126 output_received_ = false;
127 pid_ = pid;
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);
141 return;
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"));
152 private:
153 bool output_received_;
156 class SigIntTestRunner : public TestRunner {
157 public:
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"));
180 } // namespace
182 class ProcessProxyTest : public testing::Test {
183 public:
184 ProcessProxyTest() {}
185 ~ProcessProxyTest() override {}
187 protected:
188 void InitRegistryTest() {
189 registry_ = ProcessProxyRegistry::Get();
191 EXPECT_TRUE(registry_->OpenProcess(
192 kCatCommand, &pid_,
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 base::ThreadTaskRunnerHandle::Get()->PostTask(
212 FROM_HERE, base::MessageLoop::QuitClosure());
215 void RunTest() {
216 base::ThreadTaskRunnerHandle::Get()->PostTask(
217 FROM_HERE, base::Bind(&ProcessProxyTest::InitRegistryTest,
218 base::Unretained(this)));
220 // Wait until all data from output watcher is received (QuitTask will be
221 // fired on watcher thread).
222 base::MessageLoop::current()->Run();
224 base::ThreadTaskRunnerHandle::Get()->PostTask(
225 FROM_HERE,
226 base::Bind(&ProcessProxyTest::EndRegistryTest, base::Unretained(this)));
228 // Wait until we clean up the process proxy.
229 base::MessageLoop::current()->Run();
232 scoped_ptr<TestRunner> test_runner_;
234 private:
235 ProcessProxyRegistry* registry_;
236 pid_t pid_;
238 base::MessageLoop message_loop_;
241 // Test will open new process that will run cat command, and verify data we
242 // write to process gets echoed back.
243 TEST_F(ProcessProxyTest, RegistryTest) {
244 test_runner_.reset(new RegistryTestRunner());
245 RunTest();
248 // Open new process, then kill it. Verifiy that we detect when the process dies.
249 TEST_F(ProcessProxyTest, RegistryNotifiedOnProcessExit) {
250 test_runner_.reset(new RegistryNotifiedOnProcessExitTestRunner());
251 RunTest();
254 // Test verifies that \003 message send to process is processed as SigInt.
255 // Timing out on the waterfall: http://crbug.com/115064
256 TEST_F(ProcessProxyTest, DISABLED_SigInt) {
257 test_runner_.reset(new SigIntTestRunner());
258 RunTest();
261 } // namespace chromeos