blob: 0dbe5b8645256423e3dec4c08b7d557d75a48b4c [file] [log] [blame]
// Copyright 2016 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 "components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator.h"
#include <algorithm>
#include <memory>
#include <string>
#include "base/logging.h"
#include "base/macros.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cryptauth {
namespace weave {
class CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest
: public testing::Test {
protected:
CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest() {}
void TestConnectionCloseWithReason(ReasonForClose reason_for_close,
uint8_t expected_reason_for_close) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionClose(reason_for_close);
const uint16_t kCloseSize = 3;
Packet expected(kCloseSize, 0);
// uWeave Header:
// 1--- ---- : type = 1 (control packet)
// -000 ---- : counter = 0
// ---- 0010 : command = 2 (close)
// 1000 0010 = 0x82
expected = {0x82, kEmptyUpperByte, expected_reason_for_close};
EXPECT_EQ(expected, packet);
}
uint8_t GetCounterFromHeader(uint8_t header) { return (header >> 4) & 7; }
uint8_t GetPacketType(uint8_t header) { return (header >> 7) & 1; }
private:
DISALLOW_COPY_AND_ASSIGN(
CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest);
};
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionRequestTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionRequest();
const uint16_t kRequestSize = 7;
Packet expected(kRequestSize, 0);
// uWeave Header:
// 1--- ---- : type = 1 (control packet)
// -000 ---- : counter = 0
// ---- 0000 : command = 0 (request)
// 1000 0000 = 0x80
expected = {0x80,
kEmptyUpperByte,
kByteWeaveVersion,
kEmptyUpperByte,
kByteWeaveVersion,
kEmptyUpperByte,
kByteSelectMaxPacketSize};
EXPECT_EQ(expected, packet);
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionResponseWithDefaultPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionResponse();
const uint16_t kResponseSize = 5;
Packet expected_default(kResponseSize, 0);
// uWeave Header:
// 1--- ---- : type = 1 (control packet)
// -000 ---- : counter = 0
// ---- 0001 : command = 1 (response)
// 1000 0001 = 0x81
expected_default = {0x81, kEmptyUpperByte, kByteWeaveVersion, kEmptyUpperByte,
kByteDefaultMaxPacketSize};
EXPECT_EQ(expected_default, packet);
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionResponseWithSelectedPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
const uint8_t kSelectedPacketSize = 30;
const uint16_t kResponseSize = 5;
generator->SetMaxPacketSize(kSelectedPacketSize);
Packet packet = generator->CreateConnectionResponse();
Packet expected_selected(kResponseSize, 0);
// uWeave Header:
// 1--- ---- : type = 1 (control packet)
// -000 ---- : counter = 0
// ---- 0001 : command = 1 (response)
// 1000 0001 = 0x81
expected_selected = {0x81, kEmptyUpperByte, kByteWeaveVersion,
kEmptyUpperByte, kSelectedPacketSize};
EXPECT_EQ(expected_selected, packet);
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionCloseTest) {
// Reason for close spec of uWeave.
// 0x00: Close without error
// 0x01: Unknown error
// 0x02: No common version supported
// 0x03: Received packet out of sequence
// 0x80: Application error
TestConnectionCloseWithReason(ReasonForClose::CLOSE_WITHOUT_ERROR, 0x00);
TestConnectionCloseWithReason(ReasonForClose::UNKNOWN_ERROR, 0x01);
TestConnectionCloseWithReason(ReasonForClose::NO_COMMON_VERSION_SUPPORTED,
0x02);
TestConnectionCloseWithReason(ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE,
0x03);
TestConnectionCloseWithReason(ReasonForClose::APPLICATION_ERROR, 0x80);
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
EncodeDataMessageWithDefaultPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
std::string data = "abcdefghijklmnopqrstuvwxyz";
std::vector<Packet> packets = generator->EncodeDataMessage(data);
std::vector<Packet> expected(2);
// uWeave Header:
// 0--- ---- : type = 0 (data packet)
// -000 ---- : counter = 0
// ---- 1--- : first packet = true
// ---- -0-- : last packet = false
// ---- --00 : defined by uWeave to be 0
// 0000 1000 = 0x08
expected[0] = {0x08, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's'};
// uWeave Header:
// 0--- ---- : type = 0 (data packet)
// -001 ---- : counter = 1
// ---- 0--- : first packet = false
// ---- -1-- : last packet = true
// ---- --00 : defined by uWeave to be 0
// 0001 0100 = 0x14
expected[1] = {0x14, 't', 'u', 'v', 'w', 'x', 'y', 'z'};
EXPECT_EQ(expected, packets);
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
EncodeDataMessageWithSelectedPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
const uint32_t packet_size = 30;
const uint32_t residual_packet_size = 2;
std::string a(packet_size - 1, 'a');
std::string b(packet_size - 1, 'b');
std::string c(residual_packet_size - 1, 'c');
std::string data = a + b + c;
generator->SetMaxPacketSize(packet_size);
std::vector<Packet> packets = generator->EncodeDataMessage(data);
std::vector<Packet> expected(3);
expected[0].assign(packet_size, 'a');
// uWeave Header:
// 0--- ---- : type = 0 (data packet)
// -000 ---- : counter = 0
// ---- 1--- : first packet = true
// ---- -0-- : last packet = false
// ---- --00 : defined by uWeave to be 0
// 0000 1000 = 0x08
expected[0][0] = 0x08;
expected[1].assign(packet_size, 'b');
// uWeave Header:
// 0--- ---- : type = 0 (data packet)
// -001 ---- : counter = 1
// ---- 0--- : first packet = false
// ---- -0-- : last packet = false
// ---- --00 : defined by uWeave to be 0
// 0001 0000 = 0x10
expected[1][0] = 0x10;
expected[2].assign(residual_packet_size, 'c');
// uWeave Header:
// 0--- ---- : type = 0 (data packet)
// -010 ---- : counter = 2
// ---- 0--- : first packet = false
// ---- -1-- : last packet = true
// ---- --00 : defined by uWeave to be 0
// 0010 0100 = 0x24
expected[2][0] = 0x24;
EXPECT_EQ(expected, packets);
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
PacketCounterForMixedPacketTypesTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionRequest();
EXPECT_EQ(0, GetCounterFromHeader(packet[0]));
std::string data = "a";
std::vector<Packet> packets = generator->EncodeDataMessage(data);
EXPECT_EQ(1, GetCounterFromHeader(packets[0][0]));
packet = generator->CreateConnectionClose(ReasonForClose::UNKNOWN_ERROR);
EXPECT_EQ(2, GetCounterFromHeader(packet[0]));
}
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
PacketCounterWrappedAroundTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
const uint8_t kNumPackets = 100;
std::string data(kNumPackets * kByteDefaultMaxPacketSize, 'a');
std::vector<Packet> packets = generator->EncodeDataMessage(data);
std::vector<Packet> expected(kNumPackets);
const uint8_t kDataType = 0;
for (uint8_t i = 0; i < kNumPackets; ++i) {
uint8_t header = packets[i][0];
EXPECT_EQ(i % kMaxPacketCounter, GetCounterFromHeader(header));
EXPECT_EQ(kDataType, GetPacketType(header));
}
}
} // namespace weave
} // namespace cryptauth