summaryrefslogtreecommitdiffstats
path: root/chromeos/process_proxy/process_proxy_unittest.cc
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-12 20:22:48 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-12 20:22:48 +0000
commit3a01162bc4f385c6353a603662721eb95530b526 (patch)
tree8a46fdd70745d81c24288705f2e1539b64047a5a /chromeos/process_proxy/process_proxy_unittest.cc
parentb0cc590aacd6c9908d154970eabe41cb370c2cbe (diff)
downloadchromium_src-3a01162bc4f385c6353a603662721eb95530b526.zip
chromium_src-3a01162bc4f385c6353a603662721eb95530b526.tar.gz
chromium_src-3a01162bc4f385c6353a603662721eb95530b526.tar.bz2
Move chrome/browser/chromeos/process_proxy to chromeos
BUG=180711 Review URL: https://codereview.chromium.org/12433023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187641 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/process_proxy/process_proxy_unittest.cc')
-rw-r--r--chromeos/process_proxy/process_proxy_unittest.cc257
1 files changed, 257 insertions, 0 deletions
diff --git a/chromeos/process_proxy/process_proxy_unittest.cc b/chromeos/process_proxy/process_proxy_unittest.cc
new file mode 100644
index 0000000..ad0ba4b
--- /dev/null
+++ b/chromeos/process_proxy/process_proxy_unittest.cc
@@ -0,0 +1,257 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <sys/wait.h>
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/process_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "chromeos/process_proxy/process_proxy_registry.h"
+
+namespace chromeos {
+
+namespace {
+
+// The test line must have all distinct characters.
+const char kTestLineToSend[] = "abcdefgh\n";
+const char kTestLineExpected[] = "abcdefgh\r\n";
+
+const char kCatCommand[] = "cat";
+const char kStdoutType[] = "stdout";
+const int kTestLineNum = 100;
+
+class TestRunner {
+ public:
+ virtual ~TestRunner() {}
+ virtual void SetupExpectations(pid_t pid) = 0;
+ virtual void OnSomeRead(pid_t pid, const std::string& type,
+ const std::string& output) = 0;
+ virtual void StartRegistryTest(ProcessProxyRegistry* registry) = 0;
+
+ protected:
+ pid_t pid_;
+};
+
+class RegistryTestRunner : public TestRunner {
+ public:
+ virtual ~RegistryTestRunner() {}
+
+ virtual void SetupExpectations(pid_t pid) OVERRIDE {
+ pid_ = pid;
+ left_to_check_index_[0] = 0;
+ left_to_check_index_[1] = 0;
+ // We consider that a line processing has started if a value in
+ // left_to_check__[index] is set to 0, thus -2.
+ lines_left_ = 2 * kTestLineNum - 2;
+ expected_line_ = kTestLineExpected;
+ }
+
+ // Method to test validity of received input. We will receive two streams of
+ // the same data. (input will be echoed twice by the testing process). Each
+ // stream will contain the same string repeated |kTestLineNum| times. So we
+ // have to match 2 * |kTestLineNum| lines. The problem is the received lines
+ // from different streams may be interleaved (e.g. we may receive
+ // abc|abcdef|defgh|gh). To deal with that, we allow to test received text
+ // against two lines. The lines MUST NOT have two same characters for this
+ // algorithm to work.
+ virtual void OnSomeRead(pid_t pid, const std::string& type,
+ const std::string& output) OVERRIDE {
+ EXPECT_EQ(type, kStdoutType);
+ EXPECT_EQ(pid_, pid);
+
+ bool valid = true;
+ for (size_t i = 0; i < output.length(); i++) {
+ // The character output[i] should be next in at least one of the lines we
+ // are testing.
+ valid = (ProcessReceivedCharacter(output[i], 0) ||
+ ProcessReceivedCharacter(output[i], 1));
+ EXPECT_TRUE(valid) << "Received: " << output;
+ }
+
+ if (!valid || TestSucceeded()) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ MessageLoop::QuitClosure());
+ }
+ }
+
+ virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE {
+ for (int i = 0; i < kTestLineNum; i++) {
+ EXPECT_TRUE(registry->SendInput(pid_, kTestLineToSend));
+ }
+ }
+
+ private:
+ bool ProcessReceivedCharacter(char received, size_t stream) {
+ if (stream >= arraysize(left_to_check_index_))
+ return false;
+ bool success = left_to_check_index_[stream] < expected_line_.length() &&
+ expected_line_[left_to_check_index_[stream]] == received;
+ if (success)
+ left_to_check_index_[stream]++;
+ if (left_to_check_index_[stream] == expected_line_.length() &&
+ lines_left_ > 0) {
+ // Take another line to test for this stream, if there are any lines left.
+ // If not, this stream is done.
+ left_to_check_index_[stream] = 0;
+ lines_left_--;
+ }
+ return success;
+ }
+
+ bool TestSucceeded() {
+ return left_to_check_index_[0] == expected_line_.length() &&
+ left_to_check_index_[1] == expected_line_.length() &&
+ lines_left_ == 0;
+ }
+
+ size_t left_to_check_index_[2];
+ size_t lines_left_;
+ std::string expected_line_;
+};
+
+class RegistryNotifiedOnProcessExitTestRunner : public TestRunner {
+ public:
+ virtual ~RegistryNotifiedOnProcessExitTestRunner() {}
+
+ virtual void SetupExpectations(pid_t pid) OVERRIDE {
+ output_received_ = false;
+ pid_ = pid;
+ }
+
+ virtual void OnSomeRead(pid_t pid, const std::string& type,
+ const std::string& output) OVERRIDE {
+ EXPECT_EQ(pid_, pid);
+ if (!output_received_) {
+ output_received_ = true;
+ EXPECT_EQ(type, "stdout");
+ EXPECT_EQ(output, "p");
+ base::KillProcess(pid_, 0 , true);
+ return;
+ }
+ EXPECT_EQ("exit", type);
+ MessageLoop::current()->PostTask(FROM_HERE,
+ MessageLoop::QuitClosure());
+ }
+
+ virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE {
+ EXPECT_TRUE(registry->SendInput(pid_, "p"));
+ }
+
+ private:
+ bool output_received_;
+};
+
+class SigIntTestRunner : public TestRunner {
+ public:
+ virtual ~SigIntTestRunner() {}
+
+ virtual void SetupExpectations(pid_t pid) OVERRIDE {
+ pid_ = pid;
+ }
+
+ virtual void OnSomeRead(pid_t pid, const std::string& type,
+ const std::string& output) OVERRIDE {
+ EXPECT_EQ(pid_, pid);
+ // We may receive ^C on stdout, but we don't care about that, as long as we
+ // eventually received exit event.
+ if (type == "exit") {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ MessageLoop::QuitClosure());
+ }
+ }
+
+ virtual void StartRegistryTest(ProcessProxyRegistry* registry) OVERRIDE {
+ // Send SingInt and verify the process exited.
+ EXPECT_TRUE(registry->SendInput(pid_, "\003"));
+ }
+};
+
+} // namespace
+
+class ProcessProxyTest : public testing::Test {
+ public:
+ ProcessProxyTest() {}
+ virtual ~ProcessProxyTest() {}
+
+ protected:
+ void InitRegistryTest() {
+ registry_ = ProcessProxyRegistry::Get();
+
+ EXPECT_TRUE(registry_->OpenProcess(
+ kCatCommand, &pid_,
+ base::Bind(&TestRunner::OnSomeRead,
+ base::Unretained(test_runner_.get()))));
+
+ test_runner_->SetupExpectations(pid_);
+ test_runner_->StartRegistryTest(registry_);
+ }
+
+ void EndRegistryTest() {
+ registry_->CloseProcess(pid_);
+
+ base::TerminationStatus status = base::GetTerminationStatus(pid_, NULL);
+ EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status);
+ if (status == base::TERMINATION_STATUS_STILL_RUNNING)
+ base::KillProcess(pid_, 0, true);
+
+ MessageLoop::current()->PostTask(FROM_HERE,
+ MessageLoop::QuitClosure());
+ }
+
+ void RunTest() {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ProcessProxyTest::InitRegistryTest,
+ base::Unretained(this)));
+
+ // Wait until all data from output watcher is received (QuitTask will be
+ // fired on watcher thread).
+ MessageLoop::current()->Run();
+
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ProcessProxyTest::EndRegistryTest,
+ base::Unretained(this)));
+
+ // Wait until we clean up the process proxy.
+ MessageLoop::current()->Run();
+ }
+
+ scoped_ptr<TestRunner> test_runner_;
+
+ private:
+ ProcessProxyRegistry* registry_;
+ pid_t pid_;
+
+ MessageLoop message_loop_;
+};
+
+// Test will open new process that will run cat command, and verify data we
+// write to process gets echoed back.
+TEST_F(ProcessProxyTest, RegistryTest) {
+ test_runner_.reset(new RegistryTestRunner());
+ RunTest();
+}
+
+// Open new process, then kill it. Verifiy that we detect when the process dies.
+TEST_F(ProcessProxyTest, RegistryNotifiedOnProcessExit) {
+ test_runner_.reset(new RegistryNotifiedOnProcessExitTestRunner());
+ RunTest();
+}
+
+// Test verifies that \003 message send to process is processed as SigInt.
+// Timing out on the waterfall: http://crbug.com/115064
+TEST_F(ProcessProxyTest, DISABLED_SigInt) {
+ test_runner_.reset(new SigIntTestRunner());
+ RunTest();
+}
+
+} // namespace chromeos