Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: chrome/browser/chromeos/process_proxy/process_proxy_browsertest.cc

Issue 12433023: Move chrome/browser/chromeos/process_proxy to chromeos (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 <string>
8 #include <sys/wait.h>
9
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop.h"
13 #include "base/posix/eintr_wrapper.h"
14 #include "base/process_util.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/threading/thread.h"
17 #include "chrome/browser/chromeos/process_proxy/process_proxy_registry.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/browser_thread.h"
21
22 using content::BrowserThread;
23
24 namespace {
25
26 // The test line must have all distinct characters.
27 const char kTestLineToSend[] = "abcdefgh\n";
28 const char kTestLineExpected[] = "abcdefgh\r\n";
29
30 const char kCatCommand[] = "cat";
31 const char kStdoutType[] = "stdout";
32 const int kTestLineNum = 100;
33
34 class TestRunner {
35 public:
36 virtual ~TestRunner() {}
37 virtual void SetupExpectations(pid_t pid) = 0;
38 virtual void OnSomeRead(pid_t pid, const std::string& type,
39 const std::string& output) = 0;
40 virtual void StartRegistryTest(ProcessProxyRegistry* registry) = 0;
41
42 protected:
43 pid_t pid_;
44 };
45
46 class RegistryTestRunner : public TestRunner {
47 public:
48 virtual ~RegistryTestRunner() {}
49
50 virtual void SetupExpectations(pid_t pid) OVERRIDE {
51 pid_ = pid;
52 left_to_check_index_[0] = 0;
53 left_to_check_index_[1] = 0;
54 // We consider that a line processing has started if a value in
55 // left_to_check__[index] is set to 0, thus -2.
56 lines_left_ = 2 * kTestLineNum - 2;
57 expected_line_ = kTestLineExpected;
58 }
59
60 // Method to test validity of received input. We will receive two streams of
61 // the same data. (input will be echoed twice by the testing process). Each
62 // stream will contain the same string repeated |kTestLineNum| times. So we
63 // have to match 2 * |kTestLineNum| lines. The problem is the received lines
64 // from different streams may be interleaved (e.g. we may receive
65 // abc|abcdef|defgh|gh). To deal with that, we allow to test received text
66 // against two lines. The lines MUST NOT have two same characters for this
67 // algorithm to work.
68 virtual void OnSomeRead(pid_t pid, const std::string& type,
69 const std::string& output) OVERRIDE {
70 EXPECT_EQ(type, kStdoutType);
71 EXPECT_EQ(pid_, pid);
72
73 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 }
81
82 if (!valid || TestSucceeded()) {
83 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
84 MessageLoop::QuitClosure());
85 }
86 }
87
88 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE {
89 for (int i = 0; i < kTestLineNum; i++) {
90 EXPECT_TRUE(registry->SendInput(pid_, kTestLineToSend));
91 }
92 }
93
94 private:
95 bool ProcessReceivedCharacter(char received, size_t stream) {
96 if (stream >= arraysize(left_to_check_index_))
97 return false;
98 bool success = left_to_check_index_[stream] < expected_line_.length() &&
99 expected_line_[left_to_check_index_[stream]] == received;
100 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() &&
114 left_to_check_index_[1] == expected_line_.length() &&
115 lines_left_ == 0;
116 }
117
118 size_t left_to_check_index_[2];
119 size_t lines_left_;
120 std::string expected_line_;
121 };
122
123 class RegistryNotifiedOnProcessExitTestRunner : public TestRunner {
124 public:
125 virtual ~RegistryNotifiedOnProcessExitTestRunner() {}
126
127 virtual void SetupExpectations(pid_t pid) OVERRIDE {
128 output_received_ = false;
129 pid_ = pid;
130 }
131
132 virtual void OnSomeRead(pid_t pid, const std::string& type,
133 const std::string& output) OVERRIDE {
134 EXPECT_EQ(pid_, pid);
135 if (!output_received_) {
136 output_received_ = true;
137 EXPECT_EQ(type, "stdout");
138 EXPECT_EQ(output, "p");
139 base::KillProcess(pid_, 0 , true);
140 return;
141 }
142 EXPECT_EQ("exit", type);
143 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
144 MessageLoop::QuitClosure());
145 }
146
147 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE {
148 EXPECT_TRUE(registry->SendInput(pid_, "p"));
149 }
150
151 private:
152 bool output_received_;
153 };
154
155 class SigIntTestRunner : public TestRunner {
156 public:
157 virtual ~SigIntTestRunner() {}
158
159 virtual void SetupExpectations(pid_t pid) OVERRIDE {
160 pid_ = pid;
161 }
162
163 virtual void OnSomeRead(pid_t pid, 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 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
170 MessageLoop::QuitClosure());
171 }
172 }
173
174 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE {
175 // Send SingInt and verify the process exited.
176 EXPECT_TRUE(registry->SendInput(pid_, "\003"));
177 }
178 };
179
180 } // namespace
181
182 class ProcessProxyTest : public InProcessBrowserTest {
183 public:
184 ProcessProxyTest() {}
185 virtual ~ProcessProxyTest() {}
186
187 protected:
188 void InitRegistryTest() {
189 registry_ = ProcessProxyRegistry::Get();
190
191 EXPECT_TRUE(registry_->OpenProcess(kCatCommand, &pid_,
192 base::Bind(&TestRunner::OnSomeRead,
193 base::Unretained(test_runner_.get()))));
194
195 test_runner_->SetupExpectations(pid_);
196 test_runner_->StartRegistryTest(registry_);
197 }
198
199 void EndRegistryTest() {
200 registry_->CloseProcess(pid_);
201
202 base::TerminationStatus status = base::GetTerminationStatus(pid_, NULL);
203 EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status);
204 if (status == base::TERMINATION_STATUS_STILL_RUNNING)
205 base::KillProcess(pid_, 0, true);
206
207 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
208 MessageLoop::QuitClosure());
209 }
210
211 void RunTest() {
212 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
213 base::Bind(&ProcessProxyTest::InitRegistryTest,
214 base::Unretained(this)));
215
216 // Wait until all data from output watcher is received (QuitTask will be
217 // fired on watcher thread).
218 content::RunMessageLoop();
219
220 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
221 base::Bind(&ProcessProxyTest::EndRegistryTest,
222 base::Unretained(this)));
223
224 // Wait until we clean up the process proxy.
225 content::RunMessageLoop();
226 }
227
228 scoped_ptr<TestRunner> test_runner_;
229
230 private:
231 ProcessProxyRegistry* registry_;
232 pid_t pid_;
233 };
234
235 // Test will open new process that will run cat command, and verify data we
236 // write to process gets echoed back.
237 IN_PROC_BROWSER_TEST_F(ProcessProxyTest, RegistryTest) {
238 test_runner_.reset(new RegistryTestRunner());
239 RunTest();
240 }
241
242 // Open new process, then kill it. Verifiy that we detect when the process dies.
243 IN_PROC_BROWSER_TEST_F(ProcessProxyTest, RegistryNotifiedOnProcessExit) {
244 test_runner_.reset(new RegistryNotifiedOnProcessExitTestRunner());
245 RunTest();
246 }
247
248 // Test verifies that \003 message send to process is processed as SigInt.
249 // Timing out on the waterfall: http://crbug.com/115064
250 IN_PROC_BROWSER_TEST_F(ProcessProxyTest, DISABLED_SigInt) {
251 test_runner_.reset(new SigIntTestRunner());
252 RunTest();
253 }
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/process_proxy/process_proxy.cc ('k') | chrome/browser/chromeos/process_proxy/process_proxy_registry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698