1 // Copyright 2017 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 "device/fido/ble/fido_ble_frames.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace {
13
GetSomeData(size_t size)14 std::vector<uint8_t> GetSomeData(size_t size) {
15 std::vector<uint8_t> data(size);
16 for (size_t i = 0; i < size; ++i)
17 data[i] = static_cast<uint8_t>((i * i) & 0xFF);
18 return data;
19 }
20
21 } // namespace
22
23 namespace device {
24
TEST(FidoBleFramesTest,InitializationFragment)25 TEST(FidoBleFramesTest, InitializationFragment) {
26 const std::vector<uint8_t> data = GetSomeData(25);
27 constexpr uint16_t kDataLength = 21123;
28
29 FidoBleFrameInitializationFragment fragment(
30 FidoBleDeviceCommand::kMsg, kDataLength, base::make_span(data));
31 std::vector<uint8_t> buffer;
32 const size_t binary_size = fragment.Serialize(&buffer);
33 EXPECT_EQ(buffer.size(), binary_size);
34
35 EXPECT_EQ(data.size() + 3, binary_size);
36
37 FidoBleFrameInitializationFragment parsed_fragment;
38 ASSERT_TRUE(
39 FidoBleFrameInitializationFragment::Parse(buffer, &parsed_fragment));
40
41 EXPECT_EQ(kDataLength, parsed_fragment.data_length());
42 EXPECT_TRUE(std::equal(data.begin(), data.end(),
43 parsed_fragment.fragment().begin(),
44 parsed_fragment.fragment().end()));
45 EXPECT_EQ(FidoBleDeviceCommand::kMsg, parsed_fragment.command());
46 }
47
TEST(FidoBleFramesTest,ContinuationFragment)48 TEST(FidoBleFramesTest, ContinuationFragment) {
49 const auto data = GetSomeData(25);
50 constexpr uint8_t kSequence = 61;
51
52 FidoBleFrameContinuationFragment fragment(base::make_span(data), kSequence);
53
54 std::vector<uint8_t> buffer;
55 const size_t binary_size = fragment.Serialize(&buffer);
56 EXPECT_EQ(buffer.size(), binary_size);
57
58 EXPECT_EQ(data.size() + 1, binary_size);
59
60 FidoBleFrameContinuationFragment parsed_fragment;
61 ASSERT_TRUE(
62 FidoBleFrameContinuationFragment::Parse(buffer, &parsed_fragment));
63
64 EXPECT_TRUE(std::equal(data.begin(), data.end(),
65 parsed_fragment.fragment().begin(),
66 parsed_fragment.fragment().end()));
67 EXPECT_EQ(kSequence, parsed_fragment.sequence());
68 }
69
TEST(FidoBleFramesTest,SplitAndAssemble)70 TEST(FidoBleFramesTest, SplitAndAssemble) {
71 for (size_t size : {0, 1, 16, 17, 18, 20, 21, 22, 35, 36,
72 37, 39, 40, 41, 54, 55, 56, 60, 100, 65535}) {
73 SCOPED_TRACE(size);
74
75 FidoBleFrame frame(FidoBleDeviceCommand::kPing, GetSomeData(size));
76
77 auto fragments = frame.ToFragments(20);
78
79 EXPECT_EQ(frame.command(), fragments.first.command());
80 EXPECT_EQ(frame.data().size(),
81 static_cast<size_t>(fragments.first.data_length()));
82
83 FidoBleFrameAssembler assembler(fragments.first);
84 while (!fragments.second.empty()) {
85 ASSERT_TRUE(assembler.AddFragment(fragments.second.front()));
86 fragments.second.pop();
87 }
88
89 EXPECT_TRUE(assembler.IsDone());
90 ASSERT_TRUE(assembler.GetFrame());
91
92 auto result_frame = std::move(*assembler.GetFrame());
93 EXPECT_EQ(frame.command(), result_frame.command());
94 EXPECT_EQ(frame.data(), result_frame.data());
95 }
96 }
97
TEST(FidoBleFramesTest,FrameAssemblerError)98 TEST(FidoBleFramesTest, FrameAssemblerError) {
99 FidoBleFrame frame(FidoBleDeviceCommand::kPing, GetSomeData(30));
100
101 auto fragments = frame.ToFragments(20);
102 ASSERT_EQ(1u, fragments.second.size());
103
104 fragments.second.front() =
105 FidoBleFrameContinuationFragment(fragments.second.front().fragment(), 51);
106
107 FidoBleFrameAssembler assembler(fragments.first);
108 EXPECT_FALSE(assembler.IsDone());
109 EXPECT_FALSE(assembler.GetFrame());
110 EXPECT_FALSE(assembler.AddFragment(fragments.second.front()));
111 EXPECT_FALSE(assembler.IsDone());
112 EXPECT_FALSE(assembler.GetFrame());
113 }
114
TEST(FidoBleFramesTest,FrameGettersAndValidity)115 TEST(FidoBleFramesTest, FrameGettersAndValidity) {
116 {
117 FidoBleFrame frame(FidoBleDeviceCommand::kKeepAlive,
118 std::vector<uint8_t>(2));
119 EXPECT_FALSE(frame.IsValid());
120 }
121 {
122 FidoBleFrame frame(FidoBleDeviceCommand::kError, {});
123 EXPECT_FALSE(frame.IsValid());
124 }
125
126 for (auto code : {FidoBleFrame::KeepaliveCode::TUP_NEEDED,
127 FidoBleFrame::KeepaliveCode::PROCESSING}) {
128 FidoBleFrame frame(FidoBleDeviceCommand::kKeepAlive,
129 std::vector<uint8_t>(1, static_cast<uint8_t>(code)));
130 EXPECT_TRUE(frame.IsValid());
131 EXPECT_EQ(code, frame.GetKeepaliveCode());
132 }
133
134 for (auto code : {
135 FidoBleFrame::ErrorCode::INVALID_CMD,
136 FidoBleFrame::ErrorCode::INVALID_PAR,
137 FidoBleFrame::ErrorCode::INVALID_SEQ,
138 FidoBleFrame::ErrorCode::INVALID_LEN,
139 FidoBleFrame::ErrorCode::REQ_TIMEOUT, FidoBleFrame::ErrorCode::NA_1,
140 FidoBleFrame::ErrorCode::NA_2, FidoBleFrame::ErrorCode::NA_3,
141 }) {
142 FidoBleFrame frame(FidoBleDeviceCommand::kError,
143 {static_cast<uint8_t>(code)});
144 EXPECT_TRUE(frame.IsValid());
145 EXPECT_EQ(code, frame.GetErrorCode());
146 }
147 }
148
149 } // namespace device
150