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 |