普通文本  |  414行  |  11.59 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 "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) {}

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

  virtual 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