1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "model/hci/h4_parser.h"
18
19 #include <gtest/gtest.h>
20
21 #include <array>
22
23 namespace rootcanal {
24 using PacketData = std::vector<uint8_t>;
25
26 class H4ParserTest : public ::testing::Test {
27 public:
28 protected:
SetUp()29 void SetUp() override {
30 packet_.clear();
31 parser_.Reset();
32 }
33
TearDown()34 void TearDown() override { parser_.Reset(); }
35
PacketReadCallback(const std::vector<uint8_t> & packet)36 void PacketReadCallback(const std::vector<uint8_t>& packet) {
37 packet_ = std::move(packet);
38 }
39
40 protected:
41 H4Parser parser_{
__anon362f6ab60102() 42 [&](auto p) {
43 type_ = PacketType::COMMAND;
44 PacketReadCallback(p);
45 },
__anon362f6ab60202() 46 [&](auto p) {
47 type_ = PacketType::EVENT;
48 PacketReadCallback(p);
49 },
__anon362f6ab60302() 50 [&](auto p) {
51 type_ = PacketType::ACL;
52 PacketReadCallback(p);
53 },
__anon362f6ab60402() 54 [&](auto p) {
55 type_ = PacketType::SCO;
56 PacketReadCallback(p);
57 },
__anon362f6ab60502() 58 [&](auto p) {
59 type_ = PacketType::ISO;
60 PacketReadCallback(p);
61 },
62 true,
63 };
64 PacketData packet_;
65 PacketType type_;
66 };
67
TEST_F(H4ParserTest,InitiallyExpectOneByte)68 TEST_F(H4ParserTest, InitiallyExpectOneByte) {
69 ASSERT_EQ(1, (int)parser_.BytesRequested());
70 }
71
TEST_F(H4ParserTest,SwitchStateAfterType)72 TEST_F(H4ParserTest, SwitchStateAfterType) {
73 uint8_t typ = (uint8_t)PacketType::ACL;
74 ASSERT_TRUE(parser_.Consume(&typ, 1));
75 ASSERT_EQ(parser_.CurrentState(), H4Parser::State::HCI_PREAMBLE);
76 }
77
TEST_F(H4ParserTest,RequestedBytesDecreases)78 TEST_F(H4ParserTest, RequestedBytesDecreases) {
79 // Make sure that the requested bytes is monotonically decreasing
80 // for the requested types.
81 uint8_t typ = (uint8_t)PacketType::ACL;
82 ASSERT_TRUE(parser_.Consume(&typ, 1));
83 auto wanted = parser_.BytesRequested();
84 while (wanted > 0) {
85 ASSERT_EQ(wanted, parser_.BytesRequested());
86 ASSERT_TRUE(parser_.Consume(&typ, 1));
87 wanted--;
88 }
89
90 ASSERT_EQ(parser_.CurrentState(), H4Parser::State::HCI_PAYLOAD);
91 wanted = parser_.BytesRequested();
92 while (wanted > 0) {
93 ASSERT_EQ(wanted, parser_.BytesRequested());
94 ASSERT_TRUE(parser_.Consume(&typ, 1));
95 wanted--;
96 }
97
98 // A callback should have been invoked.
99 ASSERT_LT(0, (int)packet_.size());
100 }
101
TEST_F(H4ParserTest,RejectNoData)102 TEST_F(H4ParserTest, RejectNoData) {
103 // You need to give us something!
104 PacketData bad_bit;
105 ASSERT_FALSE(parser_.Consume(bad_bit.data(), bad_bit.size()));
106 }
107
TEST_F(H4ParserTest,TooMuchIsDeath)108 TEST_F(H4ParserTest, TooMuchIsDeath) {
109 PacketData bad_bit({0xfd});
110 ASSERT_DEATH(parser_.Consume(bad_bit.data(), parser_.BytesRequested() + 1),
111 "More bytes read .* than expected .*!");
112 }
113
TEST_F(H4ParserTest,WrongTypeIsDeath)114 TEST_F(H4ParserTest, WrongTypeIsDeath) {
115 parser_.DisableRecovery();
116 PacketData bad_bit({0xfd});
117 ASSERT_DEATH(parser_.Consume(bad_bit.data(), bad_bit.size()),
118 "Received invalid packet type.*");
119 }
120
TEST_F(H4ParserTest,CallsTheRightCallbacks)121 TEST_F(H4ParserTest, CallsTheRightCallbacks) {
122 // Make sure that the proper type of callback is invoked.
123 std::vector<PacketType> types({PacketType::ACL, PacketType::SCO,
124 PacketType::COMMAND, PacketType::EVENT,
125 PacketType::ISO});
126 for (auto packetType : types) {
127 // Configure the incoming packet.
128 uint8_t typ = (uint8_t)packetType;
129 ASSERT_TRUE(parser_.Consume(&typ, 1));
130
131 // Feed data as long as this packet is not complete.
132 while (parser_.CurrentState() != H4Parser::State::HCI_TYPE) {
133 PacketData data;
134 for (uint32_t i = 0; i < parser_.BytesRequested(); i++) {
135 data.push_back((uint8_t)i);
136 }
137 ASSERT_TRUE(parser_.Consume(data.data(), data.size()));
138 }
139
140 // The proper callbacks should have been invoked.
141 ASSERT_LT(0, (int)packet_.size());
142 ASSERT_EQ(packetType, type_);
143 }
144 }
145
TEST_F(H4ParserTest,Recovery)146 TEST_F(H4ParserTest, Recovery) {
147 // Validate that the recovery state is exited only after receiving the
148 // HCI Reset command.
149 parser_.EnableRecovery();
150
151 // Enter recovery state after receiving an invalid packet type.
152 uint8_t invalid_packet_type = 0xfd;
153 ASSERT_TRUE(parser_.Consume(&invalid_packet_type, 1));
154 ASSERT_EQ(parser_.CurrentState(), H4Parser::State::HCI_RECOVERY);
155
156 const std::array<uint8_t, 4> reset_command{0x01, 0x03, 0x0c, 0x00};
157
158 // Send prefixes of the HCI Reset command, restarting over from the start.
159 for (size_t n = 1; n < 4; n++) {
160 for (size_t i = 0; i < n; i++) {
161 ASSERT_TRUE(parser_.Consume(&reset_command[i], 1));
162 ASSERT_EQ(parser_.CurrentState(), H4Parser::State::HCI_RECOVERY);
163 }
164 }
165
166 // Finally send the full HCI Reset command.
167 for (size_t i = 0; i < 4; i++) {
168 ASSERT_EQ(parser_.CurrentState(), H4Parser::State::HCI_RECOVERY);
169 ASSERT_TRUE(parser_.Consume(&reset_command[i], 1));
170 }
171
172 // Validate that the HCI recovery state is exited,
173 // and the HCI Reset command correctly received on the command callback.
174 ASSERT_EQ(parser_.CurrentState(), H4Parser::State::HCI_TYPE);
175 ASSERT_LT(0, (int)packet_.size());
176
177 // Validate that the HCI Reset command was correctly received.
178 ASSERT_EQ(type_, PacketType::COMMAND);
179 ASSERT_EQ(packet_.size(), reset_command.size() - 1);
180 for (size_t i = 1; i < packet_.size(); i++) {
181 ASSERT_EQ(packet_[i - 1], reset_command[i]);
182 }
183 }
184
185 } // namespace rootcanal
186