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

Unified Diff: chrome/browser/devtools/adb_client_socket_browsertest.cc

Issue 43793002: [DevTools] Added browser tests for adb_client_socket.cc and android_device.cc (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed nits. Added offline device. Created 7 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/devtools/adb_client_socket_browsertest.cc
diff --git a/chrome/browser/devtools/adb_client_socket_browsertest.cc b/chrome/browser/devtools/adb_client_socket_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..941e7d84efb5d09fb72d1e362ca6faad5b235130
--- /dev/null
+++ b/chrome/browser/devtools/adb_client_socket_browsertest.cc
@@ -0,0 +1,319 @@
+// Copyright (c) 2013 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 "base/strings/string_number_conversions.h"
+#include "chrome/browser/devtools/android_device.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/test_utils.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/socket/stream_socket.h"
+#include "net/socket/tcp_server_socket.h"
+
+using namespace net;
+
+static const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
+static const char kDeviceModel[] = "Nexus 8";
+
+static const int kBufferSize = 16*1024;
+static const int kAdbPort = 5037;
+
+static const int kAdbMessageHeaderSize = 4;
+
+class MockAdbServer {
+public:
+ MockAdbServer() {
+ input_buffer_ = new net::GrowableIOBuffer();
+ input_buffer_->SetCapacity(kBufferSize);
+
+ output_buffer_ = new net::GrowableIOBuffer();
+ }
+
+ void Start(base::Callback<bool(void)> callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ IPAddressNumber address;
+ ParseIPLiteralToNumber("127.0.0.1", &address);
+
+ IPEndPoint endpoint(address, kAdbPort);
+
+ server_socket_.reset(new TCPServerSocket(NULL, NetLog::Source()));
+ server_socket_->Listen(endpoint, 2);
+
+ callback.Run();
+
+ AcceptConnection();
+ }
+
+ void Shutdown(base::Callback<bool(void)> callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ server_socket_.reset();
+
+ if (client_socket_) {
+ client_socket_->Disconnect();
+ client_socket_.reset();
+ }
+
+ callback.Run();
+ }
+
+private:
+ void AcceptConnection() {
+ if (client_socket_) {
+ client_socket_->Disconnect();
+ client_socket_.reset();
+ }
+
+ int accept_result = server_socket_->Accept(&client_socket_,
+ base::Bind(&MockAdbServer::OnAccepted, base::Unretained(this)));
+ if (accept_result != ERR_IO_PENDING)
+ OnAccepted(accept_result);
+ }
+
+ void OnAccepted(int result) {
+ ASSERT_EQ(result, 0);
+ ReadData();
+ }
+
+ void ReadData() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ int read_result = client_socket_->Read(
+ input_buffer_.get(),
+ input_buffer_->RemainingCapacity(),
+ base::Bind(&MockAdbServer::OnDataRead, base::Unretained(this)));
+
+ if (read_result != ERR_IO_PENDING)
+ OnDataRead(read_result);
+ }
+
+ void OnDataRead(int count) {
+ if (count <= 0) {
+ AcceptConnection();
+ return;
+ }
+
+ input_buffer_->set_offset(input_buffer_->offset() + count);
+
+ if (!TryProcessCommand()) {
+ // Posting is needed not to enter deep recursion in case too synchronous
+ // replies.
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&MockAdbServer::ReadData, base::Unretained(this)));
+ }
+ }
+
+ void WriteData() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ ASSERT_NE(output_buffer_->offset(), output_buffer_->capacity());
+ int write_result = client_socket_->Write(
+ output_buffer_,
+ output_buffer_->capacity() - output_buffer_->offset(),
+ base::Bind(&MockAdbServer::OnDataWritten,
+ base::Unretained(this)));
+ if (write_result != ERR_IO_PENDING)
+ OnDataWritten(write_result);
+ }
+
+ void OnDataWritten(int count) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ if (count < 0) {
+ AcceptConnection();
+ return;
+ }
+
+ ASSERT_TRUE(count > 0);
+ ASSERT_TRUE(output_buffer_->offset() + count <= output_buffer_->capacity());
+
+ output_buffer_->set_offset(output_buffer_->offset() + count);
+ if (output_buffer_->offset() != output_buffer_->capacity())
+ WriteData();
+ else if (!TryProcessCommand())
+ ReadData();
+ }
+
+ bool TryProcessCommand() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ char* data = input_buffer_->StartOfBuffer();
+ int data_size = input_buffer_->offset();
+
+ if (data_size >= kAdbMessageHeaderSize) {
+ std::string message_header(data, kAdbMessageHeaderSize);
+ int message_size;
+
+ EXPECT_TRUE(base::HexStringToInt(message_header, &message_size));
+
+ if (data_size >= message_size + kAdbMessageHeaderSize) {
+ std::string message_body(data + kAdbMessageHeaderSize, message_size );
+
+ memmove(data, data + message_size,
+ data_size - message_size - kAdbMessageHeaderSize);
+ input_buffer_->set_offset(
+ data_size - message_size - kAdbMessageHeaderSize);
+
+ ProcessCommand(message_body);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void ProcessCommand(const std::string& command) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ if (command == "host:devices") {
+ SendResponse("01498B321301A00A\tdevice\n01498B2B0D01300E\toffline");
+ } else if (command == "host:transport:01498B321301A00A") {
+ SendResponse("");
+ } else if (command == kDeviceModelCommand) {
+ SendResponse(kDeviceModel);
+ } else {
+ NOTREACHED() << "Unknown command - " << command;
+ }
+ }
+
+ void SendResponse(const std::string& response) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+ std::stringstream response_stream;
+ response_stream << "OKAY";
+
+ int size = response.size();
+ if (size > 0) {
+ static const char kHexChars[] = "0123456789ABCDEF";
+ for (int i = 3; i >= 0; i--)
+ response_stream << kHexChars[ (size >> 4*i) & 0x0f ];
+ response_stream << response;
+ }
+
+ std::string response_data = response_stream.str();
+
+ output_buffer_->SetCapacity(response_data.size());
+ output_buffer_->set_offset(0);
+ mempcpy(output_buffer_->StartOfBuffer(), response_data.c_str(),
+ response_data.size());
+ WriteData();
+ }
+
+private:
+ scoped_ptr<TCPServerSocket> server_socket_;
+ scoped_ptr<StreamSocket> client_socket_;
+ scoped_refptr<net::GrowableIOBuffer> input_buffer_;
+ scoped_refptr<net::GrowableIOBuffer> output_buffer_;
+};
+
+class AdbClientSocketTest : public InProcessBrowserTest {
+public:
+ void StartTest() {
+ adb_thread_ = RefCountedAdbThread::GetInstance();
+ adb_server_.reset(new MockAdbServer());
+
+ content::BrowserThread::PostTask(
Vladislav Kaznacheev 2013/10/28 14:12:37 This look terrifying. Please consider using Brows
Dmitry Zvorygin 2013/10/29 13:14:01 Done.
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &MockAdbServer::Start,
+ base::Unretained(adb_server_.get()),
+ base::Bind(
+ &content::BrowserThread::PostTask,
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &AdbClientSocketTest::QueryDevices,
+ base::Unretained(this)))));
+ }
+
+ void EndTest() {
+ adb_provider_ = NULL;
+ adb_thread_ = NULL;
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &MockAdbServer::Shutdown,
+ base::Unretained(adb_server_.get()),
+ base::Bind(
+ &content::BrowserThread::PostTask,
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &content::MessageLoopRunner::Quit,
+ runner))));
+ }
+
+private:
+ void QueryDevices() {
Vladislav Kaznacheev 2013/10/28 18:34:34 Is there a reason not to use DevToolsAdbBridge (li
Dmitry Zvorygin 2013/10/29 13:14:01 Done.
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ adb_provider_ = AndroidDeviceProvider::GetAdbDeviceProvider();
+ adb_provider_->QueryDevices(
+ base::Bind(&AdbClientSocketTest::AdbDevicesReceived,
+ base::Unretained(this)));
+ }
+
+ void AdbDevicesReceived(
+ const AndroidDeviceProvider::AndroidDevices& received_devices) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+#if defined(DEBUG_DEVTOOLS)
Vladislav Kaznacheev 2013/10/28 14:12:37 Just to make sure, did you try running this with d
Dmitry Zvorygin 2013/10/29 13:14:01 Sure, see gyp(i) file in changelist.
+ // Mock device is added
+ ASSERT_EQ(3U, received_devices.size());
+#else
+ ASSERT_EQ(2U, received_devices.size());
+#endif
+ for (AndroidDeviceProvider::AndroidDevices::const_iterator it =
+ received_devices.begin(); it != received_devices.end(); ++it) {
+ if ((*it)->serial() == "01498B321301A00A")
+ online_device_ = *it;
+ else if ((*it)->serial() == "01498B2B0D01300E")
+ offline_device_ = *it;
+ }
+
+ ASSERT_EQ(online_device_->serial(), "01498B321301A00A");
+ ASSERT_TRUE(online_device_->is_connected());
+ ASSERT_FALSE(offline_device_->is_connected());
+
+ adb_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&AndroidDevice::RunCommand,
+ online_device_,
+ kDeviceModelCommand,
+ base::Bind(&AdbClientSocketTest::AdbDeviceModelReceived,
+ base::Unretained(this))));
+ }
+
+ void AdbDeviceModelReceived(int result_code, const std::string& model) {
+ DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
+ ASSERT_EQ(result_code, 0);
+ ASSERT_EQ(model, kDeviceModel);
+ EndTest();
+ }
+
+public:
+ scoped_refptr<content::MessageLoopRunner> runner;
+
+private:
+ scoped_ptr<MockAdbServer> adb_server_;
+
+ scoped_refptr<RefCountedAdbThread> adb_thread_;
Vladislav Kaznacheev 2013/10/28 14:12:37 I suspect that only adb_thread_ really needs to be
Dmitry Zvorygin 2013/10/29 13:14:01 Done.
+ scoped_refptr<AndroidDeviceProvider> adb_provider_;
+ scoped_refptr<AndroidDevice> online_device_;
+ scoped_refptr<AndroidDevice> offline_device_;
+};
+
+IN_PROC_BROWSER_TEST_F(AdbClientSocketTest, TestAdbClientSocket) {
+ runner = new content::MessageLoopRunner;
+
+ StartTest();
+
+ runner->Run();
+}
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698