Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / process_proxy / process_output_watcher_unittest.cc
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.
4
5 #include <gtest/gtest.h>
6
7 #include <queue>
8 #include <string>
9 #include <vector>
10
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"
20
21 namespace chromeos {
22
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) {}
28
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) {}
37
38   std::string input;
39   bool should_send_terminating_null;
40   std::string expected_output;
41 };
42
43 class ProcessWatcherExpectations {
44  public:
45   ProcessWatcherExpectations() {}
46
47   void SetTestCase(const TestCase& test_case) {
48     received_from_out_ = 0;
49
50     out_expectations_ = test_case.expected_output;
51     if (test_case.should_send_terminating_null)
52       out_expectations_.append(std::string("", 1));
53   }
54
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;
59
60     if (out_expectations_.length() == 0 && data.length() == 0)
61       return true;
62
63     EXPECT_LT(received_from_out_, out_expectations_.length());
64     if (received_from_out_ >= out_expectations_.length())
65       return false;
66
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;
71
72     received_from_out_ += data.length();
73     return true;
74   }
75
76   bool IsDone() {
77     return received_from_out_ >= out_expectations_.length();
78   }
79
80  private:
81   std::string out_expectations_;
82   size_t received_from_out_;
83 };
84
85 class ProcessOutputWatcherTest : public testing::Test {
86  public:
87   ProcessOutputWatcherTest() : output_watch_thread_started_(false),
88                                failed_(false) {
89   }
90
91   virtual ~ProcessOutputWatcherTest() {}
92
93   virtual void TearDown() override {
94     if (output_watch_thread_started_)
95       output_watch_thread_->Stop();
96   }
97
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();
103   }
104
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();
112     }
113   }
114
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;
121   }
122
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_);
128
129     int pt_pipe[2], stop_pipe[2];
130     ASSERT_FALSE(HANDLE_EINTR(pipe(pt_pipe)));
131     ASSERT_FALSE(HANDLE_EINTR(pipe(stop_pipe)));
132
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]));
139
140     for (size_t i = 0; i < test_cases.size(); i++) {
141       expectations_.SetTestCase(test_cases[i]);
142
143       base::RunLoop run_loop;
144       ASSERT_TRUE(test_case_done_callback_.is_null());
145       test_case_done_callback_ = run_loop.QuitClosure();
146
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));
155
156       run_loop.Run();
157       EXPECT_TRUE(expectations_.IsDone());
158       if (failed_)
159         break;
160     }
161
162     // Send stop signal. It is not important which string we send.
163     EXPECT_TRUE(base::WriteFileDescriptor(stop_pipe[1], "q", 1));
164
165     EXPECT_NE(-1, IGNORE_EINTR(close(stop_pipe[1])));
166     EXPECT_NE(-1, IGNORE_EINTR(close(pt_pipe[1])));
167   }
168
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;
177 };
178
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));
191
192   RunTest(test_cases);
193 }
194
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"));
200
201   RunTest(test_cases);
202 }
203
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"));
209
210   RunTest(test_cases);
211 }
212
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"));
218
219   RunTest(test_cases);
220 }
221
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"));
228
229   RunTest(test_cases);
230 }
231
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"));
235
236   RunTest(test_cases);
237 }
238
239 TEST_F(ProcessOutputWatcherTest, SoleThreeByteUTF8Character) {
240   std::vector<TestCase> test_cases;
241   test_cases.push_back(TestCase("\xe2\x82\xac", false, "\xe2\x82\xac"));
242
243   RunTest(test_cases);
244 }
245
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_"));
250
251   RunTest(test_cases);
252 }
253
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"));
257
258   RunTest(test_cases);
259 }
260
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"));
267
268   RunTest(test_cases);
269 }
270
271 TEST_F(ProcessOutputWatcherTest, ContainsInvalidUTF8) {
272   std::vector<TestCase> test_cases;
273   test_cases.push_back(TestCase("\xc2_", false, "\xc2_"));
274
275   RunTest(test_cases);
276 }
277
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"));
283
284   RunTest(test_cases);
285 }
286
287 TEST_F(ProcessOutputWatcherTest, EndsWithInvalidUTF8) {
288   std::vector<TestCase> test_cases;
289   test_cases.push_back(TestCase("\xff", false, "\xff"));
290
291   RunTest(test_cases);
292 }
293
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"));
299
300   RunTest(test_cases);
301 }
302
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));
313
314   RunTest(test_cases);
315 }
316
317 }  // namespace chromeos