blob: 9703b51dad6f7b5c79c1c6b5384a62ba3f5e1a42 [file] [log] [blame]
// Copyright 2014 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/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_piece.h"
#include "device/serial/async_waiter.h"
#include "device/serial/data_sender.h"
#include "device/serial/data_sink_receiver.h"
#include "device/serial/data_stream.mojom.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
class DataSinkTest : public testing::Test {
public:
enum Event {
EVENT_NONE,
EVENT_READ_BUFFER_READY,
EVENT_CANCEL_RECEIVED,
EVENT_SEND_SUCCESS,
EVENT_SEND_ERROR,
EVENT_CANCEL_COMPLETE,
EVENT_ERROR,
};
DataSinkTest()
: bytes_sent_(0),
send_error_(0),
has_send_error_(false),
cancel_error_(0),
seen_connection_error_(false),
expected_event_(EVENT_NONE) {}
void SetUp() override {
message_loop_.reset(new base::MessageLoop);
mojo::InterfacePtr<serial::DataSink> sink_handle;
sink_receiver_ = mojo::WeakBindToProxy(
new DataSinkReceiver(
base::Bind(&DataSinkTest::OnDataToRead, base::Unretained(this)),
base::Bind(&DataSinkTest::OnCancel, base::Unretained(this)),
base::Bind(&DataSinkTest::OnError, base::Unretained(this))),
&sink_handle);
sender_.reset(new DataSender(sink_handle.Pass(), kBufferSize, kFatalError));
}
void TearDown() override {
read_buffer_.reset();
message_loop_.reset();
if (sink_receiver_.get())
EXPECT_TRUE(sink_receiver_->HasOneRef());
}
void WaitForEvent(Event event) {
expected_event_ = event;
base::RunLoop run_loop;
stop_run_loop_ = run_loop.QuitClosure();
run_loop.Run();
}
void EventReceived(Event event) {
if (event == expected_event_ && !stop_run_loop_.is_null())
stop_run_loop_.Run();
}
void OnError() {
seen_connection_error_ = true;
EventReceived(EVENT_ERROR);
}
void ExpectDataAndReadAll(const base::StringPiece& expected_data) {
ExpectData(expected_data, static_cast<uint32_t>(expected_data.size()), 0);
}
void ExpectData(const base::StringPiece& expected_data,
uint32_t bytes_to_read,
int32_t error) {
DCHECK(bytes_to_read <= static_cast<uint32_t>(expected_data.size()));
std::string data;
while (data.size() < static_cast<size_t>(expected_data.size())) {
if (!read_buffer_)
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(read_buffer_);
data.append(read_buffer_->GetData(), read_buffer_->GetSize());
if (bytes_to_read <= read_buffer_->GetSize()) {
if (error)
read_buffer_->DoneWithError(bytes_to_read, error);
else
read_buffer_->Done(bytes_to_read);
read_buffer_.reset();
break;
} else {
bytes_to_read -= read_buffer_->GetSize();
read_buffer_->Done(read_buffer_->GetSize());
read_buffer_.reset();
}
}
// If we terminate early, we may not see all of the data. In that case,
// check that the part we saw matches what we expected.
if (static_cast<uint32_t>(data.size()) <
static_cast<uint32_t>(expected_data.size()) &&
data.size() >= bytes_to_read) {
EXPECT_EQ(expected_data.substr(0, data.size()), data);
return;
}
EXPECT_EQ(expected_data, data);
}
void ExpectSendSuccess(uint32_t expected_bytes_sent) {
bytes_sent_ = 0;
WaitForEvent(EVENT_SEND_SUCCESS);
EXPECT_EQ(expected_bytes_sent, bytes_sent_);
EXPECT_FALSE(has_send_error_);
}
void ExpectSendError(uint32_t expected_bytes_sent, int32_t expected_error) {
bytes_sent_ = 0;
has_send_error_ = 0;
send_error_ = 0;
WaitForEvent(EVENT_SEND_ERROR);
EXPECT_EQ(expected_bytes_sent, bytes_sent_);
EXPECT_TRUE(has_send_error_);
EXPECT_EQ(expected_error, send_error_);
}
void ExpectCancel(int32_t expected_error) {
cancel_error_ = 0;
WaitForEvent(EVENT_CANCEL_RECEIVED);
EXPECT_EQ(expected_error, cancel_error_);
}
void ExpectCancelResult() { WaitForEvent(EVENT_CANCEL_COMPLETE); }
bool Send(const base::StringPiece& data) {
return sender_->Send(
data,
base::Bind(&DataSinkTest::OnDataSent, base::Unretained(this)),
base::Bind(&DataSinkTest::OnSendError, base::Unretained(this)));
}
void OnDataSent(uint32_t bytes_sent) {
bytes_sent_ = bytes_sent;
has_send_error_ = false;
EventReceived(EVENT_SEND_SUCCESS);
}
void OnSendError(uint32_t bytes_sent, int32_t error) {
bytes_sent_ = bytes_sent;
send_error_ = error;
has_send_error_ = true;
EventReceived(EVENT_SEND_ERROR);
}
void OnDataToRead(scoped_ptr<ReadOnlyBuffer> buffer) {
read_buffer_ = buffer.Pass();
read_buffer_contents_ =
std::string(read_buffer_->GetData(), read_buffer_->GetSize());
EventReceived(EVENT_READ_BUFFER_READY);
}
bool Cancel(int32_t error) {
return sender_->Cancel(
error, base::Bind(&DataSinkTest::CancelAck, base::Unretained(this)));
}
void CancelAck() { EventReceived(EVENT_CANCEL_COMPLETE); }
void OnCancel(int32_t error) {
cancel_error_ = error;
EventReceived(EVENT_CANCEL_RECEIVED);
}
protected:
static const int32_t kFatalError;
static const uint32_t kBufferSize;
scoped_ptr<base::MessageLoop> message_loop_;
base::Closure stop_run_loop_;
scoped_refptr<DataSinkReceiver> sink_receiver_;
scoped_ptr<DataSender> sender_;
uint32_t bytes_sent_;
int32_t send_error_;
bool has_send_error_;
int32_t cancel_error_;
scoped_ptr<ReadOnlyBuffer> read_buffer_;
std::string read_buffer_contents_;
bool seen_connection_error_;
Event expected_event_;
private:
DISALLOW_COPY_AND_ASSIGN(DataSinkTest);
};
const int32_t DataSinkTest::kFatalError = -10;
const uint32_t DataSinkTest::kBufferSize = 100;
TEST_F(DataSinkTest, Basic) {
ASSERT_TRUE(Send("a"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("a"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, LargeSend) {
std::string pattern = "1234567890";
std::string data;
for (uint32_t i = 0; i < kBufferSize; i++)
data.append(pattern);
ASSERT_TRUE(Send(data));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll(data));
ExpectSendSuccess(static_cast<uint32_t>(data.size()));
}
TEST_F(DataSinkTest, ErrorAndAllData) {
ASSERT_TRUE(Send("a"));
ASSERT_NO_FATAL_FAILURE(ExpectData("a", 1, -1));
ExpectSendError(1, -1);
}
TEST_F(DataSinkTest, ErrorAndPartialData) {
ASSERT_TRUE(Send("ab"));
ASSERT_NO_FATAL_FAILURE(ExpectData("ab", 1, -1));
ExpectSendError(1, -1);
ASSERT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, ErrorAndPartialDataAtPacketBoundary) {
ASSERT_TRUE(Send("ab"));
ASSERT_NO_FATAL_FAILURE(ExpectData("ab", 2, -1));
ExpectSendError(2, -1);
ASSERT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, ErrorInSecondPacket) {
ASSERT_TRUE(Send("a"));
ASSERT_TRUE(Send("b"));
ASSERT_NO_FATAL_FAILURE(ExpectData("ab", 2, -1));
ExpectSendSuccess(1);
ExpectSendError(1, -1);
ASSERT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, ErrorBeforeLargeSend) {
ASSERT_TRUE(Send("a"));
std::string pattern = "123456789";
std::string data;
for (int i = 0; i < 100; i++)
data.append("1234567890");
ASSERT_TRUE(Send(data));
ASSERT_NO_FATAL_FAILURE(ExpectData("a" + data, 1, -1));
ExpectSendError(1, -1);
ExpectSendError(0, -1);
}
TEST_F(DataSinkTest, ErrorOnly) {
ASSERT_TRUE(Send("a"));
ASSERT_NO_FATAL_FAILURE(ExpectData("a", 0, -1));
ExpectSendError(0, -1);
ASSERT_TRUE(Send("b"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("b"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, Cancel) {
ASSERT_TRUE(Send("a"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-2));
// Check that sends fail until the cancel operation completes.
EXPECT_FALSE(Send("b"));
ASSERT_NO_FATAL_FAILURE(ExpectCancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectData("a", 0, -1));
// Check that the error reported by the sink implementation is reported to the
// client - not the cancellation error.
ExpectSendError(0, -1);
ExpectCancelResult();
EXPECT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, CancelSinkSucceeds) {
ASSERT_TRUE(Send("a"));
EXPECT_TRUE(Send("b"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectCancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectData("ab", 1, 0));
ExpectSendError(1, -2);
ExpectCancelResult();
EXPECT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, CancelTwice) {
ASSERT_TRUE(Send("a"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectCancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectData("a", 0, -2));
ExpectSendError(0, -2);
ExpectCancelResult();
EXPECT_TRUE(Send("b"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-3));
ASSERT_NO_FATAL_FAILURE(ExpectCancel(-3));
ASSERT_NO_FATAL_FAILURE(ExpectData("b", 0, -3));
ExpectSendError(0, -3);
ExpectCancelResult();
EXPECT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, CancelTwiceWithNoSendBetween) {
ASSERT_TRUE(Send("a"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectCancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectData("a", 0, -2));
ExpectSendError(0, -2);
ExpectCancelResult();
ASSERT_TRUE(Cancel(-3));
ExpectCancelResult();
EXPECT_TRUE(Send("b"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("b"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, CancelDuringError) {
ASSERT_TRUE(Send("a"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectData("a", 0, -1));
ExpectSendError(0, -1);
ExpectCancelResult();
EXPECT_TRUE(Send("a"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("a"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, CancelWithoutSend) {
ASSERT_TRUE(Cancel(-2));
ExpectCancelResult();
EXPECT_TRUE(Send("a"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("a"));
ExpectSendSuccess(1);
EXPECT_EQ(0, cancel_error_);
}
TEST_F(DataSinkTest, CancelPartialPacket) {
ASSERT_TRUE(Send("ab"));
WaitForEvent(EVENT_READ_BUFFER_READY);
ASSERT_TRUE(Cancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectCancel(-2));
ASSERT_NO_FATAL_FAILURE(ExpectData("ab", 1, -2));
ExpectSendError(1, -2);
ExpectCancelResult();
EXPECT_TRUE(Send("c"));
ASSERT_NO_FATAL_FAILURE(ExpectDataAndReadAll("c"));
ExpectSendSuccess(1);
}
TEST_F(DataSinkTest, SinkReceiverShutdown) {
ASSERT_TRUE(Send("a"));
ASSERT_TRUE(Send(std::string(kBufferSize * 10, 'b')));
ASSERT_TRUE(Cancel(-1));
sink_receiver_->ShutDown();
sink_receiver_ = NULL;
ExpectSendError(0, kFatalError);
ExpectSendError(0, kFatalError);
ExpectCancelResult();
ASSERT_FALSE(Send("a"));
ASSERT_FALSE(Cancel(-1));
}
TEST_F(DataSinkTest, SenderShutdown) {
ASSERT_TRUE(Send("a"));
ASSERT_TRUE(Send(std::string(kBufferSize * 10, 'b')));
ASSERT_TRUE(Cancel(-1));
sender_.reset();
ExpectSendError(0, kFatalError);
ExpectSendError(0, kFatalError);
ExpectCancelResult();
if (!seen_connection_error_)
WaitForEvent(EVENT_ERROR);
EXPECT_TRUE(seen_connection_error_);
}
} // namespace device