blob: 292b3b673c786e4c90151e3bcae421baf5a5741d [file] [log] [blame]
[email protected]a504ba72012-01-25 01:42:571// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]8f427982011-12-13 23:40:232// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <gtest/gtest.h>
avi6e1a22d2015-12-21 03:43:206#include <stddef.h>
[email protected]8f427982011-12-13 23:40:237
dcheng0a6e80c2016-04-08 18:37:388#include <memory>
[email protected]8f427982011-12-13 23:40:239#include <string>
[email protected]8f427982011-12-13 23:40:2310
11#include "base/bind.h"
skyostil1472c842015-06-11 18:40:2412#include "base/location.h"
[email protected]998557362013-07-23 14:12:1313#include "base/process/kill.h"
rvargasf8d789c2015-04-01 04:10:1214#include "base/process/process.h"
skyostil1472c842015-06-11 18:40:2415#include "base/single_thread_task_runner.h"
[email protected]8f427982011-12-13 23:40:2316#include "base/threading/thread.h"
gabd85cc46b2016-05-11 18:23:2017#include "base/threading/thread_task_runner_handle.h"
[email protected]3a01162b2013-03-12 20:22:4818#include "chromeos/process_proxy/process_proxy_registry.h"
[email protected]8f427982011-12-13 23:40:2319
[email protected]3a01162b2013-03-12 20:22:4820namespace chromeos {
[email protected]8f427982011-12-13 23:40:2321
22namespace {
23
[email protected]56f3a812012-03-20 17:13:1924// The test line must have all distinct characters.
25const char kTestLineToSend[] = "abcdefgh\n";
26const char kTestLineExpected[] = "abcdefgh\r\n";
27
[email protected]8f427982011-12-13 23:40:2328const char kCatCommand[] = "cat";
29const char kStdoutType[] = "stdout";
30const int kTestLineNum = 100;
31
[email protected]a504ba72012-01-25 01:42:5732class TestRunner {
[email protected]8f427982011-12-13 23:40:2333 public:
[email protected]a504ba72012-01-25 01:42:5734 virtual ~TestRunner() {}
tbarzic170f12c2016-01-08 05:15:2935 virtual void SetupExpectations(int terminal_id) = 0;
36 virtual void OnSomeRead(int terminal_id,
37 const std::string& type,
[email protected]a504ba72012-01-25 01:42:5738 const std::string& output) = 0;
39 virtual void StartRegistryTest(ProcessProxyRegistry* registry) = 0;
[email protected]8f427982011-12-13 23:40:2340
[email protected]a504ba72012-01-25 01:42:5741 protected:
tbarzic170f12c2016-01-08 05:15:2942 int terminal_id_;
[email protected]a504ba72012-01-25 01:42:5743};
44
45class RegistryTestRunner : public TestRunner {
46 public:
dchengae98daa2015-01-21 20:30:4947 ~RegistryTestRunner() override {}
[email protected]a504ba72012-01-25 01:42:5748
tbarzic170f12c2016-01-08 05:15:2949 void SetupExpectations(int terminal_id) override {
50 terminal_id_ = terminal_id;
[email protected]56f3a812012-03-20 17:13:1951 left_to_check_index_[0] = 0;
52 left_to_check_index_[1] = 0;
53 // We consider that a line processing has started if a value in
54 // left_to_check__[index] is set to 0, thus -2.
55 lines_left_ = 2 * kTestLineNum - 2;
56 expected_line_ = kTestLineExpected;
[email protected]8f427982011-12-13 23:40:2357 }
58
[email protected]56f3a812012-03-20 17:13:1959 // Method to test validity of received input. We will receive two streams of
60 // the same data. (input will be echoed twice by the testing process). Each
61 // stream will contain the same string repeated |kTestLineNum| times. So we
62 // have to match 2 * |kTestLineNum| lines. The problem is the received lines
63 // from different streams may be interleaved (e.g. we may receive
64 // abc|abcdef|defgh|gh). To deal with that, we allow to test received text
65 // against two lines. The lines MUST NOT have two same characters for this
66 // algorithm to work.
tbarzic170f12c2016-01-08 05:15:2967 void OnSomeRead(int terminal_id,
dchengae98daa2015-01-21 20:30:4968 const std::string& type,
69 const std::string& output) override {
[email protected]8f427982011-12-13 23:40:2370 EXPECT_EQ(type, kStdoutType);
tbarzic170f12c2016-01-08 05:15:2971 EXPECT_EQ(terminal_id_, terminal_id);
[email protected]8f427982011-12-13 23:40:2372
[email protected]56f3a812012-03-20 17:13:1973 bool valid = true;
74 for (size_t i = 0; i < output.length(); i++) {
75 // The character output[i] should be next in at least one of the lines we
76 // are testing.
77 valid = (ProcessReceivedCharacter(output[i], 0) ||
78 ProcessReceivedCharacter(output[i], 1));
79 EXPECT_TRUE(valid) << "Received: " << output;
80 }
[email protected]8f427982011-12-13 23:40:2381
[email protected]56f3a812012-03-20 17:13:1982 if (!valid || TestSucceeded()) {
skyostil1472c842015-06-11 18:40:2483 base::ThreadTaskRunnerHandle::Get()->PostTask(
ki.stfu55e0b362015-10-12 17:45:5584 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
[email protected]8f427982011-12-13 23:40:2385 }
86 }
87
dchengae98daa2015-01-21 20:30:4988 void StartRegistryTest(ProcessProxyRegistry* registry) override {
[email protected]a504ba72012-01-25 01:42:5789 for (int i = 0; i < kTestLineNum; i++) {
tbarzic170f12c2016-01-08 05:15:2990 EXPECT_TRUE(registry->SendInput(terminal_id_, kTestLineToSend));
[email protected]a504ba72012-01-25 01:42:5791 }
92 }
93
94 private:
[email protected]56f3a812012-03-20 17:13:1995 bool ProcessReceivedCharacter(char received, size_t stream) {
[email protected]b1701a72012-03-22 23:59:0396 if (stream >= arraysize(left_to_check_index_))
[email protected]56f3a812012-03-20 17:13:1997 return false;
98 bool success = left_to_check_index_[stream] < expected_line_.length() &&
[email protected]3a01162b2013-03-12 20:22:4899 expected_line_[left_to_check_index_[stream]] == received;
[email protected]56f3a812012-03-20 17:13:19100 if (success)
101 left_to_check_index_[stream]++;
102 if (left_to_check_index_[stream] == expected_line_.length() &&
103 lines_left_ > 0) {
104 // Take another line to test for this stream, if there are any lines left.
105 // If not, this stream is done.
106 left_to_check_index_[stream] = 0;
107 lines_left_--;
108 }
109 return success;
110 }
111
112 bool TestSucceeded() {
113 return left_to_check_index_[0] == expected_line_.length() &&
[email protected]3a01162b2013-03-12 20:22:48114 left_to_check_index_[1] == expected_line_.length() &&
115 lines_left_ == 0;
[email protected]56f3a812012-03-20 17:13:19116 }
117
118 size_t left_to_check_index_[2];
119 size_t lines_left_;
120 std::string expected_line_;
[email protected]a504ba72012-01-25 01:42:57121};
122
123class RegistryNotifiedOnProcessExitTestRunner : public TestRunner {
124 public:
dchengae98daa2015-01-21 20:30:49125 ~RegistryNotifiedOnProcessExitTestRunner() override {}
[email protected]a504ba72012-01-25 01:42:57126
tbarzic170f12c2016-01-08 05:15:29127 void SetupExpectations(int terminal_id) override {
[email protected]a504ba72012-01-25 01:42:57128 output_received_ = false;
tbarzic170f12c2016-01-08 05:15:29129 terminal_id_ = terminal_id;
[email protected]a504ba72012-01-25 01:42:57130 }
131
tbarzic170f12c2016-01-08 05:15:29132 void OnSomeRead(int terminal_id,
dchengae98daa2015-01-21 20:30:49133 const std::string& type,
134 const std::string& output) override {
tbarzic170f12c2016-01-08 05:15:29135 EXPECT_EQ(terminal_id_, terminal_id);
[email protected]a504ba72012-01-25 01:42:57136 if (!output_received_) {
137 output_received_ = true;
138 EXPECT_EQ(type, "stdout");
139 EXPECT_EQ(output, "p");
rvargasf8d789c2015-04-01 04:10:12140 base::Process process =
tbarzic170f12c2016-01-08 05:15:29141 base::Process::DeprecatedGetProcessFromHandle(terminal_id_);
rvargasf8d789c2015-04-01 04:10:12142 process.Terminate(0, true);
[email protected]a504ba72012-01-25 01:42:57143 return;
144 }
145 EXPECT_EQ("exit", type);
skyostil1472c842015-06-11 18:40:24146 base::ThreadTaskRunnerHandle::Get()->PostTask(
ki.stfu55e0b362015-10-12 17:45:55147 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
[email protected]a504ba72012-01-25 01:42:57148 }
149
dchengae98daa2015-01-21 20:30:49150 void StartRegistryTest(ProcessProxyRegistry* registry) override {
tbarzic170f12c2016-01-08 05:15:29151 EXPECT_TRUE(registry->SendInput(terminal_id_, "p"));
[email protected]a504ba72012-01-25 01:42:57152 }
153
154 private:
155 bool output_received_;
156};
157
[email protected]a504ba72012-01-25 01:42:57158} // namespace
159
[email protected]3a01162b2013-03-12 20:22:48160class ProcessProxyTest : public testing::Test {
[email protected]a504ba72012-01-25 01:42:57161 public:
162 ProcessProxyTest() {}
dchengae98daa2015-01-21 20:30:49163 ~ProcessProxyTest() override {}
[email protected]a504ba72012-01-25 01:42:57164
165 protected:
[email protected]8f427982011-12-13 23:40:23166 void InitRegistryTest() {
167 registry_ = ProcessProxyRegistry::Get();
168
tbarzic170f12c2016-01-08 05:15:29169 terminal_id_ = registry_->OpenProcess(
170 kCatCommand,
171 base::Bind(&ProcessProxyTest::HandleRead, base::Unretained(this)));
[email protected]8f427982011-12-13 23:40:23172
tbarzic170f12c2016-01-08 05:15:29173 EXPECT_GE(terminal_id_, 0);
174 test_runner_->SetupExpectations(terminal_id_);
[email protected]a504ba72012-01-25 01:42:57175 test_runner_->StartRegistryTest(registry_);
[email protected]8f427982011-12-13 23:40:23176 }
177
tbarzic170f12c2016-01-08 05:15:29178 void HandleRead(int terminal_id,
179 const std::string& output_type,
180 const std::string& output) {
181 test_runner_->OnSomeRead(terminal_id, output_type, output);
182 registry_->AckOutput(terminal_id);
183 }
[email protected]8f427982011-12-13 23:40:23184
tbarzic170f12c2016-01-08 05:15:29185 void EndRegistryTest() {
186 registry_->CloseProcess(terminal_id_);
187
188 base::TerminationStatus status =
189 base::GetTerminationStatus(terminal_id_, NULL);
[email protected]dc86a86d2011-12-21 00:11:36190 EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status);
rvargasf8d789c2015-04-01 04:10:12191 if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
192 base::Process process =
tbarzic170f12c2016-01-08 05:15:29193 base::Process::DeprecatedGetProcessFromHandle(terminal_id_);
rvargasf8d789c2015-04-01 04:10:12194 process.Terminate(0, true);
195 }
[email protected]8f427982011-12-13 23:40:23196
tbarzic6ca50552015-08-10 22:32:45197 registry_->ShutDown();
198
skyostil1472c842015-06-11 18:40:24199 base::ThreadTaskRunnerHandle::Get()->PostTask(
ki.stfu55e0b362015-10-12 17:45:55200 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
[email protected]8f427982011-12-13 23:40:23201 }
202
[email protected]a504ba72012-01-25 01:42:57203 void RunTest() {
skyostil1472c842015-06-11 18:40:24204 base::ThreadTaskRunnerHandle::Get()->PostTask(
205 FROM_HERE, base::Bind(&ProcessProxyTest::InitRegistryTest,
206 base::Unretained(this)));
[email protected]8f427982011-12-13 23:40:23207
[email protected]a504ba72012-01-25 01:42:57208 // Wait until all data from output watcher is received (QuitTask will be
209 // fired on watcher thread).
[email protected]df905632013-05-29 23:04:36210 base::MessageLoop::current()->Run();
[email protected]8f427982011-12-13 23:40:23211
skyostil1472c842015-06-11 18:40:24212 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]3a01162b2013-03-12 20:22:48213 FROM_HERE,
skyostil1472c842015-06-11 18:40:24214 base::Bind(&ProcessProxyTest::EndRegistryTest, base::Unretained(this)));
[email protected]8f427982011-12-13 23:40:23215
[email protected]a504ba72012-01-25 01:42:57216 // Wait until we clean up the process proxy.
[email protected]df905632013-05-29 23:04:36217 base::MessageLoop::current()->Run();
[email protected]a504ba72012-01-25 01:42:57218 }
219
dcheng0a6e80c2016-04-08 18:37:38220 std::unique_ptr<TestRunner> test_runner_;
[email protected]a504ba72012-01-25 01:42:57221
222 private:
[email protected]8f427982011-12-13 23:40:23223 ProcessProxyRegistry* registry_;
tbarzic170f12c2016-01-08 05:15:29224 int terminal_id_;
[email protected]3a01162b2013-03-12 20:22:48225
[email protected]df905632013-05-29 23:04:36226 base::MessageLoop message_loop_;
[email protected]8f427982011-12-13 23:40:23227};
228
229// Test will open new process that will run cat command, and verify data we
230// write to process gets echoed back.
[email protected]3a01162b2013-03-12 20:22:48231TEST_F(ProcessProxyTest, RegistryTest) {
[email protected]a504ba72012-01-25 01:42:57232 test_runner_.reset(new RegistryTestRunner());
233 RunTest();
[email protected]8f427982011-12-13 23:40:23234}
235
[email protected]a504ba72012-01-25 01:42:57236// Open new process, then kill it. Verifiy that we detect when the process dies.
[email protected]3a01162b2013-03-12 20:22:48237TEST_F(ProcessProxyTest, RegistryNotifiedOnProcessExit) {
[email protected]a504ba72012-01-25 01:42:57238 test_runner_.reset(new RegistryNotifiedOnProcessExitTestRunner());
239 RunTest();
240}
241
[email protected]3a01162b2013-03-12 20:22:48242} // namespace chromeos