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

Unified Diff: content/shell/browser/layout_test/layout_test_android.cc

Issue 2540603004: [Android] Redirect std{in,out,err} to sockets for layout tests. (Closed)
Patch Set: Fix server_process_constructor name. Created 4 years 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 side-by-side diff with in-line comments
Download patch
Index: content/shell/browser/layout_test/layout_test_android.cc
diff --git a/content/shell/browser/layout_test/layout_test_android.cc b/content/shell/browser/layout_test/layout_test_android.cc
index 45bc77f5eab784a93162c617a5a896b9cc0dad22..a601811f7b7c93142971b37b8ee29adee6fefa96 100644
--- a/content/shell/browser/layout_test/layout_test_android.cc
+++ b/content/shell/browser/layout_test/layout_test_android.cc
@@ -4,6 +4,8 @@
#include "content/shell/browser/layout_test/layout_test_android.h"
+#include <fcntl.h>
+#include <iostream>
#include <memory>
#include "base/android/context_utils.h"
@@ -13,28 +15,26 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/test_support_android.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/test/nested_message_pump_android.h"
+#include "content/shell/browser/layout_test/blink_test_controller.h"
+#include "content/shell/common/layout_test/layout_test_switches.h"
#include "content/shell/common/shell_switches.h"
#include "jni/ShellLayoutTestUtils_jni.h"
+#include "net/base/ip_address.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/sockaddr_storage.h"
+#include "net/socket/socket_posix.h"
#include "url/gurl.h"
using base::android::ScopedJavaLocalRef;
namespace {
-base::FilePath GetTestFilesDirectory(JNIEnv* env) {
- ScopedJavaLocalRef<jstring> directory =
- content::Java_ShellLayoutTestUtils_getApplicationFilesDirectory(
- env, base::android::GetApplicationContext());
- return base::FilePath(ConvertJavaStringToUTF8(directory));
-}
-
-void EnsureCreateFIFO(const base::FilePath& path) {
- unlink(path.value().c_str());
- CHECK(base::android::CreateFIFO(path, 0666))
- << "Unable to create the Android's FIFO: " << path.value().c_str();
-}
-
std::unique_ptr<base::MessagePump> CreateMessagePumpForUI() {
return std::unique_ptr<base::MessagePump>(
new content::NestedMessagePumpAndroid());
@@ -44,34 +44,138 @@ std::unique_ptr<base::MessagePump> CreateMessagePumpForUI() {
namespace content {
-void EnsureInitializeForAndroidLayoutTests() {
- JNIEnv* env = base::android::AttachCurrentThread();
+ScopedAndroidConfiguration::ScopedAndroidConfiguration() : sockets_() {}
- bool success = base::MessageLoop::InitMessagePumpForUIFactory(
- &CreateMessagePumpForUI);
- CHECK(success) << "Unable to initialize the message pump for Android.";
+void ConnectCompleted(base::Closure socket_connected, int rv) {
+ CHECK_EQ(net::OK, rv) << " Failed to redirect to socket: "
+ << net::ErrorToString(rv);
+ socket_connected.Run();
+}
- // Android will need three FIFOs to communicate with the Blink test runner,
- // one for each of [stdout, stderr, stdin].
- base::FilePath files_dir(GetTestFilesDirectory(env));
+void CreateAndConnectSocket(
+ uint16_t port,
+ base::Callback<void(std::unique_ptr<net::SocketPosix>)> socket_open,
+ base::Callback<void(int)> socket_connected) {
+ net::SockaddrStorage storage;
+ net::IPAddress address;
+ CHECK(address.AssignFromIPLiteral("127.0.0.1"))
+ << "Failed to create IPAddress from IP literal 127.0.0.1.";
+ net::IPEndPoint endpoint(address, port);
+ CHECK(endpoint.ToSockAddr(storage.addr, &storage.addr_len))
+ << "Failed to convert " << endpoint.ToString() << " to sockaddr.";
+
+ std::unique_ptr<net::SocketPosix> socket(new net::SocketPosix);
+
+ int result = net::OK;
+ result = socket->Open(AF_INET);
+ CHECK_EQ(net::OK, result) << "Failed to open socket for "
+ << endpoint.ToString() << ": "
+ << net::ErrorToString(result);
+
+ // Set the socket as blocking.
+ const int flags = fcntl(socket->socket_fd(), F_GETFL);
+ if (flags & O_NONBLOCK) {
+ fcntl(socket->socket_fd(), F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ net::CompletionCallback connect_completed = base::Bind(
+ &ConnectCompleted, base::Bind(socket_connected, socket->socket_fd()));
+ result = socket->Connect(storage, connect_completed);
+ if (result != net::ERR_IO_PENDING) {
+ connect_completed.Run(result);
+ }
+ socket_open.Run(std::move(socket));
+}
- base::FilePath stdout_fifo(files_dir.Append(FILE_PATH_LITERAL("test.fifo")));
- EnsureCreateFIFO(stdout_fifo);
+void RedirectStdout(int fd) {
+ CHECK_NE(dup2(fd, STDOUT_FILENO), -1) << "Failed to dup2 stdout: "
+ << strerror(errno);
+}
- base::FilePath stderr_fifo(
- files_dir.Append(FILE_PATH_LITERAL("stderr.fifo")));
- EnsureCreateFIFO(stderr_fifo);
+void RedirectStdin(int fd) {
+ CHECK_NE(dup2(fd, STDIN_FILENO), -1) << "Failed to dup2 stdin: "
+ << strerror(errno);
+}
- base::FilePath stdin_fifo(files_dir.Append(FILE_PATH_LITERAL("stdin.fifo")));
- EnsureCreateFIFO(stdin_fifo);
+void RedirectStderr(int fd) {
+ CHECK_NE(dup2(fd, STDERR_FILENO), -1) << "Failed to dup2 stderr: "
+ << strerror(errno);
+}
- // Redirecting stdout needs to happen before redirecting stdin, which needs
- // to happen before redirecting stderr.
- success = base::android::RedirectStream(stdout, stdout_fifo, "w") &&
- base::android::RedirectStream(stdin, stdin_fifo, "r") &&
- base::android::RedirectStream(stderr, stderr_fifo, "w");
+void FinishRedirection(base::Callback<void(int)> redirect,
+ base::WaitableEvent* event,
+ int fd) {
+ redirect.Run(fd);
+ event->Signal();
+}
+
+void RedirectStream(
+ uint16_t port,
+ base::Callback<void(std::unique_ptr<net::SocketPosix>)> socket_open,
+ base::Callback<void(base::WaitableEvent*, int)> finish_redirection) {
+ base::WaitableEvent redirected(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CreateAndConnectSocket, port, socket_open,
+ base::Bind(finish_redirection, &redirected)));
+ content::ScopedAllowWaitForAndroidLayoutTests allow_wait;
+ while (!redirected.IsSignaled())
+ redirected.Wait();
+}
+
+void ScopedAndroidConfiguration::RedirectStreams() {
+ base::Callback<void(std::unique_ptr<net::SocketPosix>)> add_socket =
+ base::Bind(&ScopedAndroidConfiguration::AddSocket,
+ base::Unretained(this));
+
+ std::string stdout_port_str =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
+ switches::kAndroidStdoutPort);
+ unsigned stdout_port = 0;
+ if (base::StringToUint(stdout_port_str, &stdout_port)) {
+ RedirectStream(base::checked_cast<uint16_t>(stdout_port), add_socket,
+ base::Bind(&FinishRedirection, base::Bind(&RedirectStdout)));
+ }
+
+ std::string stdin_port_str =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
+ switches::kAndroidStdinPort);
+ unsigned stdin_port = 0;
+ if (base::StringToUint(stdin_port_str, &stdin_port)) {
+ RedirectStream(base::checked_cast<uint16_t>(stdin_port), add_socket,
+ base::Bind(&FinishRedirection, base::Bind(&RedirectStdin)));
+ }
+
+ std::string stderr_port_str =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
+ switches::kAndroidStderrPort);
+ unsigned stderr_port = 0;
+ if (base::StringToUint(stderr_port_str, &stderr_port)) {
+ RedirectStream(base::checked_cast<uint16_t>(stderr_port), add_socket,
+ base::Bind(&FinishRedirection, base::Bind(&RedirectStderr)));
+ }
+}
- CHECK(success) << "Unable to initialize the Android FIFOs.";
+void ScopedAndroidConfiguration::AddSocket(
+ std::unique_ptr<net::SocketPosix> socket) {
+ sockets_.push_back(std::move(socket));
+}
+
+ScopedAndroidConfiguration::~ScopedAndroidConfiguration() {}
+
+void ScopedAndroidConfiguration::Initialize() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jtest_data_dir =
+ content::Java_ShellLayoutTestUtils_getIsolatedTestRoot(env);
+ base::FilePath test_data_dir(
+ base::android::ConvertJavaStringToUTF8(env, jtest_data_dir));
+ base::InitAndroidTestPaths(test_data_dir);
+
+ bool success =
+ base::MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUI);
+ CHECK(success) << "Unable to initialize the message pump for Android.";
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698