Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / chromeos / process_proxy / process_proxy_unittest.cc
blob97c7495242e0bf755583e30d8c9bb1f834d02b52
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/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/process/kill.h"
13 #include "base/process/process.h"
14 #include "base/threading/thread.h"
15 #include "chromeos/process_proxy/process_proxy_registry.h"
17 namespace chromeos {
19 namespace {
21 // The test line must have all distinct characters.
22 const char kTestLineToSend[] = "abcdefgh\n";
23 const char kTestLineExpected[] = "abcdefgh\r\n";
25 const char kCatCommand[] = "cat";
26 const char kStdoutType[] = "stdout";
27 const int kTestLineNum = 100;
29 class TestRunner {
30 public:
31 virtual ~TestRunner() {}
32 virtual void SetupExpectations(pid_t pid) = 0;
33 virtual void OnSomeRead(pid_t pid, const std::string& type,
34 const std::string& output) = 0;
35 virtual void StartRegistryTest(ProcessProxyRegistry* registry) = 0;
37 protected:
38 pid_t pid_;
41 class RegistryTestRunner : public TestRunner {
42 public:
43 ~RegistryTestRunner() override {}
45 void SetupExpectations(pid_t pid) override {
46 pid_ = pid;
47 left_to_check_index_[0] = 0;
48 left_to_check_index_[1] = 0;
49 // We consider that a line processing has started if a value in
50 // left_to_check__[index] is set to 0, thus -2.
51 lines_left_ = 2 * kTestLineNum - 2;
52 expected_line_ = kTestLineExpected;
55 // Method to test validity of received input. We will receive two streams of
56 // the same data. (input will be echoed twice by the testing process). Each
57 // stream will contain the same string repeated |kTestLineNum| times. So we
58 // have to match 2 * |kTestLineNum| lines. The problem is the received lines
59 // from different streams may be interleaved (e.g. we may receive
60 // abc|abcdef|defgh|gh). To deal with that, we allow to test received text
61 // against two lines. The lines MUST NOT have two same characters for this
62 // algorithm to work.
63 void OnSomeRead(pid_t pid,
64 const std::string& type,
65 const std::string& output) override {
66 EXPECT_EQ(type, kStdoutType);
67 EXPECT_EQ(pid_, pid);
69 bool valid = true;
70 for (size_t i = 0; i < output.length(); i++) {
71 // The character output[i] should be next in at least one of the lines we
72 // are testing.
73 valid = (ProcessReceivedCharacter(output[i], 0) ||
74 ProcessReceivedCharacter(output[i], 1));
75 EXPECT_TRUE(valid) << "Received: " << output;
78 if (!valid || TestSucceeded()) {
79 base::MessageLoop::current()->PostTask(FROM_HERE,
80 base::MessageLoop::QuitClosure());
84 void StartRegistryTest(ProcessProxyRegistry* registry) override {
85 for (int i = 0; i < kTestLineNum; i++) {
86 EXPECT_TRUE(registry->SendInput(pid_, kTestLineToSend));
90 private:
91 bool ProcessReceivedCharacter(char received, size_t stream) {
92 if (stream >= arraysize(left_to_check_index_))
93 return false;
94 bool success = left_to_check_index_[stream] < expected_line_.length() &&
95 expected_line_[left_to_check_index_[stream]] == received;
96 if (success)
97 left_to_check_index_[stream]++;
98 if (left_to_check_index_[stream] == expected_line_.length() &&
99 lines_left_ > 0) {
100 // Take another line to test for this stream, if there are any lines left.
101 // If not, this stream is done.
102 left_to_check_index_[stream] = 0;
103 lines_left_--;
105 return success;
108 bool TestSucceeded() {
109 return left_to_check_index_[0] == expected_line_.length() &&
110 left_to_check_index_[1] == expected_line_.length() &&
111 lines_left_ == 0;
114 size_t left_to_check_index_[2];
115 size_t lines_left_;
116 std::string expected_line_;
119 class RegistryNotifiedOnProcessExitTestRunner : public TestRunner {
120 public:
121 ~RegistryNotifiedOnProcessExitTestRunner() override {}
123 void SetupExpectations(pid_t pid) override {
124 output_received_ = false;
125 pid_ = pid;
128 void OnSomeRead(pid_t pid,
129 const std::string& type,
130 const std::string& output) override {
131 EXPECT_EQ(pid_, pid);
132 if (!output_received_) {
133 output_received_ = true;
134 EXPECT_EQ(type, "stdout");
135 EXPECT_EQ(output, "p");
136 base::Process process =
137 base::Process::DeprecatedGetProcessFromHandle(pid_);
138 process.Terminate(0, true);
139 return;
141 EXPECT_EQ("exit", type);
142 base::MessageLoop::current()->PostTask(FROM_HERE,
143 base::MessageLoop::QuitClosure());
146 void StartRegistryTest(ProcessProxyRegistry* registry) override {
147 EXPECT_TRUE(registry->SendInput(pid_, "p"));
150 private:
151 bool output_received_;
154 class SigIntTestRunner : public TestRunner {
155 public:
156 ~SigIntTestRunner() override {}
158 void SetupExpectations(pid_t pid) override { pid_ = pid; }
160 void OnSomeRead(pid_t pid,
161 const std::string& type,
162 const std::string& output) override {
163 EXPECT_EQ(pid_, pid);
164 // We may receive ^C on stdout, but we don't care about that, as long as we
165 // eventually received exit event.
166 if (type == "exit") {
167 base::MessageLoop::current()->PostTask(FROM_HERE,
168 base::MessageLoop::QuitClosure());
172 void StartRegistryTest(ProcessProxyRegistry* registry) override {
173 // Send SingInt and verify the process exited.
174 EXPECT_TRUE(registry->SendInput(pid_, "\003"));
178 } // namespace
180 class ProcessProxyTest : public testing::Test {
181 public:
182 ProcessProxyTest() {}
183 ~ProcessProxyTest() override {}
185 protected:
186 void InitRegistryTest() {
187 registry_ = ProcessProxyRegistry::Get();
189 EXPECT_TRUE(registry_->OpenProcess(
190 kCatCommand, &pid_,
191 base::Bind(&TestRunner::OnSomeRead,
192 base::Unretained(test_runner_.get()))));
194 test_runner_->SetupExpectations(pid_);
195 test_runner_->StartRegistryTest(registry_);
198 void EndRegistryTest() {
199 registry_->CloseProcess(pid_);
201 base::TerminationStatus status = base::GetTerminationStatus(pid_, NULL);
202 EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status);
203 if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
204 base::Process process =
205 base::Process::DeprecatedGetProcessFromHandle(pid_);
206 process.Terminate(0, true);
209 base::MessageLoop::current()->PostTask(FROM_HERE,
210 base::MessageLoop::QuitClosure());
213 void RunTest() {
214 base::MessageLoop::current()->PostTask(
215 FROM_HERE,
216 base::Bind(&ProcessProxyTest::InitRegistryTest,
217 base::Unretained(this)));
219 // Wait until all data from output watcher is received (QuitTask will be
220 // fired on watcher thread).
221 base::MessageLoop::current()->Run();
223 base::MessageLoop::current()->PostTask(
224 FROM_HERE,
225 base::Bind(&ProcessProxyTest::EndRegistryTest,
226 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