Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "tools/battor_agent/battor_connection.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "device/serial/serial.mojom.h" | |
| 10 #include "device/serial/test_serial_io_handler.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 #include "tools/battor_agent/battor_protocol_types.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 void NullWriteCallback(int, device::serial::SendError) {} | |
| 17 void NullReadCallback(int, device::serial::ReceiveError) {} | |
| 18 | |
| 19 } // namespace | |
| 20 | |
| 21 namespace battor { | |
| 22 | |
| 23 // TestableBattOrConnection uses a fake serial connection be testable. | |
| 24 class TestableBattOrConnection : public BattOrConnection { | |
| 25 public: | |
| 26 TestableBattOrConnection() : BattOrConnection(nullptr, nullptr) {} | |
| 27 scoped_refptr<device::SerialIoHandler> CreateIoHandler() override { | |
| 28 return device::TestSerialIoHandler::Create(); | |
| 29 } | |
| 30 | |
| 31 scoped_refptr<device::SerialIoHandler> GetIoHandler() { return io_handler_; } | |
| 32 }; | |
| 33 | |
| 34 // BattOrConnectionTest provides a BattOrConnection that captures the | |
| 35 // results of its commands. | |
| 36 class BattOrConnectionTest : public testing::Test { | |
| 37 protected: | |
| 38 scoped_ptr<TestableBattOrConnection> connection; | |
| 39 | |
| 40 void SetUp() override { | |
| 41 connection.reset(new TestableBattOrConnection()); | |
| 42 } | |
| 43 | |
| 44 void Connect() { | |
| 45 connection->Connect( | |
| 46 "/dev/test", base::Bind(&BattOrConnectionTest::CaptureConnectResult, | |
| 47 base::Unretained(this))); | |
| 48 } | |
| 49 | |
| 50 void CaptureConnectResult(bool success) { connect_success = success; } | |
| 51 | |
| 52 void SendControlMessage(BattOrControlMessageType type, | |
| 53 uint16_t param1, | |
| 54 uint16_t param2) { | |
| 55 BattOrControlMessage msg{type, param1, param2}; | |
| 56 connection->SendBytes( | |
| 57 base::Bind(&BattOrConnectionTest::CaptureSendBytesResults, | |
| 58 base::Unretained(this)), | |
| 59 BATTOR_MESSAGE_TYPE_CONTROL, reinterpret_cast<char*>(&msg), | |
| 60 sizeof(msg)); | |
| 61 } | |
| 62 | |
| 63 // Writes the specified bytes directly to the serial connectino. | |
| 64 void SendBytesRaw(const char* data, uint16_t bytes_to_send) { | |
| 65 std::vector<char> data_vector(data, data + bytes_to_send); | |
| 66 connection->GetIoHandler()->Write(make_scoped_ptr( | |
| 67 new device::SendBuffer(data_vector, base::Bind(&NullWriteCallback)))); | |
| 68 } | |
| 69 | |
| 70 void CaptureSendBytesResults(bool success) { send_success = success; } | |
| 71 | |
| 72 void ReadBytes(uint16_t bytes_to_read) { | |
| 73 connection->ReadBytes( | |
| 74 base::Bind(&BattOrConnectionTest::CaptureReadBytesResults, | |
| 75 base::Unretained(this)), | |
| 76 bytes_to_read); | |
| 77 } | |
| 78 | |
| 79 // Reads the specified number of bytes directly from the serial connection. | |
| 80 scoped_refptr<net::IOBuffer> ReadBytesRaw(int bytes_to_read) { | |
| 81 scoped_refptr<net::IOBuffer> buffer( | |
| 82 new net::IOBuffer((size_t)bytes_to_read)); | |
| 83 | |
| 84 connection->GetIoHandler()->Read( | |
| 85 make_scoped_ptr(new device::ReceiveBuffer( | |
| 86 buffer, bytes_to_read, base::Bind(&NullReadCallback)))); | |
| 87 | |
| 88 return buffer; | |
| 89 } | |
| 90 | |
| 91 void CaptureReadBytesResults(bool success, | |
| 92 BattOrMessageType type, | |
| 93 scoped_ptr<std::vector<char>> bytes) { | |
| 94 read_success = success; | |
| 95 read_type = type; | |
| 96 read_bytes = bytes.Pass(); | |
| 97 } | |
| 98 | |
| 99 // Result from the last connect command. | |
| 100 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
| |
| 101 // Result from the last send command. | |
| 102 bool send_success; | |
| 103 // Results from the last read command. | |
| 104 bool read_success; | |
| 105 BattOrMessageType read_type; | |
| 106 scoped_ptr<std::vector<char>> read_bytes; | |
| 107 }; | |
| 108 | |
| 109 TEST_F(BattOrConnectionTest, InitSendsCorrectBytes) { | |
| 110 Connect(); | |
| 111 ASSERT_TRUE(connect_success); | |
| 112 | |
| 113 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); | |
| 114 | |
| 115 const char expected_data[] = { | |
| 116 BATTOR_SPECIAL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, | |
| 117 BATTOR_SPECIAL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_INIT, | |
| 118 BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 119 BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 120 BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 121 BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 122 BATTOR_SPECIAL_BYTE_END, | |
| 123 }; | |
| 124 | |
| 125 ASSERT_TRUE(send_success); | |
| 126 ASSERT_EQ(0, std::memcmp(ReadBytesRaw(13)->data(), expected_data, 13)); | |
| 127 } | |
| 128 | |
| 129 TEST_F(BattOrConnectionTest, ResetSendsCorrectBytes) { | |
| 130 Connect(); | |
| 131 ASSERT_TRUE(connect_success); | |
| 132 | |
| 133 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); | |
| 134 | |
| 135 const char expected_data[] = { | |
| 136 BATTOR_SPECIAL_BYTE_START, | |
| 137 BATTOR_MESSAGE_TYPE_CONTROL, | |
| 138 BATTOR_CONTROL_MESSAGE_TYPE_RESET, | |
| 139 BATTOR_SPECIAL_BYTE_ESCAPE, | |
| 140 0x00, | |
| 141 BATTOR_SPECIAL_BYTE_ESCAPE, | |
| 142 0x00, | |
| 143 BATTOR_SPECIAL_BYTE_ESCAPE, | |
| 144 0x00, | |
| 145 BATTOR_SPECIAL_BYTE_ESCAPE, | |
| 146 0x00, | |
| 147 BATTOR_SPECIAL_BYTE_END, | |
| 148 }; | |
| 149 | |
| 150 ASSERT_TRUE(send_success); | |
| 151 ASSERT_EQ(0, std::memcmp(ReadBytesRaw(12)->data(), expected_data, 12)); | |
| 152 } | |
| 153 | |
| 154 TEST_F(BattOrConnectionTest, ReadBytesControlMessage) { | |
| 155 Connect(); | |
| 156 ASSERT_TRUE(connect_success); | |
| 157 | |
| 158 const char data[] = { | |
| 159 BATTOR_SPECIAL_BYTE_START, | |
| 160 BATTOR_MESSAGE_TYPE_CONTROL, | |
| 161 BATTOR_CONTROL_MESSAGE_TYPE_RESET, | |
| 162 0x04, | |
| 163 0x04, | |
| 164 0x04, | |
| 165 0x04, | |
| 166 BATTOR_SPECIAL_BYTE_END, | |
| 167 }; | |
| 168 SendBytesRaw(data, 8); | |
| 169 | |
| 170 ReadBytes(5); | |
| 171 | |
| 172 const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x04, 0x04, 0x04, | |
| 173 0x04}; | |
| 174 | |
| 175 ASSERT_TRUE(read_success); | |
| 176 ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, read_type); | |
| 177 ASSERT_EQ(0, std::memcmp(read_bytes->data(), expected, 5)); | |
| 178 } | |
| 179 | |
| 180 TEST_F(BattOrConnectionTest, ReadBytesEmptyStream) { | |
| 181 Connect(); | |
| 182 ASSERT_TRUE(connect_success); | |
| 183 | |
| 184 ReadBytes(1); | |
| 185 | |
| 186 ASSERT_FALSE(read_success); | |
| 187 } | |
| 188 | |
| 189 TEST_F(BattOrConnectionTest, ReadBytesWithEscapeCharacters) { | |
| 190 Connect(); | |
| 191 ASSERT_TRUE(connect_success); | |
| 192 | |
| 193 const char data[] = { | |
| 194 BATTOR_SPECIAL_BYTE_START, | |
| 195 BATTOR_MESSAGE_TYPE_CONTROL_ACK, | |
| 196 BATTOR_CONTROL_MESSAGE_TYPE_RESET, | |
| 197 BATTOR_SPECIAL_BYTE_ESCAPE, | |
| 198 0x00, | |
| 199 BATTOR_SPECIAL_BYTE_END, | |
| 200 }; | |
| 201 SendBytesRaw(data, 6); | |
| 202 | |
| 203 ReadBytes(2); | |
| 204 | |
| 205 const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x00}; | |
| 206 | |
| 207 ASSERT_TRUE(read_success); | |
| 208 ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL_ACK, read_type); | |
| 209 ASSERT_EQ(0, std::memcmp(read_bytes->data(), expected, 2)); | |
| 210 } | |
| 211 | |
| 212 TEST_F(BattOrConnectionTest, ReadBytesWithEscapeCharactersInSubsequentReads) { | |
| 213 Connect(); | |
| 214 ASSERT_TRUE(connect_success); | |
| 215 | |
| 216 // The first read should request 7 bytes. Of those 7 bytes, though, 2 of them | |
| 217 // are escape bytes, so we'll then do a second read of 2 bytes. In that second | |
| 218 // read, we'll see another escape byte, so we'll have to do a third read of 1 | |
| 219 // byte. That third read should complete the message. | |
| 220 const char data[] = { | |
| 221 // These bytes make up the first read. | |
| 222 BATTOR_SPECIAL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL_ACK, | |
| 223 BATTOR_CONTROL_MESSAGE_TYPE_RESET, BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 224 BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 225 // These bytes make up the second read. | |
| 226 BATTOR_SPECIAL_BYTE_ESCAPE, 0x00, | |
| 227 // This byte makes up the third read. | |
| 228 BATTOR_SPECIAL_BYTE_END, | |
| 229 }; | |
| 230 SendBytesRaw(data, 10); | |
| 231 | |
| 232 ReadBytes(4); | |
| 233 | |
| 234 const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x00, 0x00, 0x00}; | |
| 235 | |
| 236 ASSERT_TRUE(read_success); | |
| 237 ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL_ACK, read_type); | |
| 238 ASSERT_EQ(0, std::memcmp(read_bytes->data(), expected, 4)); | |
| 239 } | |
| 240 | |
| 241 TEST_F(BattOrConnectionTest, ReadControlMessage) { | |
| 242 Connect(); | |
| 243 ASSERT_TRUE(connect_success); | |
| 244 | |
| 245 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); | |
| 246 ReadBytes(sizeof(BattOrControlMessage)); | |
| 247 | |
| 248 ASSERT_TRUE(read_success); | |
| 249 ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, read_type); | |
| 250 | |
| 251 BattOrControlMessage* msg = | |
| 252 reinterpret_cast<BattOrControlMessage*>(read_bytes->data()); | |
| 253 | |
| 254 ASSERT_EQ(BATTOR_CONTROL_MESSAGE_TYPE_RESET, msg->type); | |
| 255 ASSERT_EQ(4, msg->param1); | |
| 256 ASSERT_EQ(7, msg->param2); | |
| 257 } | |
| 258 | |
| 259 } // namespace battor | |
| OLD | NEW |