Chromium Code Reviews| Index: device/serial/serial_connection_unittest.cc |
| diff --git a/device/serial/serial_connection_unittest.cc b/device/serial/serial_connection_unittest.cc |
| index b70607196fb2cba7288c0fe6e59881d5e3229670..9fb3ee426ad7f919826700a9d69d3c121442fd3f 100644 |
| --- a/device/serial/serial_connection_unittest.cc |
| +++ b/device/serial/serial_connection_unittest.cc |
| @@ -2,10 +2,17 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include <string> |
| + |
| #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/data_receiver.h" |
| +#include "device/serial/data_sender.h" |
| +#include "device/serial/data_stream.mojom.h" |
| #include "device/serial/serial.mojom.h" |
| +#include "device/serial/serial_connection.h" |
| #include "device/serial/serial_service_impl.h" |
| #include "device/serial/test_serial_io_handler.h" |
| #include "mojo/public/cpp/bindings/error_handler.h" |
| @@ -29,7 +36,31 @@ class FakeSerialDeviceEnumerator : public SerialDeviceEnumerator { |
| class SerialConnectionTest : public testing::Test, public mojo::ErrorHandler { |
| public: |
| - SerialConnectionTest() : connected_(false), success_(false) {} |
| + enum Event { |
| + EVENT_NONE, |
| + EVENT_GOT_INFO, |
| + EVENT_SET_OPTIONS, |
| + EVENT_GOT_CONTROL_SIGNALS, |
| + EVENT_SET_CONTROL_SIGNALS, |
| + EVENT_FLUSHED, |
| + EVENT_DATA_AT_IO_HANDLER, |
| + EVENT_DATA_SENT, |
| + EVENT_SEND_ERROR, |
| + EVENT_DATA_RECEIVED, |
| + EVENT_RECEIVE_ERROR, |
| + EVENT_CANCEL_COMPLETE, |
| + EVENT_ERROR, |
| + }; |
| + |
| + static const uint32_t kBufferSize; |
| + |
| + SerialConnectionTest() |
| + : connected_(false), |
| + success_(false), |
| + bytes_sent_(0), |
| + send_error_(serial::SEND_ERROR_NONE), |
| + receive_error_(serial::RECEIVE_ERROR_NONE), |
| + expected_event_(EVENT_NONE) {} |
| virtual void SetUp() OVERRIDE { |
| message_loop_.reset(new base::MessageLoop); |
| @@ -43,39 +74,69 @@ class SerialConnectionTest : public testing::Test, public mojo::ErrorHandler { |
| scoped_ptr<SerialDeviceEnumerator>(new FakeSerialDeviceEnumerator)), |
| &service); |
| service.set_error_handler(this); |
| - service->Connect( |
| - "device", serial::ConnectionOptions::New(), mojo::Get(&connection_)); |
| + mojo::InterfacePtr<serial::DataSink> consumer; |
| + mojo::InterfacePtr<serial::DataSource> producer; |
| + service->Connect("device", |
| + serial::ConnectionOptions::New(), |
| + mojo::Get(&connection_), |
| + mojo::Get(&consumer), |
| + mojo::Get(&producer)); |
| + sender_.reset(new DataSender( |
| + consumer.Pass(), kBufferSize, serial::SEND_ERROR_DISCONNECTED)); |
| + receiver_ = new DataReceiver( |
| + producer.Pass(), kBufferSize, serial::RECEIVE_ERROR_DISCONNECTED); |
| connection_.set_error_handler(this); |
| connection_->GetInfo( |
| base::Bind(&SerialConnectionTest::StoreInfo, base::Unretained(this))); |
| - RunMessageLoop(); |
| + WaitForEvent(EVENT_GOT_INFO); |
| ASSERT_TRUE(io_handler_); |
| } |
| void StoreInfo(serial::ConnectionInfoPtr options) { |
| info_ = options.Pass(); |
| - StopMessageLoop(); |
| + EventReceived(EVENT_GOT_INFO); |
| } |
| void StoreControlSignals(serial::DeviceControlSignalsPtr signals) { |
| signals_ = signals.Pass(); |
| - StopMessageLoop(); |
| + EventReceived(EVENT_GOT_CONTROL_SIGNALS); |
| } |
| - void StoreSuccess(bool success) { |
| + void StoreSuccess(Event event_to_report, bool success) { |
| success_ = success; |
| - StopMessageLoop(); |
| + EventReceived(event_to_report); |
| + } |
| + |
| + void Send(const base::StringPiece& data) { |
| + ASSERT_TRUE(sender_->Send( |
| + data, |
| + base::Bind(&SerialConnectionTest::OnDataSent, base::Unretained(this)), |
| + base::Bind(&SerialConnectionTest::OnSendError, |
| + base::Unretained(this)))); |
| + } |
| + |
| + void Receive() { |
| + ASSERT_TRUE( |
| + receiver_->Receive(base::Bind(&SerialConnectionTest::OnDataReceived, |
| + base::Unretained(this)), |
| + base::Bind(&SerialConnectionTest::OnReceiveError, |
| + base::Unretained(this)))); |
| } |
| - void RunMessageLoop() { |
| - run_loop_.reset(new base::RunLoop); |
| - run_loop_->Run(); |
| + void WaitForEvent(Event event) { |
| + expected_event_ = event; |
| + base::RunLoop run_loop; |
| + stop_run_loop_ = run_loop.QuitClosure(); |
| + run_loop.Run(); |
| } |
| - void StopMessageLoop() { |
| + void EventReceived(Event event) { |
| + if (event != expected_event_) |
| + return; |
| + expected_event_ = EVENT_NONE; |
| ASSERT_TRUE(message_loop_); |
| - ASSERT_TRUE(run_loop_); |
| - message_loop_->PostTask(FROM_HERE, run_loop_->QuitClosure()); |
| + ASSERT_TRUE(!stop_run_loop_.is_null()); |
| + message_loop_->PostTask(FROM_HERE, stop_run_loop_); |
| } |
| scoped_refptr<SerialIoHandler> CreateIoHandler() { |
| @@ -83,8 +144,32 @@ class SerialConnectionTest : public testing::Test, public mojo::ErrorHandler { |
| return io_handler_; |
| } |
| + void OnDataSent(uint32_t bytes_sent) { |
| + bytes_sent_ += bytes_sent; |
| + send_error_ = serial::SEND_ERROR_NONE; |
| + EventReceived(EVENT_DATA_SENT); |
| + } |
| + |
| + void OnSendError(uint32_t bytes_sent, int32_t error) { |
| + bytes_sent_ += bytes_sent; |
| + send_error_ = static_cast<serial::SendError>(error); |
| + EventReceived(EVENT_SEND_ERROR); |
| + } |
| + |
| + void OnDataReceived(scoped_ptr<ReadOnlyBuffer> buffer) { |
| + data_received_ += std::string(buffer->GetData(), buffer->GetSize()); |
| + buffer->Done(buffer->GetSize()); |
| + receive_error_ = serial::RECEIVE_ERROR_NONE; |
| + EventReceived(EVENT_DATA_RECEIVED); |
| + } |
| + |
| + void OnReceiveError(int32_t error) { |
| + receive_error_ = static_cast<serial::ReceiveError>(error); |
| + EventReceived(EVENT_RECEIVE_ERROR); |
| + } |
| + |
| virtual void OnConnectionError() OVERRIDE { |
| - StopMessageLoop(); |
| + EventReceived(EVENT_ERROR); |
| FAIL() << "Connection error"; |
| } |
| @@ -93,16 +178,25 @@ class SerialConnectionTest : public testing::Test, public mojo::ErrorHandler { |
| serial::DeviceControlSignalsPtr signals_; |
| bool connected_; |
| bool success_; |
| + int bytes_sent_; |
| + serial::SendError send_error_; |
| + serial::ReceiveError receive_error_; |
| + std::string data_received_; |
| + Event expected_event_; |
| scoped_ptr<base::MessageLoop> message_loop_; |
| - scoped_ptr<base::RunLoop> run_loop_; |
| + base::Closure stop_run_loop_; |
| mojo::InterfacePtr<serial::Connection> connection_; |
| + scoped_ptr<DataSender> sender_; |
| + scoped_refptr<DataReceiver> receiver_; |
| scoped_refptr<TestSerialIoHandler> io_handler_; |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SerialConnectionTest); |
| }; |
| +const uint32_t SerialConnectionTest::kBufferSize = 10; |
| + |
| TEST_F(SerialConnectionTest, GetInfo) { |
| // |info_| is filled in during SetUp(). |
| ASSERT_TRUE(info_); |
| @@ -119,10 +213,11 @@ TEST_F(SerialConnectionTest, SetOptions) { |
| options->data_bits = serial::DATA_BITS_SEVEN; |
| options->has_cts_flow_control = true; |
| options->cts_flow_control = true; |
| - connection_->SetOptions( |
| - options.Pass(), |
| - base::Bind(&SerialConnectionTest::StoreSuccess, base::Unretained(this))); |
| - RunMessageLoop(); |
| + connection_->SetOptions(options.Pass(), |
| + base::Bind(&SerialConnectionTest::StoreSuccess, |
| + base::Unretained(this), |
| + EVENT_SET_OPTIONS)); |
| + WaitForEvent(EVENT_SET_OPTIONS); |
| ASSERT_TRUE(success_); |
| serial::ConnectionInfo* info = io_handler_->connection_info(); |
| EXPECT_EQ(12345u, info->bitrate); |
| @@ -139,7 +234,7 @@ TEST_F(SerialConnectionTest, GetControlSignals) { |
| signals->dcd = true; |
| signals->dsr = true; |
| - RunMessageLoop(); |
| + WaitForEvent(EVENT_GOT_CONTROL_SIGNALS); |
| ASSERT_TRUE(signals_); |
| EXPECT_TRUE(signals_->dcd); |
| EXPECT_FALSE(signals_->cts); |
| @@ -154,10 +249,11 @@ TEST_F(SerialConnectionTest, SetControlSignals) { |
| signals->has_rts = true; |
| signals->rts = true; |
| - connection_->SetControlSignals( |
| - signals.Pass(), |
| - base::Bind(&SerialConnectionTest::StoreSuccess, base::Unretained(this))); |
| - RunMessageLoop(); |
| + connection_->SetControlSignals(signals.Pass(), |
| + base::Bind(&SerialConnectionTest::StoreSuccess, |
| + base::Unretained(this), |
| + EVENT_SET_CONTROL_SIGNALS)); |
| + WaitForEvent(EVENT_SET_CONTROL_SIGNALS); |
| ASSERT_TRUE(success_); |
| EXPECT_TRUE(io_handler_->dtr()); |
| EXPECT_TRUE(io_handler_->rts()); |
| @@ -165,17 +261,67 @@ TEST_F(SerialConnectionTest, SetControlSignals) { |
| TEST_F(SerialConnectionTest, Flush) { |
| ASSERT_EQ(0, io_handler_->flushes()); |
| - connection_->Flush( |
| - base::Bind(&SerialConnectionTest::StoreSuccess, base::Unretained(this))); |
| - RunMessageLoop(); |
| + connection_->Flush(base::Bind(&SerialConnectionTest::StoreSuccess, |
| + base::Unretained(this), |
| + EVENT_FLUSHED)); |
| + WaitForEvent(EVENT_FLUSHED); |
| ASSERT_TRUE(success_); |
| EXPECT_EQ(1, io_handler_->flushes()); |
| } |
| TEST_F(SerialConnectionTest, Disconnect) { |
| connection_.reset(); |
| - message_loop_.reset(); |
| + io_handler_->set_send_callback(base::Bind(base::DoNothing)); |
| + ASSERT_NO_FATAL_FAILURE(Send("data")); |
| + WaitForEvent(EVENT_SEND_ERROR); |
| + EXPECT_EQ(serial::SEND_ERROR_DISCONNECTED, send_error_); |
| + EXPECT_EQ(0, bytes_sent_); |
| + ASSERT_NO_FATAL_FAILURE(Receive()); |
| + WaitForEvent(EVENT_RECEIVE_ERROR); |
| + EXPECT_EQ(serial::RECEIVE_ERROR_DISCONNECTED, receive_error_); |
| + EXPECT_EQ("", data_received_); |
| EXPECT_TRUE(io_handler_->HasOneRef()); |
| } |
| +TEST_F(SerialConnectionTest, Echo) { |
| + ASSERT_NO_FATAL_FAILURE(Send("data")); |
| + WaitForEvent(EVENT_DATA_SENT); |
| + EXPECT_EQ(serial::SEND_ERROR_NONE, send_error_); |
| + EXPECT_EQ(4, bytes_sent_); |
| + ASSERT_NO_FATAL_FAILURE(Receive()); |
| + WaitForEvent(EVENT_DATA_RECEIVED); |
| + EXPECT_EQ("data", data_received_); |
| + EXPECT_EQ(serial::RECEIVE_ERROR_NONE, receive_error_); |
| +} |
| + |
| +TEST_F(SerialConnectionTest, Cancel) { |
| + // To test that cancels are correctly passed to the IoHandler, we need a send |
| + // to be in progress because otherwise, the DataSinkReceiver would handle the |
| + // cancel internally. |
| + io_handler_->set_send_callback( |
|
raymes
2014/08/22 04:57:43
Maybe add a comment to this function in TestIoHand
Sam McNally
2014/08/22 08:12:12
Done.
|
| + base::Bind(&SerialConnectionTest::EventReceived, |
| + base::Unretained(this), |
| + EVENT_DATA_AT_IO_HANDLER)); |
| + ASSERT_NO_FATAL_FAILURE(Send("something else")); |
| + WaitForEvent(EVENT_DATA_AT_IO_HANDLER); |
| + EXPECT_EQ(0, bytes_sent_); |
| + |
| + ASSERT_TRUE(sender_->Cancel(serial::SEND_ERROR_TIMEOUT, |
| + base::Bind(&SerialConnectionTest::EventReceived, |
| + base::Unretained(this), |
| + EVENT_CANCEL_COMPLETE))); |
| + |
| + WaitForEvent(EVENT_CANCEL_COMPLETE); |
| + EXPECT_EQ(serial::SEND_ERROR_TIMEOUT, send_error_); |
| + |
| + ASSERT_NO_FATAL_FAILURE(Send("data")); |
| + WaitForEvent(EVENT_DATA_SENT); |
| + EXPECT_EQ(serial::SEND_ERROR_NONE, send_error_); |
| + EXPECT_EQ(4, bytes_sent_); |
| + ASSERT_NO_FATAL_FAILURE(Receive()); |
| + WaitForEvent(EVENT_DATA_RECEIVED); |
| + EXPECT_EQ("data", data_received_); |
| + EXPECT_EQ(serial::RECEIVE_ERROR_NONE, receive_error_); |
| +} |
| + |
| } // namespace device |