普通文本  |  328行  |  10.82 KB

// 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 <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"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace device {
namespace {

class FakeSerialDeviceEnumerator : public SerialDeviceEnumerator {
  virtual mojo::Array<serial::DeviceInfoPtr> GetDevices() OVERRIDE {
    mojo::Array<serial::DeviceInfoPtr> devices(1);
    devices[0] = serial::DeviceInfo::New();
    devices[0]->path = "device";
    return devices.Pass();
  }
};

}  // namespace

class SerialConnectionTest : public testing::Test, public mojo::ErrorHandler {
 public:
  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);
    mojo::InterfacePtr<serial::SerialService> service;
    mojo::BindToProxy(
        new SerialServiceImpl(
            new SerialConnectionFactory(
                base::Bind(&SerialConnectionTest::CreateIoHandler,
                           base::Unretained(this)),
                base::MessageLoopProxy::current()),
            scoped_ptr<SerialDeviceEnumerator>(new FakeSerialDeviceEnumerator)),
        &service);
    service.set_error_handler(this);
    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)));
    WaitForEvent(EVENT_GOT_INFO);
    ASSERT_TRUE(io_handler_.get());
  }

  void StoreInfo(serial::ConnectionInfoPtr options) {
    info_ = options.Pass();
    EventReceived(EVENT_GOT_INFO);
  }

  void StoreControlSignals(serial::DeviceControlSignalsPtr signals) {
    signals_ = signals.Pass();
    EventReceived(EVENT_GOT_CONTROL_SIGNALS);
  }

  void StoreSuccess(Event event_to_report, bool success) {
    success_ = success;
    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 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_)
      return;
    expected_event_ = EVENT_NONE;
    ASSERT_TRUE(message_loop_);
    ASSERT_TRUE(!stop_run_loop_.is_null());
    message_loop_->PostTask(FROM_HERE, stop_run_loop_);
  }

  scoped_refptr<SerialIoHandler> CreateIoHandler() {
    io_handler_ = new TestSerialIoHandler;
    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 {
    EventReceived(EVENT_ERROR);
    FAIL() << "Connection error";
  }

  mojo::Array<serial::DeviceInfoPtr> devices_;
  serial::ConnectionInfoPtr info_;
  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_;
  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_);
  EXPECT_EQ(9600u, info_->bitrate);
  EXPECT_EQ(serial::DATA_BITS_EIGHT, info_->data_bits);
  EXPECT_EQ(serial::PARITY_BIT_NO, info_->parity_bit);
  EXPECT_EQ(serial::STOP_BITS_ONE, info_->stop_bits);
  EXPECT_FALSE(info_->cts_flow_control);
}

TEST_F(SerialConnectionTest, SetOptions) {
  serial::ConnectionOptionsPtr options(serial::ConnectionOptions::New());
  options->bitrate = 12345;
  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),
                                     EVENT_SET_OPTIONS));
  WaitForEvent(EVENT_SET_OPTIONS);
  ASSERT_TRUE(success_);
  serial::ConnectionInfo* info = io_handler_->connection_info();
  EXPECT_EQ(12345u, info->bitrate);
  EXPECT_EQ(serial::DATA_BITS_SEVEN, info->data_bits);
  EXPECT_EQ(serial::PARITY_BIT_NO, info->parity_bit);
  EXPECT_EQ(serial::STOP_BITS_ONE, info->stop_bits);
  EXPECT_TRUE(info->cts_flow_control);
}

TEST_F(SerialConnectionTest, GetControlSignals) {
  connection_->GetControlSignals(base::Bind(
      &SerialConnectionTest::StoreControlSignals, base::Unretained(this)));
  serial::DeviceControlSignals* signals = io_handler_->device_control_signals();
  signals->dcd = true;
  signals->dsr = true;

  WaitForEvent(EVENT_GOT_CONTROL_SIGNALS);
  ASSERT_TRUE(signals_);
  EXPECT_TRUE(signals_->dcd);
  EXPECT_FALSE(signals_->cts);
  EXPECT_FALSE(signals_->ri);
  EXPECT_TRUE(signals_->dsr);
}

TEST_F(SerialConnectionTest, SetControlSignals) {
  serial::HostControlSignalsPtr signals(serial::HostControlSignals::New());
  signals->has_dtr = true;
  signals->dtr = true;
  signals->has_rts = true;
  signals->rts = true;

  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());
}

TEST_F(SerialConnectionTest, Flush) {
  ASSERT_EQ(0, io_handler_->flushes());
  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();
  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(
      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