| 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 |