blob: a0637f98f4a6b93b0d324d29017d9765c9a13358 [file] [log] [blame]
// Copyright (c) 2016 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 "chrome/test/chromedriver/net/adb_client_socket.h"
#include <memory>
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/gtest_util.h"
#include "base/test/mock_callback.h"
#include "net/socket/socket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
class MockSocket : public net::MockClientSocket {
public:
int return_values_length;
std::string* return_values_array;
MockSocket(std::string* return_values_array, int return_values_length)
: MockClientSocket(net::NetLogWithSource()),
return_values_length(return_values_length),
return_values_array(return_values_array) {}
MockSocket() : MockClientSocket(net::NetLogWithSource()) {}
int Read(net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback) override {
int result = ReadHelper(buf, buf_len);
if (result == net::ERR_IO_PENDING) {
// Note this really should be posted as a task, but that is a pain to
// figure out.
std::move(callback).Run(ReadLoop(buf, buf_len));
}
return result;
}
int ReadLoop(net::IOBuffer* buf, int buf_len) {
int result;
do {
result = ReadHelper(buf, buf_len);
} while (result == net::ERR_IO_PENDING);
return result;
}
int ReadHelper(net::IOBuffer* buf, int buf_len) {
if (return_values_length) {
int chunk_length = return_values_array[0].length();
if (chunk_length > buf_len) {
strncpy(buf->data(), return_values_array[0].data(), buf_len);
return_values_array[0] = return_values_array[0].substr(buf_len);
return buf_len;
}
strncpy(buf->data(), return_values_array[0].data(), chunk_length);
return_values_length--;
return_values_array++;
if (chunk_length == 0) {
return net::ERR_IO_PENDING;
}
return chunk_length;
}
return 0;
}
int Write(
net::IOBuffer* buf,
int buf_len,
const net::CompletionOnceCallback callback,
const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
return 0;
}
// The following functions are not expected to be used.
int Connect(const net::CompletionOnceCallback callback) override {
return net::ERR_UNEXPECTED;
}
bool GetSSLInfo(net::SSLInfo* ssl_info) override { return false; }
bool WasEverUsed() const override { return false; }
};
class AdbClientSocketTest : public testing::Test {
public:
void TestParsing(const char* adb_output,
bool has_length,
int expected_result_code,
const char* expected_response) {
base::MockCallback<AdbClientSocket::CommandCallback> callback;
EXPECT_CALL(callback, Run(expected_result_code, expected_response));
AdbClientSocket::ParseOutput(has_length, callback.Get(),
std::string(adb_output));
}
void TestReadUntilEOF_EOF(const char* data_on_buffer) {
std::unique_ptr<MockSocket> socket = std::make_unique<MockSocket>();
AdbClientSocket adb_socket(3);
base::MockCallback<AdbClientSocket::ParserCallback> parse_callback;
EXPECT_CALL(parse_callback, Run(data_on_buffer));
base::MockCallback<AdbClientSocket::CommandCallback> response_callback;
// The following means "expect not to be called."
EXPECT_CALL(response_callback, Run(0, "")).Times(0);
scoped_refptr<net::GrowableIOBuffer> buffer =
base::MakeRefCounted<net::GrowableIOBuffer>();
buffer->SetCapacity(100);
strcpy(buffer->data(), data_on_buffer);
buffer->set_offset(strlen(data_on_buffer));
adb_socket.ReadUntilEOF(parse_callback.Get(), response_callback.Get(),
buffer, 0);
}
void TestReadUntilEOF_Error() {
int error_code = -1;
std::unique_ptr<MockSocket> socket = std::make_unique<MockSocket>();
// 3 is an arbitrary meaningless number in the following call.
AdbClientSocket adb_socket(3);
base::MockCallback<AdbClientSocket::ParserCallback> parse_callback;
// The following means "expect not to be called."
EXPECT_CALL(parse_callback, Run("")).Times(0);
base::MockCallback<AdbClientSocket::CommandCallback> response_callback;
EXPECT_CALL(response_callback, Run(error_code, "IO error")).Times(1);
scoped_refptr<net::GrowableIOBuffer> buffer =
base::MakeRefCounted<net::GrowableIOBuffer>();
buffer->SetCapacity(100);
adb_socket.ReadUntilEOF(parse_callback.Get(), response_callback.Get(),
buffer, error_code);
}
void TestReadUntilEOF_Recurse(std::string* chunks,
int number_chunks,
std::string expected_result) {
// 3 is an arbitrary meaningless number in the following call.
AdbClientSocket adb_socket(3);
adb_socket.socket_ = std::make_unique<MockSocket>(chunks, number_chunks);
base::MockCallback<AdbClientSocket::ParserCallback> parse_callback;
EXPECT_CALL(parse_callback, Run(expected_result.c_str())).Times(1);
base::MockCallback<AdbClientSocket::CommandCallback> response_callback;
// The following means "expect not to be called."
EXPECT_CALL(response_callback, Run(0, "")).Times(0);
scoped_refptr<net::GrowableIOBuffer> buffer =
base::MakeRefCounted<net::GrowableIOBuffer>();
int initial_capacity = 4;
buffer->SetCapacity(initial_capacity);
int result = adb_socket.socket_->Read(
buffer.get(), initial_capacity,
base::BindOnce(&AdbClientSocket::ReadUntilEOF,
base::Unretained(&adb_socket), parse_callback.Get(),
response_callback.Get(), buffer));
if (result != net::ERR_IO_PENDING) {
adb_socket.ReadUntilEOF(parse_callback.Get(), response_callback.Get(),
buffer, result);
}
}
void TestReadStatus(const char* buffer_data,
int result,
const char* expected_result_string,
int expected_result_code) {
base::MockCallback<AdbClientSocket::ParserCallback> parse_callback;
// The following means "expect not to be called."
EXPECT_CALL(parse_callback, Run("")).Times(0);
base::MockCallback<AdbClientSocket::CommandCallback> response_callback;
EXPECT_CALL(response_callback,
Run(expected_result_code, expected_result_string))
.Times(1);
scoped_refptr<net::GrowableIOBuffer> buffer =
base::MakeRefCounted<net::GrowableIOBuffer>();
int initial_capacity = 100;
buffer->SetCapacity(initial_capacity);
if (result > 0) {
strncpy(buffer->data(), buffer_data, result);
}
AdbClientSocket::ReadStatusOutput(response_callback.Get(), buffer, result);
}
};
TEST_F(AdbClientSocketTest, ParseOutput) {
TestParsing("OKAY000512345", true, 0, "12345");
TestParsing("FAIL000512345", true, 1, "12345");
TestParsing("OKAY12345", false, 0, "12345");
TestParsing("FAIL12345", false, 1, "12345");
TestParsing("ABC", false, 1, "ABC");
TestParsing("ABC", true, 1, "ABC");
TestParsing("OKAYAB", false, 0, "AB");
TestParsing("OKAYAB", true, 1, "AB");
TestParsing("OKAYOKAYOKAY", false, 0, "OKAY");
TestParsing("", false, 1, "");
TestParsing("", true, 1, "");
TestParsing("OKAYOKAY", true, 0, "");
TestParsing("OKAYOKAY", false, 0, "");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_EOFEmptyString) {
TestReadUntilEOF_EOF("");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_EOFNonEmptyString1) {
TestReadUntilEOF_EOF("blah");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_EOFNonEmptyString2) {
TestReadUntilEOF_EOF("blahbla");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_Error) {
TestReadUntilEOF_Error();
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_GrowBuffer) {
std::string chunks[7] = {"This", "", " data", " should",
"", " be ", "read in."};
TestReadUntilEOF_Recurse(chunks, 7, "This data should be read in.");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_EmptyChunks) {
std::string chunks[5] = {"", "", "", "", ""};
TestReadUntilEOF_Recurse(chunks, 5, "");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_Empty) {
std::string chunks[0] = {};
TestReadUntilEOF_Recurse(chunks, 0, "");
}
TEST_F(AdbClientSocketTest, ReadUntilEOF_EmptyEndingChunk) {
std::string chunks[2] = {"yeah", ""};
TestReadUntilEOF_Recurse(chunks, 2, "yeah");
}
TEST_F(AdbClientSocketTest, ReadStatusOutput_Okay) {
TestReadStatus("OKAY", 4, "OKAY", 0);
}
TEST_F(AdbClientSocketTest, ReadStatusOutput_OkayNulls) {
TestReadStatus("OKAY\0\0\0\0", 8, "OKAY", 0);
}
TEST_F(AdbClientSocketTest, ReadStatusOutput_Fail) {
TestReadStatus("FAIL", 4, "FAIL", 1);
}
TEST_F(AdbClientSocketTest, ReadStatusOutput_FailEmpty) {
TestReadStatus("", 0, "FAIL", 1);
}