blob: ba9c4bdae3ebcae577b465a1b1e4f89de852f2fc [file] [log] [blame]
// Copyright 2017 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 "device/fido/ble/fido_ble_frames.h"
#include <algorithm>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
namespace {
std::vector<uint8_t> GetSomeData(size_t size) {
std::vector<uint8_t> data(size);
for (size_t i = 0; i < size; ++i)
data[i] = static_cast<uint8_t>((i * i) & 0xFF);
return data;
}
} // namespace
namespace device {
TEST(FidoBleFramesTest, InitializationFragment) {
const std::vector<uint8_t> data = GetSomeData(25);
constexpr uint16_t kDataLength = 21123;
FidoBleFrameInitializationFragment fragment(
FidoBleDeviceCommand::kMsg, kDataLength, base::make_span(data));
std::vector<uint8_t> buffer;
const size_t binary_size = fragment.Serialize(&buffer);
EXPECT_EQ(buffer.size(), binary_size);
EXPECT_EQ(data.size() + 3, binary_size);
FidoBleFrameInitializationFragment parsed_fragment;
ASSERT_TRUE(
FidoBleFrameInitializationFragment::Parse(buffer, &parsed_fragment));
EXPECT_EQ(kDataLength, parsed_fragment.data_length());
EXPECT_TRUE(std::equal(data.begin(), data.end(),
parsed_fragment.fragment().begin(),
parsed_fragment.fragment().end()));
EXPECT_EQ(FidoBleDeviceCommand::kMsg, parsed_fragment.command());
}
TEST(FidoBleFramesTest, ContinuationFragment) {
const auto data = GetSomeData(25);
constexpr uint8_t kSequence = 61;
FidoBleFrameContinuationFragment fragment(base::make_span(data), kSequence);
std::vector<uint8_t> buffer;
const size_t binary_size = fragment.Serialize(&buffer);
EXPECT_EQ(buffer.size(), binary_size);
EXPECT_EQ(data.size() + 1, binary_size);
FidoBleFrameContinuationFragment parsed_fragment;
ASSERT_TRUE(
FidoBleFrameContinuationFragment::Parse(buffer, &parsed_fragment));
EXPECT_TRUE(std::equal(data.begin(), data.end(),
parsed_fragment.fragment().begin(),
parsed_fragment.fragment().end()));
EXPECT_EQ(kSequence, parsed_fragment.sequence());
}
TEST(FidoBleFramesTest, SplitAndAssemble) {
for (size_t size : {0, 1, 16, 17, 18, 20, 21, 22, 35, 36,
37, 39, 40, 41, 54, 55, 56, 60, 100, 65535}) {
SCOPED_TRACE(size);
FidoBleFrame frame(FidoBleDeviceCommand::kPing, GetSomeData(size));
auto fragments = frame.ToFragments(20);
EXPECT_EQ(frame.command(), fragments.first.command());
EXPECT_EQ(frame.data().size(),
static_cast<size_t>(fragments.first.data_length()));
FidoBleFrameAssembler assembler(fragments.first);
while (!fragments.second.empty()) {
ASSERT_TRUE(assembler.AddFragment(fragments.second.front()));
fragments.second.pop();
}
EXPECT_TRUE(assembler.IsDone());
ASSERT_TRUE(assembler.GetFrame());
auto result_frame = std::move(*assembler.GetFrame());
EXPECT_EQ(frame.command(), result_frame.command());
EXPECT_EQ(frame.data(), result_frame.data());
}
}
TEST(FidoBleFramesTest, FrameAssemblerError) {
FidoBleFrame frame(FidoBleDeviceCommand::kPing, GetSomeData(30));
auto fragments = frame.ToFragments(20);
ASSERT_EQ(1u, fragments.second.size());
fragments.second.front() =
FidoBleFrameContinuationFragment(fragments.second.front().fragment(), 51);
FidoBleFrameAssembler assembler(fragments.first);
EXPECT_FALSE(assembler.IsDone());
EXPECT_FALSE(assembler.GetFrame());
EXPECT_FALSE(assembler.AddFragment(fragments.second.front()));
EXPECT_FALSE(assembler.IsDone());
EXPECT_FALSE(assembler.GetFrame());
}
TEST(FidoBleFramesTest, FrameGettersAndValidity) {
{
FidoBleFrame frame(FidoBleDeviceCommand::kKeepAlive,
std::vector<uint8_t>(2));
EXPECT_FALSE(frame.IsValid());
}
{
FidoBleFrame frame(FidoBleDeviceCommand::kError, {});
EXPECT_FALSE(frame.IsValid());
}
for (auto code : {FidoBleFrame::KeepaliveCode::TUP_NEEDED,
FidoBleFrame::KeepaliveCode::PROCESSING}) {
FidoBleFrame frame(FidoBleDeviceCommand::kKeepAlive,
std::vector<uint8_t>(1, static_cast<uint8_t>(code)));
EXPECT_TRUE(frame.IsValid());
EXPECT_EQ(code, frame.GetKeepaliveCode());
}
for (auto code : {
FidoBleFrame::ErrorCode::INVALID_CMD,
FidoBleFrame::ErrorCode::INVALID_PAR,
FidoBleFrame::ErrorCode::INVALID_SEQ,
FidoBleFrame::ErrorCode::INVALID_LEN,
FidoBleFrame::ErrorCode::REQ_TIMEOUT, FidoBleFrame::ErrorCode::NA_1,
FidoBleFrame::ErrorCode::NA_2, FidoBleFrame::ErrorCode::NA_3,
}) {
FidoBleFrame frame(FidoBleDeviceCommand::kError,
{static_cast<uint8_t>(code)});
EXPECT_TRUE(frame.IsValid());
EXPECT_EQ(code, frame.GetErrorCode());
}
}
} // namespace device