Chromium Code Reviews| Index: tools/battor_agent/battor_connection_unittest.cc |
| diff --git a/tools/battor_agent/battor_connection_unittest.cc b/tools/battor_agent/battor_connection_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0ac4983acfd939ec2078ef6ad92df8b1cee655c1 |
| --- /dev/null |
| +++ b/tools/battor_agent/battor_connection_unittest.cc |
| @@ -0,0 +1,259 @@ |
| +// Copyright 2015 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 "tools/battor_agent/battor_connection.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "device/serial/serial.mojom.h" |
| +#include "device/serial/test_serial_io_handler.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "tools/battor_agent/battor_protocol_types.h" |
| + |
| +namespace { |
| + |
| +void NullWriteCallback(int, device::serial::SendError) {} |
| +void NullReadCallback(int, device::serial::ReceiveError) {} |
| + |
| +} // namespace |
| + |
| +namespace battor { |
| + |
| +// TestableBattOrConnection uses a fake serial connection be testable. |
| +class TestableBattOrConnection : public BattOrConnection { |
| + public: |
| + TestableBattOrConnection() : BattOrConnection(nullptr, nullptr) {} |
| + scoped_refptr<device::SerialIoHandler> CreateIoHandler() override { |
| + return device::TestSerialIoHandler::Create(); |
| + } |
| + |
| + scoped_refptr<device::SerialIoHandler> GetIoHandler() { return io_handler_; } |
| +}; |
| + |
| +// BattOrConnectionTest provides a BattOrConnection that captures the |
| +// results of its commands. |
| +class BattOrConnectionTest : public testing::Test { |
| + protected: |
| + scoped_ptr<TestableBattOrConnection> connection; |
| + |
| + void SetUp() override { |
| + connection.reset(new TestableBattOrConnection()); |
| + } |
| + |
| + void Connect() { |
| + connection->Connect( |
| + "/dev/test", base::Bind(&BattOrConnectionTest::CaptureConnectResult, |
| + base::Unretained(this))); |
| + } |
| + |
| + void CaptureConnectResult(bool success) { connect_success = success; } |
| + |
| + void SendControlMessage(BattOrControlMessageType type, |
| + uint16_t param1, |
| + uint16_t param2) { |
| + BattOrControlMessage msg{type, param1, param2}; |
| + connection->SendBytes( |
| + base::Bind(&BattOrConnectionTest::CaptureSendBytesResults, |
| + base::Unretained(this)), |
| + BATTOR_MESSAGE_TYPE_CONTROL, reinterpret_cast<char*>(&msg), |
| + sizeof(msg)); |
| + } |
| + |
| + // Writes the specified bytes directly to the serial connectino. |
| + void SendBytesRaw(const char* data, uint16_t bytes_to_send) { |
| + std::vector<char> data_vector(data, data + bytes_to_send); |
| + connection->GetIoHandler()->Write(make_scoped_ptr( |
| + new device::SendBuffer(data_vector, base::Bind(&NullWriteCallback)))); |
| + } |
| + |
| + void CaptureSendBytesResults(bool success) { send_success = success; } |
| + |
| + void ReadBytes(uint16_t bytes_to_read) { |
| + connection->ReadBytes( |
| + base::Bind(&BattOrConnectionTest::CaptureReadBytesResults, |
| + base::Unretained(this)), |
| + bytes_to_read); |
| + } |
| + |
| + // Reads the specified number of bytes directly from the serial connection. |
| + scoped_refptr<net::IOBuffer> ReadBytesRaw(int bytes_to_read) { |
| + scoped_refptr<net::IOBuffer> buffer( |
| + new net::IOBuffer((size_t)bytes_to_read)); |
| + |
| + connection->GetIoHandler()->Read( |
| + make_scoped_ptr(new device::ReceiveBuffer( |
| + buffer, bytes_to_read, base::Bind(&NullReadCallback)))); |
| + |
| + return buffer; |
| + } |
| + |
| + void CaptureReadBytesResults(bool success, |
| + BattOrMessageType type, |
| + scoped_ptr<std::vector<char>> bytes) { |
| + read_success = success; |
| + read_type = type; |
| + read_bytes = bytes.Pass(); |
| + } |
| + |
| + // Result from the last connect command. |
| + bool connect_success; |
|
Zhen Wang
2015/12/14 23:39:47
I think the practice is to make variables private
charliea (OOO until 10-5)
2015/12/15 23:50:04
Done.
I wasn't sure if this was the case in unit
|
| + // Result from the last send command. |
| + bool send_success; |
| + // Results from the last read command. |
| + bool read_success; |
| + BattOrMessageType read_type; |
| + scoped_ptr<std::vector<char>> read_bytes; |
| +}; |
| + |
| +TEST_F(BattOrConnectionTest, InitSendsCorrectBytes) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); |
| + |
| + const char expected_data[] = { |
| + BATTOR_SPECIAL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_INIT, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + BATTOR_SPECIAL_BYTE_END, |
| + }; |
| + |
| + ASSERT_TRUE(send_success); |
| + ASSERT_EQ(0, std::memcmp(ReadBytesRaw(13)->data(), expected_data, 13)); |
| +} |
| + |
| +TEST_F(BattOrConnectionTest, ResetSendsCorrectBytes) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); |
| + |
| + const char expected_data[] = { |
| + BATTOR_SPECIAL_BYTE_START, |
| + BATTOR_MESSAGE_TYPE_CONTROL, |
| + BATTOR_CONTROL_MESSAGE_TYPE_RESET, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, |
| + 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, |
| + 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, |
| + 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, |
| + 0x00, |
| + BATTOR_SPECIAL_BYTE_END, |
| + }; |
| + |
| + ASSERT_TRUE(send_success); |
| + ASSERT_EQ(0, std::memcmp(ReadBytesRaw(12)->data(), expected_data, 12)); |
| +} |
| + |
| +TEST_F(BattOrConnectionTest, ReadBytesControlMessage) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + const char data[] = { |
| + BATTOR_SPECIAL_BYTE_START, |
| + BATTOR_MESSAGE_TYPE_CONTROL, |
| + BATTOR_CONTROL_MESSAGE_TYPE_RESET, |
| + 0x04, |
| + 0x04, |
| + 0x04, |
| + 0x04, |
| + BATTOR_SPECIAL_BYTE_END, |
| + }; |
| + SendBytesRaw(data, 8); |
| + |
| + ReadBytes(5); |
| + |
| + const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x04, 0x04, 0x04, |
| + 0x04}; |
| + |
| + ASSERT_TRUE(read_success); |
| + ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, read_type); |
| + ASSERT_EQ(0, std::memcmp(read_bytes->data(), expected, 5)); |
| +} |
| + |
| +TEST_F(BattOrConnectionTest, ReadBytesEmptyStream) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + ReadBytes(1); |
| + |
| + ASSERT_FALSE(read_success); |
| +} |
| + |
| +TEST_F(BattOrConnectionTest, ReadBytesWithEscapeCharacters) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + const char data[] = { |
| + BATTOR_SPECIAL_BYTE_START, |
| + BATTOR_MESSAGE_TYPE_CONTROL_ACK, |
| + BATTOR_CONTROL_MESSAGE_TYPE_RESET, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, |
| + 0x00, |
| + BATTOR_SPECIAL_BYTE_END, |
| + }; |
| + SendBytesRaw(data, 6); |
| + |
| + ReadBytes(2); |
| + |
| + const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x00}; |
| + |
| + ASSERT_TRUE(read_success); |
| + ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL_ACK, read_type); |
| + ASSERT_EQ(0, std::memcmp(read_bytes->data(), expected, 2)); |
| +} |
| + |
| +TEST_F(BattOrConnectionTest, ReadBytesWithEscapeCharactersInSubsequentReads) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + // The first read should request 7 bytes. Of those 7 bytes, though, 2 of them |
| + // are escape bytes, so we'll then do a second read of 2 bytes. In that second |
| + // read, we'll see another escape byte, so we'll have to do a third read of 1 |
| + // byte. That third read should complete the message. |
| + const char data[] = { |
| + // These bytes make up the first read. |
| + BATTOR_SPECIAL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL_ACK, |
| + BATTOR_CONTROL_MESSAGE_TYPE_RESET, BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + // These bytes make up the second read. |
| + BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, |
| + // This byte makes up the third read. |
| + BATTOR_SPECIAL_BYTE_END, |
| + }; |
| + SendBytesRaw(data, 10); |
| + |
| + ReadBytes(4); |
| + |
| + const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x00, 0x00, 0x00}; |
| + |
| + ASSERT_TRUE(read_success); |
| + ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL_ACK, read_type); |
| + ASSERT_EQ(0, std::memcmp(read_bytes->data(), expected, 4)); |
| +} |
| + |
| +TEST_F(BattOrConnectionTest, ReadControlMessage) { |
| + Connect(); |
| + ASSERT_TRUE(connect_success); |
| + |
| + SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); |
| + ReadBytes(sizeof(BattOrControlMessage)); |
| + |
| + ASSERT_TRUE(read_success); |
| + ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, read_type); |
| + |
| + BattOrControlMessage* msg = |
| + reinterpret_cast<BattOrControlMessage*>(read_bytes->data()); |
| + |
| + ASSERT_EQ(BATTOR_CONTROL_MESSAGE_TYPE_RESET, msg->type); |
| + ASSERT_EQ(4, msg->param1); |
| + ASSERT_EQ(7, msg->param2); |
| +} |
| + |
| +} // namespace battor |