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