OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <gtest/gtest.h> | 5 #include <gtest/gtest.h> |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <sys/wait.h> | 8 #include <sys/wait.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/posix/eintr_wrapper.h" | 13 #include "base/posix/eintr_wrapper.h" |
14 #include "base/process_util.h" | 14 #include "base/process_util.h" |
15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
16 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
17 #include "chrome/browser/chromeos/process_proxy/process_proxy_registry.h" | 17 #include "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 | 18 |
22 using content::BrowserThread; | 19 namespace chromeos { |
23 | 20 |
24 namespace { | 21 namespace { |
25 | 22 |
26 // The test line must have all distinct characters. | 23 // The test line must have all distinct characters. |
27 const char kTestLineToSend[] = "abcdefgh\n"; | 24 const char kTestLineToSend[] = "abcdefgh\n"; |
28 const char kTestLineExpected[] = "abcdefgh\r\n"; | 25 const char kTestLineExpected[] = "abcdefgh\r\n"; |
29 | 26 |
30 const char kCatCommand[] = "cat"; | 27 const char kCatCommand[] = "cat"; |
31 const char kStdoutType[] = "stdout"; | 28 const char kStdoutType[] = "stdout"; |
32 const int kTestLineNum = 100; | 29 const int kTestLineNum = 100; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 bool valid = true; | 70 bool valid = true; |
74 for (size_t i = 0; i < output.length(); i++) { | 71 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 | 72 // The character output[i] should be next in at least one of the lines we |
76 // are testing. | 73 // are testing. |
77 valid = (ProcessReceivedCharacter(output[i], 0) || | 74 valid = (ProcessReceivedCharacter(output[i], 0) || |
78 ProcessReceivedCharacter(output[i], 1)); | 75 ProcessReceivedCharacter(output[i], 1)); |
79 EXPECT_TRUE(valid) << "Received: " << output; | 76 EXPECT_TRUE(valid) << "Received: " << output; |
80 } | 77 } |
81 | 78 |
82 if (!valid || TestSucceeded()) { | 79 if (!valid || TestSucceeded()) { |
83 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 80 MessageLoop::current()->PostTask(FROM_HERE, |
84 MessageLoop::QuitClosure()); | 81 MessageLoop::QuitClosure()); |
85 } | 82 } |
86 } | 83 } |
87 | 84 |
88 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE { | 85 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE { |
89 for (int i = 0; i < kTestLineNum; i++) { | 86 for (int i = 0; i < kTestLineNum; i++) { |
90 EXPECT_TRUE(registry->SendInput(pid_, kTestLineToSend)); | 87 EXPECT_TRUE(registry->SendInput(pid_, kTestLineToSend)); |
91 } | 88 } |
92 } | 89 } |
93 | 90 |
94 private: | 91 private: |
95 bool ProcessReceivedCharacter(char received, size_t stream) { | 92 bool ProcessReceivedCharacter(char received, size_t stream) { |
96 if (stream >= arraysize(left_to_check_index_)) | 93 if (stream >= arraysize(left_to_check_index_)) |
97 return false; | 94 return false; |
98 bool success = left_to_check_index_[stream] < expected_line_.length() && | 95 bool success = left_to_check_index_[stream] < expected_line_.length() && |
99 expected_line_[left_to_check_index_[stream]] == received; | 96 expected_line_[left_to_check_index_[stream]] == received; |
100 if (success) | 97 if (success) |
101 left_to_check_index_[stream]++; | 98 left_to_check_index_[stream]++; |
102 if (left_to_check_index_[stream] == expected_line_.length() && | 99 if (left_to_check_index_[stream] == expected_line_.length() && |
103 lines_left_ > 0) { | 100 lines_left_ > 0) { |
104 // Take another line to test for this stream, if there are any lines left. | 101 // Take another line to test for this stream, if there are any lines left. |
105 // If not, this stream is done. | 102 // If not, this stream is done. |
106 left_to_check_index_[stream] = 0; | 103 left_to_check_index_[stream] = 0; |
107 lines_left_--; | 104 lines_left_--; |
108 } | 105 } |
109 return success; | 106 return success; |
110 } | 107 } |
111 | 108 |
112 bool TestSucceeded() { | 109 bool TestSucceeded() { |
113 return left_to_check_index_[0] == expected_line_.length() && | 110 return left_to_check_index_[0] == expected_line_.length() && |
114 left_to_check_index_[1] == expected_line_.length() && | 111 left_to_check_index_[1] == expected_line_.length() && |
115 lines_left_ == 0; | 112 lines_left_ == 0; |
116 } | 113 } |
117 | 114 |
118 size_t left_to_check_index_[2]; | 115 size_t left_to_check_index_[2]; |
119 size_t lines_left_; | 116 size_t lines_left_; |
120 std::string expected_line_; | 117 std::string expected_line_; |
121 }; | 118 }; |
122 | 119 |
123 class RegistryNotifiedOnProcessExitTestRunner : public TestRunner { | 120 class RegistryNotifiedOnProcessExitTestRunner : public TestRunner { |
124 public: | 121 public: |
125 virtual ~RegistryNotifiedOnProcessExitTestRunner() {} | 122 virtual ~RegistryNotifiedOnProcessExitTestRunner() {} |
126 | 123 |
127 virtual void SetupExpectations(pid_t pid) OVERRIDE { | 124 virtual void SetupExpectations(pid_t pid) OVERRIDE { |
128 output_received_ = false; | 125 output_received_ = false; |
129 pid_ = pid; | 126 pid_ = pid; |
130 } | 127 } |
131 | 128 |
132 virtual void OnSomeRead(pid_t pid, const std::string& type, | 129 virtual void OnSomeRead(pid_t pid, const std::string& type, |
133 const std::string& output) OVERRIDE { | 130 const std::string& output) OVERRIDE { |
134 EXPECT_EQ(pid_, pid); | 131 EXPECT_EQ(pid_, pid); |
135 if (!output_received_) { | 132 if (!output_received_) { |
136 output_received_ = true; | 133 output_received_ = true; |
137 EXPECT_EQ(type, "stdout"); | 134 EXPECT_EQ(type, "stdout"); |
138 EXPECT_EQ(output, "p"); | 135 EXPECT_EQ(output, "p"); |
139 base::KillProcess(pid_, 0 , true); | 136 base::KillProcess(pid_, 0 , true); |
140 return; | 137 return; |
141 } | 138 } |
142 EXPECT_EQ("exit", type); | 139 EXPECT_EQ("exit", type); |
143 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 140 MessageLoop::current()->PostTask(FROM_HERE, |
144 MessageLoop::QuitClosure()); | 141 MessageLoop::QuitClosure()); |
145 } | 142 } |
146 | 143 |
147 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE { | 144 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE { |
148 EXPECT_TRUE(registry->SendInput(pid_, "p")); | 145 EXPECT_TRUE(registry->SendInput(pid_, "p")); |
149 } | 146 } |
150 | 147 |
151 private: | 148 private: |
152 bool output_received_; | 149 bool output_received_; |
153 }; | 150 }; |
154 | 151 |
155 class SigIntTestRunner : public TestRunner { | 152 class SigIntTestRunner : public TestRunner { |
156 public: | 153 public: |
157 virtual ~SigIntTestRunner() {} | 154 virtual ~SigIntTestRunner() {} |
158 | 155 |
159 virtual void SetupExpectations(pid_t pid) OVERRIDE { | 156 virtual void SetupExpectations(pid_t pid) OVERRIDE { |
160 pid_ = pid; | 157 pid_ = pid; |
161 } | 158 } |
162 | 159 |
163 virtual void OnSomeRead(pid_t pid, const std::string& type, | 160 virtual void OnSomeRead(pid_t pid, const std::string& type, |
164 const std::string& output) OVERRIDE { | 161 const std::string& output) OVERRIDE { |
165 EXPECT_EQ(pid_, pid); | 162 EXPECT_EQ(pid_, pid); |
166 // We may receive ^C on stdout, but we don't care about that, as long as we | 163 // We may receive ^C on stdout, but we don't care about that, as long as we |
167 // eventually received exit event. | 164 // eventually received exit event. |
168 if (type == "exit") { | 165 if (type == "exit") { |
169 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 166 MessageLoop::current()->PostTask(FROM_HERE, |
170 MessageLoop::QuitClosure()); | 167 MessageLoop::QuitClosure()); |
171 } | 168 } |
172 } | 169 } |
173 | 170 |
174 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE { | 171 virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE { |
175 // Send SingInt and verify the process exited. | 172 // Send SingInt and verify the process exited. |
176 EXPECT_TRUE(registry->SendInput(pid_, "\003")); | 173 EXPECT_TRUE(registry->SendInput(pid_, "\003")); |
177 } | 174 } |
178 }; | 175 }; |
179 | 176 |
180 } // namespace | 177 } // namespace |
181 | 178 |
182 class ProcessProxyTest : public InProcessBrowserTest { | 179 class ProcessProxyTest : public testing::Test { |
183 public: | 180 public: |
184 ProcessProxyTest() {} | 181 ProcessProxyTest() {} |
185 virtual ~ProcessProxyTest() {} | 182 virtual ~ProcessProxyTest() {} |
186 | 183 |
187 protected: | 184 protected: |
188 void InitRegistryTest() { | 185 void InitRegistryTest() { |
189 registry_ = ProcessProxyRegistry::Get(); | 186 registry_ = ProcessProxyRegistry::Get(); |
190 | 187 |
191 EXPECT_TRUE(registry_->OpenProcess(kCatCommand, &pid_, | 188 EXPECT_TRUE(registry_->OpenProcess( |
192 base::Bind(&TestRunner::OnSomeRead, | 189 kCatCommand, &pid_, |
193 base::Unretained(test_runner_.get())))); | 190 base::Bind(&TestRunner::OnSomeRead, |
| 191 base::Unretained(test_runner_.get())))); |
194 | 192 |
195 test_runner_->SetupExpectations(pid_); | 193 test_runner_->SetupExpectations(pid_); |
196 test_runner_->StartRegistryTest(registry_); | 194 test_runner_->StartRegistryTest(registry_); |
197 } | 195 } |
198 | 196 |
199 void EndRegistryTest() { | 197 void EndRegistryTest() { |
200 registry_->CloseProcess(pid_); | 198 registry_->CloseProcess(pid_); |
201 | 199 |
202 base::TerminationStatus status = base::GetTerminationStatus(pid_, NULL); | 200 base::TerminationStatus status = base::GetTerminationStatus(pid_, NULL); |
203 EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status); | 201 EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status); |
204 if (status == base::TERMINATION_STATUS_STILL_RUNNING) | 202 if (status == base::TERMINATION_STATUS_STILL_RUNNING) |
205 base::KillProcess(pid_, 0, true); | 203 base::KillProcess(pid_, 0, true); |
206 | 204 |
207 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 205 MessageLoop::current()->PostTask(FROM_HERE, |
208 MessageLoop::QuitClosure()); | 206 MessageLoop::QuitClosure()); |
209 } | 207 } |
210 | 208 |
211 void RunTest() { | 209 void RunTest() { |
212 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 210 MessageLoop::current()->PostTask( |
213 base::Bind(&ProcessProxyTest::InitRegistryTest, | 211 FROM_HERE, |
214 base::Unretained(this))); | 212 base::Bind(&ProcessProxyTest::InitRegistryTest, |
| 213 base::Unretained(this))); |
215 | 214 |
216 // Wait until all data from output watcher is received (QuitTask will be | 215 // Wait until all data from output watcher is received (QuitTask will be |
217 // fired on watcher thread). | 216 // fired on watcher thread). |
218 content::RunMessageLoop(); | 217 MessageLoop::current()->Run(); |
219 | 218 |
220 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 219 MessageLoop::current()->PostTask( |
221 base::Bind(&ProcessProxyTest::EndRegistryTest, | 220 FROM_HERE, |
222 base::Unretained(this))); | 221 base::Bind(&ProcessProxyTest::EndRegistryTest, |
| 222 base::Unretained(this))); |
223 | 223 |
224 // Wait until we clean up the process proxy. | 224 // Wait until we clean up the process proxy. |
225 content::RunMessageLoop(); | 225 MessageLoop::current()->Run(); |
226 } | 226 } |
227 | 227 |
228 scoped_ptr<TestRunner> test_runner_; | 228 scoped_ptr<TestRunner> test_runner_; |
229 | 229 |
230 private: | 230 private: |
231 ProcessProxyRegistry* registry_; | 231 ProcessProxyRegistry* registry_; |
232 pid_t pid_; | 232 pid_t pid_; |
| 233 |
| 234 MessageLoop message_loop_; |
233 }; | 235 }; |
234 | 236 |
235 // Test will open new process that will run cat command, and verify data we | 237 // Test will open new process that will run cat command, and verify data we |
236 // write to process gets echoed back. | 238 // write to process gets echoed back. |
237 IN_PROC_BROWSER_TEST_F(ProcessProxyTest, RegistryTest) { | 239 TEST_F(ProcessProxyTest, RegistryTest) { |
238 test_runner_.reset(new RegistryTestRunner()); | 240 test_runner_.reset(new RegistryTestRunner()); |
239 RunTest(); | 241 RunTest(); |
240 } | 242 } |
241 | 243 |
242 // Open new process, then kill it. Verifiy that we detect when the process dies. | 244 // Open new process, then kill it. Verifiy that we detect when the process dies. |
243 IN_PROC_BROWSER_TEST_F(ProcessProxyTest, RegistryNotifiedOnProcessExit) { | 245 TEST_F(ProcessProxyTest, RegistryNotifiedOnProcessExit) { |
244 test_runner_.reset(new RegistryNotifiedOnProcessExitTestRunner()); | 246 test_runner_.reset(new RegistryNotifiedOnProcessExitTestRunner()); |
245 RunTest(); | 247 RunTest(); |
246 } | 248 } |
247 | 249 |
248 // Test verifies that \003 message send to process is processed as SigInt. | 250 // Test verifies that \003 message send to process is processed as SigInt. |
249 // Timing out on the waterfall: http://crbug.com/115064 | 251 // Timing out on the waterfall: http://crbug.com/115064 |
250 IN_PROC_BROWSER_TEST_F(ProcessProxyTest, DISABLED_SigInt) { | 252 TEST_F(ProcessProxyTest, DISABLED_SigInt) { |
251 test_runner_.reset(new SigIntTestRunner()); | 253 test_runner_.reset(new SigIntTestRunner()); |
252 RunTest(); | 254 RunTest(); |
253 } | 255 } |
| 256 |
| 257 } // namespace chromeos |
OLD | NEW |