[Telemetry] Reenable unused-import lint check for telemetry.
[chromium-blink-merge.git] / chromeos / process_proxy / process_output_watcher_unittest.cc
blob5732467943b32f0e0508fd8bbcfb4cada61f455d
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 <queue>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/files/file_util.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string_util.h"
18 #include "base/threading/thread.h"
19 #include "chromeos/process_proxy/process_output_watcher.h"
21 namespace chromeos {
23 struct TestCase {
24 TestCase(const std::string& input, bool send_terminating_null)
25 : input(input),
26 should_send_terminating_null(send_terminating_null),
27 expected_output(input) {}
29 // Conctructor for cases where the output is not expected to be the same as
30 // input.
31 TestCase(const std::string& input,
32 bool send_terminating_null,
33 const std::string& expected_output)
34 : input(input),
35 should_send_terminating_null(send_terminating_null),
36 expected_output(expected_output) {}
38 std::string input;
39 bool should_send_terminating_null;
40 std::string expected_output;
43 class ProcessWatcherExpectations {
44 public:
45 ProcessWatcherExpectations() {}
47 void SetTestCase(const TestCase& test_case) {
48 received_from_out_ = 0;
50 out_expectations_ = test_case.expected_output;
51 if (test_case.should_send_terminating_null)
52 out_expectations_.append(std::string("", 1));
55 bool CheckExpectations(const std::string& data, ProcessOutputType type) {
56 EXPECT_EQ(PROCESS_OUTPUT_TYPE_OUT, type);
57 if (type != PROCESS_OUTPUT_TYPE_OUT)
58 return false;
60 if (out_expectations_.length() == 0 && data.length() == 0)
61 return true;
63 EXPECT_LT(received_from_out_, out_expectations_.length());
64 if (received_from_out_ >= out_expectations_.length())
65 return false;
67 EXPECT_EQ(received_from_out_,
68 out_expectations_.find(data, received_from_out_));
69 if (received_from_out_ != out_expectations_.find(data, received_from_out_))
70 return false;
72 received_from_out_ += data.length();
73 return true;
76 bool IsDone() {
77 return received_from_out_ >= out_expectations_.length();
80 private:
81 std::string out_expectations_;
82 size_t received_from_out_;
85 class ProcessOutputWatcherTest : public testing::Test {
86 public:
87 ProcessOutputWatcherTest() : output_watch_thread_started_(false),
88 failed_(false) {
91 ~ProcessOutputWatcherTest() override {}
93 void TearDown() override {
94 if (output_watch_thread_started_)
95 output_watch_thread_->Stop();
98 void StartWatch(int pt, int stop) {
99 // This will delete itself.
100 ProcessOutputWatcher* crosh_watcher = new ProcessOutputWatcher(pt, stop,
101 base::Bind(&ProcessOutputWatcherTest::OnRead, base::Unretained(this)));
102 crosh_watcher->Start();
105 void OnRead(ProcessOutputType type, const std::string& output) {
106 ASSERT_FALSE(failed_);
107 failed_ = !expectations_.CheckExpectations(output, type);
108 if (failed_ || expectations_.IsDone()) {
109 ASSERT_FALSE(test_case_done_callback_.is_null());
110 message_loop_.PostTask(FROM_HERE, test_case_done_callback_);
111 test_case_done_callback_.Reset();
115 protected:
116 std::string VeryLongString() {
117 std::string result = "0123456789";
118 for (int i = 0; i < 8; i++)
119 result = result.append(result);
120 return result;
123 void RunTest(const std::vector<TestCase>& test_cases) {
124 ASSERT_FALSE(output_watch_thread_started_);
125 output_watch_thread_.reset(new base::Thread("ProcessOutpuWatchThread"));
126 output_watch_thread_started_ = output_watch_thread_->Start();
127 ASSERT_TRUE(output_watch_thread_started_);
129 int pt_pipe[2], stop_pipe[2];
130 ASSERT_FALSE(HANDLE_EINTR(pipe(pt_pipe)));
131 ASSERT_FALSE(HANDLE_EINTR(pipe(stop_pipe)));
133 output_watch_thread_->message_loop()->PostTask(
134 FROM_HERE,
135 base::Bind(&ProcessOutputWatcherTest::StartWatch,
136 base::Unretained(this),
137 pt_pipe[0],
138 stop_pipe[0]));
140 for (size_t i = 0; i < test_cases.size(); i++) {
141 expectations_.SetTestCase(test_cases[i]);
143 base::RunLoop run_loop;
144 ASSERT_TRUE(test_case_done_callback_.is_null());
145 test_case_done_callback_ = run_loop.QuitClosure();
147 const std::string& test_str = test_cases[i].input;
148 // Let's make inputs not NULL terminated, unless other is specified in
149 // the test case.
150 ssize_t test_size = test_str.length() * sizeof(*test_str.c_str());
151 if (test_cases[i].should_send_terminating_null)
152 test_size += sizeof(*test_str.c_str());
153 EXPECT_TRUE(base::WriteFileDescriptor(pt_pipe[1], test_str.c_str(),
154 test_size));
156 run_loop.Run();
157 EXPECT_TRUE(expectations_.IsDone());
158 if (failed_)
159 break;
162 // Send stop signal. It is not important which string we send.
163 EXPECT_TRUE(base::WriteFileDescriptor(stop_pipe[1], "q", 1));
165 EXPECT_NE(-1, IGNORE_EINTR(close(stop_pipe[1])));
166 EXPECT_NE(-1, IGNORE_EINTR(close(pt_pipe[1])));
169 private:
170 base::Closure test_case_done_callback_;
171 base::MessageLoop message_loop_;
172 scoped_ptr<base::Thread> output_watch_thread_;
173 bool output_watch_thread_started_;
174 bool failed_;
175 ProcessWatcherExpectations expectations_;
176 std::vector<TestCase> exp;
179 // http://crbug.com/396496
180 TEST_F(ProcessOutputWatcherTest, DISABLED_OutputWatcher) {
181 std::vector<TestCase> test_cases;
182 test_cases.push_back(TestCase("t", false));
183 test_cases.push_back(TestCase("testing output\n", false));
184 test_cases.push_back(TestCase("testing error\n", false));
185 test_cases.push_back(TestCase("testing error1\n", false));
186 test_cases.push_back(TestCase("testing output1\n", false));
187 test_cases.push_back(TestCase("testing output2\n", false));
188 test_cases.push_back(TestCase("testing output3\n", false));
189 test_cases.push_back(TestCase(VeryLongString(), false));
190 test_cases.push_back(TestCase("testing error2\n", false));
192 RunTest(test_cases);
195 // http://crbug.com/396496
196 TEST_F(ProcessOutputWatcherTest, DISABLED_SplitUTF8Character) {
197 std::vector<TestCase> test_cases;
198 test_cases.push_back(TestCase("test1\xc2", false, "test1"));
199 test_cases.push_back(TestCase("\xb5test1", false, "\xc2\xb5test1"));
201 RunTest(test_cases);
204 // http://crbug.com/396496
205 TEST_F(ProcessOutputWatcherTest, DISABLED_SplitSoleUTF8Character) {
206 std::vector<TestCase> test_cases;
207 test_cases.push_back(TestCase("\xc2", false, ""));
208 test_cases.push_back(TestCase("\xb5", false, "\xc2\xb5"));
210 RunTest(test_cases);
213 // http://crbug.com/396496
214 TEST_F(ProcessOutputWatcherTest, DISABLED_SplitUTF8CharacterLength3) {
215 std::vector<TestCase> test_cases;
216 test_cases.push_back(TestCase("test3\xe2\x82", false, "test3"));
217 test_cases.push_back(TestCase("\xac", false, "\xe2\x82\xac"));
219 RunTest(test_cases);
222 // http://crbug.com/396496
223 TEST_F(ProcessOutputWatcherTest, DISABLED_SplitSoleUTF8CharacterThreeWays) {
224 std::vector<TestCase> test_cases;
225 test_cases.push_back(TestCase("\xe2", false, ""));
226 test_cases.push_back(TestCase("\x82", false, ""));
227 test_cases.push_back(TestCase("\xac", false, "\xe2\x82\xac"));
229 RunTest(test_cases);
232 TEST_F(ProcessOutputWatcherTest, EndsWithThreeByteUTF8Character) {
233 std::vector<TestCase> test_cases;
234 test_cases.push_back(TestCase("test\xe2\x82\xac", false, "test\xe2\x82\xac"));
236 RunTest(test_cases);
239 TEST_F(ProcessOutputWatcherTest, SoleThreeByteUTF8Character) {
240 std::vector<TestCase> test_cases;
241 test_cases.push_back(TestCase("\xe2\x82\xac", false, "\xe2\x82\xac"));
243 RunTest(test_cases);
246 TEST_F(ProcessOutputWatcherTest, HasThreeByteUTF8Character) {
247 std::vector<TestCase> test_cases;
248 test_cases.push_back(
249 TestCase("test\xe2\x82\xac_", false, "test\xe2\x82\xac_"));
251 RunTest(test_cases);
254 TEST_F(ProcessOutputWatcherTest, MulitByteUTF8CharNullTerminated) {
255 std::vector<TestCase> test_cases;
256 test_cases.push_back(TestCase("test\xe2\x82\xac", true, "test\xe2\x82\xac"));
258 RunTest(test_cases);
261 // http://crbug.com/396496
262 TEST_F(ProcessOutputWatcherTest, DISABLED_MultipleMultiByteUTF8Characters) {
263 std::vector<TestCase> test_cases;
264 test_cases.push_back(
265 TestCase("test\xe2\x82\xac\xc2", false, "test\xe2\x82\xac"));
266 test_cases.push_back(TestCase("\xb5", false, "\xc2\xb5"));
268 RunTest(test_cases);
271 TEST_F(ProcessOutputWatcherTest, ContainsInvalidUTF8) {
272 std::vector<TestCase> test_cases;
273 test_cases.push_back(TestCase("\xc2_", false, "\xc2_"));
275 RunTest(test_cases);
278 // http://crbug.com/396496
279 TEST_F(ProcessOutputWatcherTest, DISABLED_InvalidUTF8SeriesOfTrailingBytes) {
280 std::vector<TestCase> test_cases;
281 test_cases.push_back(TestCase("\x82\x82\x82", false, "\x82\x82\x82"));
282 test_cases.push_back(TestCase("\x82\x82\x82", false, "\x82\x82\x82"));
284 RunTest(test_cases);
287 TEST_F(ProcessOutputWatcherTest, EndsWithInvalidUTF8) {
288 std::vector<TestCase> test_cases;
289 test_cases.push_back(TestCase("\xff", false, "\xff"));
291 RunTest(test_cases);
294 // http://crbug.com/396496
295 TEST_F(ProcessOutputWatcherTest, DISABLED_FourByteUTF8) {
296 std::vector<TestCase> test_cases;
297 test_cases.push_back(TestCase("\xf0\xa4\xad", false, ""));
298 test_cases.push_back(TestCase("\xa2", false, "\xf0\xa4\xad\xa2"));
300 RunTest(test_cases);
303 // Verifies that sending '\0' generates PROCESS_OUTPUT_TYPE_OUT event and does
304 // not terminate output watcher.
305 // http://crbug.com/396496
306 TEST_F(ProcessOutputWatcherTest, DISABLED_SendNull) {
307 std::vector<TestCase> test_cases;
308 // This will send '\0' to output watcher.
309 test_cases.push_back(TestCase("", true));
310 // Let's verify that next input also gets detected (i.e. output watcher does
311 // not exit after seeing '\0' from previous test case).
312 test_cases.push_back(TestCase("a", true));
314 RunTest(test_cases);
317 } // namespace chromeos