blob: d51b4f3389a4c45fda93a3810d0a2395e610bedd [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 <wlan/common/parse_element.h>
#include <gtest/gtest.h>
namespace wlan {
namespace common {
TEST(ParseElement, Ssid) {
const uint8_t raw_body[] = { 'f', 'o', 'o' };
std::optional<Span<const uint8_t>> ssid = ParseSsid(raw_body);
ASSERT_TRUE(ssid);
EXPECT_EQ(raw_body, ssid->data());
EXPECT_EQ(3u, ssid->size());
}
TEST(ParseElement, SsidTooLong) {
const uint8_t raw_body[33] = {};
std::optional<Span<const uint8_t>> ssid = ParseSsid(raw_body);
ASSERT_FALSE(ssid);
}
TEST(ParseElement, SupportedRates) {
const uint8_t raw_body[] = { 10, 20, 30, 40, 50, 60, 70, 80 };
std::optional<Span<const SupportedRate>> rates = ParseSupportedRates(raw_body);
ASSERT_TRUE(rates);
EXPECT_EQ(raw_body, reinterpret_cast<const uint8_t*>(rates->data()));
EXPECT_EQ(8u, rates->size());
}
TEST(ParseElement, SupportedRatesEmpty) {
std::optional<Span<const SupportedRate>> rates = ParseSupportedRates({});
ASSERT_FALSE(rates);
}
TEST(ParseElement, SupportedRatesTooLong) {
const uint8_t raw_body[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
std::optional<Span<const SupportedRate>> rates = ParseSupportedRates(raw_body);
ASSERT_FALSE(rates);
}
TEST(ParseElement, DsssParamSet) {
const uint8_t raw_body[] = { 11 };
const DsssParamSet* dsss = ParseDsssParamSet(raw_body);
ASSERT_NE(nullptr, dsss);
ASSERT_EQ(11u, dsss->current_chan);
}
TEST(ParseElement, DsssParamSetToShort) {
const DsssParamSet* dsss = ParseDsssParamSet({});
ASSERT_EQ(nullptr, dsss);
}
TEST(ParseElement, DsssParamSetToLong) {
const uint8_t raw_body[] = { 11, 12 };
const DsssParamSet* dsss = ParseDsssParamSet(raw_body);
ASSERT_EQ(nullptr, dsss);
}
TEST(ParseElement, CfParamSet) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6 };
const CfParamSet* cf = ParseCfParamSet(raw_body);
ASSERT_NE(nullptr, cf);
ASSERT_EQ(1, cf->count);
ASSERT_EQ(2, cf->period);
ASSERT_EQ(0x0403, cf->max_duration);
ASSERT_EQ(0x0605, cf->dur_remaining);
}
TEST(ParseElement, CfParamSetTooShort) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5 };
const CfParamSet* cf = ParseCfParamSet(raw_body);
ASSERT_EQ(nullptr, cf);
}
TEST(ParseElement, CfParamSetTooLong) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6, 7 };
const CfParamSet* cf = ParseCfParamSet(raw_body);
ASSERT_EQ(nullptr, cf);
}
TEST(ParseElement, Tim) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5 };
std::optional<ParsedTim> tim = ParseTim(raw_body);
ASSERT_TRUE(tim);
EXPECT_EQ(1, tim->header.dtim_count);
EXPECT_EQ(2, tim->header.dtim_period);
EXPECT_EQ(3, tim->header.bmp_ctrl.val());
EXPECT_EQ(&raw_body[3], tim->bitmap.data());
EXPECT_EQ(2u, tim->bitmap.size());
}
TEST(ParseElement, TimEmptyBitmap) {
const uint8_t raw_body[] = { 1, 2, 3 };
std::optional<ParsedTim> tim = ParseTim(raw_body);
ASSERT_FALSE(tim);
}
TEST(ParseElement, TimTooShort) {
const uint8_t raw_body[] = { 1, 2 };
std::optional<ParsedTim> tim = ParseTim(raw_body);
ASSERT_FALSE(tim);
}
TEST(ParseElement, CountryNoTriplets) {
const uint8_t raw_body[] = { 'A', 'B', 'C', 0 };
std::optional<ParsedCountry> c = ParseCountry(raw_body);
ASSERT_TRUE(c);
EXPECT_EQ('A', c->country.data[0]);
EXPECT_EQ('B', c->country.data[1]);
EXPECT_EQ('C', c->country.data[2]);
EXPECT_TRUE(c->triplets.empty());
}
TEST(ParseElement, CountrySingleTriplet) {
const uint8_t raw_body[] = { 'A', 'B', 'C', 1, 2, 3 };
std::optional<ParsedCountry> c = ParseCountry(raw_body);
ASSERT_TRUE(c);
EXPECT_EQ('A', c->country.data[0]);
EXPECT_EQ('B', c->country.data[1]);
EXPECT_EQ('C', c->country.data[2]);
EXPECT_EQ(1u, c->triplets.size());
EXPECT_EQ(1u, c->triplets[0].first_channel_number);
EXPECT_EQ(2u, c->triplets[0].number_of_channels);
EXPECT_EQ(3u, c->triplets[0].max_tx_power);
}
TEST(ParseElement, CountryTwoTriplets) {
const uint8_t raw_body[] = { 'A', 'B', 'C', 1, 2, 3, 4, 5, 6, 0 };
std::optional<ParsedCountry> c = ParseCountry(raw_body);
ASSERT_TRUE(c);
EXPECT_EQ('A', c->country.data[0]);
EXPECT_EQ('B', c->country.data[1]);
EXPECT_EQ('C', c->country.data[2]);
EXPECT_EQ(&raw_body[3], reinterpret_cast<const uint8_t*>(c->triplets.data()));
EXPECT_EQ(2u, c->triplets.size());
}
TEST(ParseElement, CountryTooShort) {
const uint8_t raw_body[] = { 'A', 'B' };
std::optional<ParsedCountry> c = ParseCountry(raw_body);
ASSERT_FALSE(c);
}
TEST(ParseElement, ExtendedSupportedRates) {
const uint8_t raw_body[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
std::optional<Span<const SupportedRate>> rates = ParseExtendedSupportedRates(raw_body);
ASSERT_TRUE(rates);
EXPECT_EQ(raw_body, reinterpret_cast<const uint8_t*>(rates->data()));
EXPECT_EQ(9u, rates->size());
}
TEST(ParseElement, ExtendedSupportedRatesEmpty) {
std::optional<Span<const SupportedRate>> rates = ParseExtendedSupportedRates({});
ASSERT_FALSE(rates);
}
TEST(ParseElement, MeshConfiguration) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6, 7 };
const MeshConfiguration* mc = ParseMeshConfiguration(raw_body);
ASSERT_NE(nullptr, mc);
EXPECT_EQ(1u, static_cast<uint8_t>(mc->active_path_sel_proto_id));
EXPECT_EQ(2u, static_cast<uint8_t>(mc->active_path_sel_metric_id));
EXPECT_EQ(3u, static_cast<uint8_t>(mc->congest_ctrl_method_id));
EXPECT_EQ(4u, static_cast<uint8_t>(mc->sync_method_id));
EXPECT_EQ(5u, static_cast<uint8_t>(mc->auth_proto_id));
EXPECT_EQ(6u, mc->mesh_formation_info.val());
EXPECT_EQ(7u, mc->mesh_capability.val());
}
TEST(ParseElement, MeshConfigurationTooShort) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6 };
const MeshConfiguration* mc = ParseMeshConfiguration(raw_body);
ASSERT_EQ(nullptr, mc);
}
TEST(ParseElement, MeshConfigurationTooLong) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const MeshConfiguration* mc = ParseMeshConfiguration(raw_body);
ASSERT_EQ(nullptr, mc);
}
TEST(ParseElement, MeshId) {
const uint8_t raw_body[] = { 'f', 'o', 'o' };
std::optional<Span<const uint8_t>> mesh_id = ParseMeshId(raw_body);
ASSERT_TRUE(mesh_id);
EXPECT_EQ(raw_body, mesh_id->data());
EXPECT_EQ(3u, mesh_id->size());
}
TEST(ParseElement, MeshIdTooLong) {
const uint8_t raw_body[33] = {};
std::optional<Span<const uint8_t>> mesh_id = ParseMeshId(raw_body);
ASSERT_FALSE(mesh_id);
}
TEST(ParseElement, QosCapability) {
const uint8_t raw_body[] = { 5 };
const QosInfo* qos = ParseQosCapability(raw_body);
ASSERT_NE(nullptr, qos);
EXPECT_EQ(5, qos->val());
}
TEST(ParseElement, QosCapabilityTooShort) {
const QosInfo* qos = ParseQosCapability({});
ASSERT_EQ(nullptr, qos);
}
TEST(ParseElement, QosCapabilityTooLong) {
const uint8_t raw_body[] = { 5, 6 };
const QosInfo* qos = ParseQosCapability(raw_body);
ASSERT_EQ(nullptr, qos);
}
TEST(ParseElement, GcrGroupAddress) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6 };
const common::MacAddr* addr = ParseGcrGroupAddress(raw_body);
ASSERT_NE(nullptr, addr);
EXPECT_EQ(1, addr->byte[0]);
EXPECT_EQ(2, addr->byte[1]);
EXPECT_EQ(3, addr->byte[2]);
EXPECT_EQ(4, addr->byte[3]);
EXPECT_EQ(5, addr->byte[4]);
EXPECT_EQ(6, addr->byte[5]);
}
TEST(ParseElement, GcrGroupAddressTooShort) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5 };
const common::MacAddr* addr = ParseGcrGroupAddress(raw_body);
ASSERT_EQ(nullptr, addr);
}
TEST(ParseElement, GcrGroupAddressTooLong) {
const uint8_t raw_body[] = { 1, 2, 3, 4, 5, 6, 7 };
const common::MacAddr* addr = ParseGcrGroupAddress(raw_body);
ASSERT_EQ(nullptr, addr);
}
TEST(ParseElement, HtCapabilities) {
const uint8_t raw_body[26] = {
0xaa, 0xbb, // ht cap info
0x55, // ampdu params
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, // mcs
0xdd, 0xee, // ext caps
0x11, 0x22, 0x33, 0x44, // beamforming
0x77 // asel
};
const HtCapabilities* h = ParseHtCapabilities(raw_body);
ASSERT_NE(nullptr, h);
EXPECT_EQ(0xbbaau, h->ht_cap_info.val());
EXPECT_EQ(0x55u, h->ampdu_params.val());
EXPECT_EQ(0x0706050403020100ul, h->mcs_set.rx_mcs_head.val());
EXPECT_EQ(0x0b0a0908u, h->mcs_set.rx_mcs_tail.val());
EXPECT_EQ(0x0f0e0d0cu, h->mcs_set.tx_mcs.val());
EXPECT_EQ(0xeeddu, h->ht_ext_cap.val());
EXPECT_EQ(0x44332211u, h->txbf_cap.val());
EXPECT_EQ(0x77u, h->asel_cap.val());
}
TEST(ParseElement, HtCapabilitiesTooShort) {
const uint8_t raw_body[25] = {};
const HtCapabilities* h = ParseHtCapabilities(raw_body);
ASSERT_EQ(nullptr, h);
}
TEST(ParseElement, HtCapabilitiesTooLong) {
const uint8_t raw_body[27] = {};
const HtCapabilities* h = ParseHtCapabilities(raw_body);
ASSERT_EQ(nullptr, h);
}
TEST(ParseElement, HtOperation) {
const uint8_t raw_body[22] = { 36, 0x11, 0x22, 0x33, 0x44, 0x55,
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
const HtOperation* h = ParseHtOperation(raw_body);
ASSERT_NE(nullptr, h);
EXPECT_EQ(36, h->primary_chan);
EXPECT_EQ(0x44332211u, h->head.val());
EXPECT_EQ(0x55u, h->tail.val());
EXPECT_EQ(0x0706050403020100ul, h->basic_mcs_set.rx_mcs_head.val());
EXPECT_EQ(0x0b0a0908u, h->basic_mcs_set.rx_mcs_tail.val());
EXPECT_EQ(0x0f0e0d0cu, h->basic_mcs_set.tx_mcs.val());
}
TEST(ParseElement, HtOperationTooShort) {
const uint8_t raw_body[21] = {};
const HtOperation* h = ParseHtOperation(raw_body);
ASSERT_EQ(nullptr, h);
}
TEST(ParseElement, HtOperationTooLong) {
const uint8_t raw_body[23] = {};
const HtOperation* h = ParseHtOperation(raw_body);
ASSERT_EQ(nullptr, h);
}
TEST(ParseElement, VhtCapabilities) {
const uint8_t raw_body[12] = { 0xaa, 0xbb, 0xcc, 0xdd,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
const VhtCapabilities* v = ParseVhtCapabilities(raw_body);
ASSERT_NE(nullptr, v);
EXPECT_EQ(0xddccbbaau, v->vht_cap_info.val());
EXPECT_EQ(0x8877665544332211ul, v->vht_mcs_nss.val());
}
TEST(ParseElement, VhtCapabilitiesTooShort) {
const uint8_t raw_body[11] = {};
const VhtCapabilities* v = ParseVhtCapabilities(raw_body);
ASSERT_EQ(nullptr, v);
}
TEST(ParseElement, VhtCapabilitiesTooLong) {
const uint8_t raw_body[13] = {};
const VhtCapabilities* v = ParseVhtCapabilities(raw_body);
ASSERT_EQ(nullptr, v);
}
TEST(ParseElement, VhtOperation) {
const uint8_t raw_body[5] = { 1, 155, 42, 0x33, 0x55 };
const VhtOperation* v = ParseVhtOperation(raw_body);
ASSERT_NE(nullptr, v);
EXPECT_EQ(1u, v->vht_cbw);
EXPECT_EQ(155u, v->center_freq_seg0);
EXPECT_EQ(42u, v->center_freq_seg1);
EXPECT_EQ(0x5533, v->basic_mcs.val());
}
TEST(ParseElement, VhtOperationTooShort) {
const uint8_t raw_body[4] = { 1, 155, 42, 0x33 };
const VhtOperation* v = ParseVhtOperation(raw_body);
ASSERT_EQ(nullptr, v);
}
TEST(ParseElement, VhtOperationTooLong) {
const uint8_t raw_body[6] = { 1, 155, 42, 0x33, 0x44, 0x55 };
const VhtOperation* v = ParseVhtOperation(raw_body);
ASSERT_EQ(nullptr, v);
}
TEST(ParseElement, MpmOpenBad) {
{
const uint8_t too_short[3] = { 0x11, 0x22, 0x33 };
EXPECT_FALSE(ParseMpmOpen(too_short));
}
{
const uint8_t weird_length[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
EXPECT_FALSE(ParseMpmOpen(weird_length));
}
{
const uint8_t too_long[21] = {};
EXPECT_FALSE(ParseMpmOpen(too_long));
}
}
TEST(ParseElement, MpmOpenGoodNoPmk) {
const uint8_t data[] = { 0x11, 0x22, 0x33, 0x44 };
auto mpm = ParseMpmOpen(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(mpm->pmk, nullptr);
}
TEST(ParseElement, MpmOpenGoodWithPmk) {
const uint8_t data[20] = {
0x11, 0x22, 0x33, 0x44,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
auto mpm = ParseMpmOpen(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(static_cast<const void*>(mpm->pmk), data + 4);
}
TEST(ParseElement, MpmConfirmBad) {
{
const uint8_t too_short[] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
EXPECT_FALSE(ParseMpmConfirm(too_short));
}
{
const uint8_t weird_length[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
EXPECT_FALSE(ParseMpmConfirm(weird_length));
}
{
const uint8_t too_long[23] = {};
EXPECT_FALSE(ParseMpmConfirm(too_long));
}
}
TEST(ParseElement, MpmConfirmGoodNoPmk) {
const uint8_t data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
auto mpm = ParseMpmConfirm(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(static_cast<uint16_t>(mpm->peer_link_id), 0x6655u);
EXPECT_EQ(mpm->pmk, nullptr);
}
TEST(ParseElement, MpmConfirmGoodWithPmk) {
const uint8_t data[22] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
auto mpm = ParseMpmConfirm(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(static_cast<uint16_t>(mpm->peer_link_id), 0x6655u);
EXPECT_EQ(static_cast<const void*>(mpm->pmk), data + 6);
}
TEST(ParseElement, MpmCloseBad) {
{
const uint8_t too_short[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
EXPECT_FALSE(ParseMpmClose(too_short));
}
{
const uint8_t weird_length[7] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
EXPECT_FALSE(ParseMpmClose(weird_length));
}
{
const uint8_t weird_length[9] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 };
EXPECT_FALSE(ParseMpmClose(weird_length));
}
{
const uint8_t too_long[25] = {};
EXPECT_FALSE(ParseMpmClose(too_long));
}
}
TEST(ParseElement, MpmCloseGoodNoLinkIdNoPmk) {
const uint8_t data[6] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
auto mpm = ParseMpmClose(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(mpm->peer_link_id, std::optional<uint16_t>{});
EXPECT_EQ(mpm->reason_code, 0x6655u);
EXPECT_EQ(mpm->pmk, nullptr);
}
TEST(ParseElement, MpmCloseGoodWithLinkIdNoPmk) {
const uint8_t data[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
auto mpm = ParseMpmClose(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(mpm->peer_link_id, std::optional<uint16_t>{ 0x6655u });
EXPECT_EQ(mpm->reason_code, 0x8877u);
EXPECT_EQ(mpm->pmk, nullptr);
}
TEST(ParseElement, MpmCloseGoodNoLinkIdWithPmk) {
const uint8_t data[22] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
auto mpm = ParseMpmClose(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(mpm->peer_link_id, std::optional<uint16_t>{});
EXPECT_EQ(mpm->reason_code, 0x6655u);
EXPECT_EQ(static_cast<const void*>(mpm->pmk), data + 6);
}
TEST(ParseElement, MpmCloseGoodWithLinkIdWithPmk) {
const uint8_t data[24] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
auto mpm = ParseMpmClose(data);
ASSERT_TRUE(mpm);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.protocol), 0x2211u);
EXPECT_EQ(static_cast<uint16_t>(mpm->header.local_link_id), 0x4433u);
EXPECT_EQ(mpm->peer_link_id, std::optional<uint16_t>{ 0x6655u });
EXPECT_EQ(mpm->reason_code, 0x8877u);
EXPECT_EQ(static_cast<const void*>(mpm->pmk), data + 8);
}
TEST(ParseElement, PreqMinimal) {
// clang-format off
const uint8_t data[17 + 9] = {
0x00, // flags
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, 0x11, // originator hwmp seqno
0x18, 0x19, 0x1a, 0x1b, // lifetime
0x1c, 0x1d, 0x1e, 0x1f, // metric
// Target count. Having no targets probably doesn't make sense,
// but we test this code path anyway.
0,
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_TRUE(preq);
EXPECT_EQ(data, reinterpret_cast<const uint8_t*>(preq->header));
EXPECT_EQ(0x02u, preq->header->hop_count);
EXPECT_EQ(nullptr, preq->originator_external_addr);
EXPECT_EQ(0x1b1a1918u, preq->middle->lifetime);
EXPECT_EQ(0u, preq->per_target.size());
}
TEST(ParseElement, PreqFull) {
// clang-format off
const uint8_t data[17 + 9 + 6 + 2*11] = {
0x40, // flags: address extension = true
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, 0x11, // originator hwmp seqno
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, // originator external address
0x18, 0x19, 0x1a, 0x1b, // lifetime
0x1c, 0x1d, 0x1e, 0x1f, // metric
2, // target count
// Target 1
0x00, // target flags
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // target address
0xa1, 0xa2, 0xa3, 0xa4, // target hwmp seqno
// Target 2
0x00, // target flags
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, // target address
0xb1, 0xb2, 0xb3, 0xb4, // target hwmp seqno
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_TRUE(preq);
EXPECT_EQ(data, reinterpret_cast<const uint8_t*>(preq->header));
EXPECT_EQ(0x02u, preq->header->hop_count);
ASSERT_NE(nullptr, preq->originator_external_addr);
EXPECT_EQ(MacAddr("16:17:18:19:1a:1b"), *preq->originator_external_addr);
EXPECT_EQ(0x1b1a1918u, preq->middle->lifetime);
ASSERT_EQ(2u, preq->per_target.size());
ASSERT_EQ(MacAddr("bb:bb:bb:bb:bb:bb"), preq->per_target[1].target_addr);
}
TEST(ParseElement, PreqTooLong) {
// clang-format off
const uint8_t data[17 + 9 + 1] = {
0x00, // flags
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, 0x11, // originator hwmp seqno
0x18, 0x19, 0x1a, 0x1b, // lifetime
0x1c, 0x1d, 0x1e, 0x1f, // metric
0, // target count
1 // extra byte
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_FALSE(preq);
}
TEST(ParseElement, PreqTooShort_Header) {
// clang-format off
const uint8_t data[17 - 1] = {
0x00, // flags
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, // one byte missing from originator hwmp seqno
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_FALSE(preq);
}
TEST(ParseElement, PreqTooShort_OrigExtAddr) {
// clang-format off
const uint8_t data[17 + 6 - 1] = {
0x40, // flags: address extension = true
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, 0x11, // originator hwmp seqno
0x16, 0x17, 0x18, 0x19, 0x1a, // one byte missing from originator external address
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_FALSE(preq);
}
TEST(ParseElement, PreqTooShort_Middle) {
// clang-format off
const uint8_t data[17 + 9 - 1] = {
0x00, // flags
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, 0x11, // originator hwmp seqno
0x18, 0x19, 0x1a, 0x1b, // lifetime
0x1c, 0x1d, 0x1e, 0x1f, // metric
// Target count missing
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_FALSE(preq);
}
TEST(ParseElement, PreqTooShort_PerTarget) {
// clang-format off
const uint8_t data[26 + 6 + 2*11 - 1] = {
0x40, // flags: address extension = true
0x02, // hop count
0x03, // element ttl
0x04, 0x05, 0x06, 0x07, // path discovery ID
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // originator addr
0x0e, 0x0f, 0x10, 0x11, // originator hwmp seqno
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, // originator external address
0x18, 0x19, 0x1a, 0x1b, // lifetime
0x1c, 0x1d, 0x1e, 0x1f, // metric
2, // target count
// Target 1
0x00, // target flags
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // target address
0xa1, 0xa2, 0xa3, 0xa4, // target hwmp seqno
// Target 2
0x00, // target flags
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, // target address
0xb1, 0xb2, 0xb3, // one byte missing from target hwmp seqno
};
// clang-format on
auto preq = ParsePreq(data);
ASSERT_FALSE(preq);
}
TEST(ParseElement, PrepNoExtAddr) {
// clang-format off
const uint8_t data[] = {
0x00, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x0d, 0x0e, 0x0f, 0x10, // lifetime
0x11, 0x12, 0x13, 0x14, // metric
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // originator addr
0x1b, 0x1c, 0x1d, 0x1e, // originator hwmp seqno
};
// clang-format on
auto prep = ParsePrep(data);
ASSERT_TRUE(prep);
EXPECT_EQ(data, reinterpret_cast<const uint8_t*>(prep->header));
EXPECT_EQ(0x01u, prep->header->hop_count);
EXPECT_EQ(nullptr, prep->target_external_addr);
EXPECT_EQ(MacAddr("15:16:17:18:19:1a"), prep->tail->originator_addr);
}
TEST(ParseElement, PrepWithExtAddr) {
// clang-format off
const uint8_t data[] = {
0x40, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x44, 0x55, 0x66, 0x77, 0x88, 0x99, // target external addr
0x0d, 0x0e, 0x0f, 0x10, // lifetime
0x11, 0x12, 0x13, 0x14, // metric
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // originator addr
0x1b, 0x1c, 0x1d, 0x1e, // originator hwmp seqno
};
// clang-format on
auto prep = ParsePrep(data);
ASSERT_TRUE(prep);
EXPECT_EQ(data, reinterpret_cast<const uint8_t*>(prep->header));
EXPECT_EQ(0x01u, prep->header->hop_count);
ASSERT_NE(nullptr, prep->target_external_addr);
EXPECT_EQ(common::MacAddr("44:55:66:77:88:99"), *prep->target_external_addr);
EXPECT_EQ(MacAddr("15:16:17:18:19:1a"), prep->tail->originator_addr);
}
TEST(ParseElement, PrepTooShort_Header) {
// clang-format off
const uint8_t data[] = {
0x00, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, // one byte missing from target hwmp seqno
};
// clang-format on
auto prep = ParsePrep(data);
ASSERT_FALSE(prep);
}
TEST(ParseElement, PrepTooShort_Tail) {
// clang-format off
const uint8_t data[] = {
0x00, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x0d, 0x0e, 0x0f, 0x10, // lifetime
0x11, 0x12, 0x13, 0x14, // metric
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // originator addr
0x1b, 0x1c, 0x1d, // one byte missing from originator hwmp seqno
};
// clang-format on
auto prep = ParsePrep(data);
ASSERT_FALSE(prep);
}
TEST(ParseElement, PrepTooShort_ExtAddr) {
// clang-format off
const uint8_t data[] = {
0x40, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x44, 0x55, 0x66, 0x77, 0x88, // one byte missing from target external addr
};
// clang-format on
auto prep = ParsePrep(data);
ASSERT_FALSE(prep);
}
TEST(ParseElement, PrepTooLong) {
// clang-format off
const uint8_t data[] = {
0x00, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x0d, 0x0e, 0x0f, 0x10, // lifetime
0x11, 0x12, 0x13, 0x14, // metric
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // originator addr
0x1b, 0x1c, 0x1d, 0x1e, // originator hwmp seqno
0, // extra byte
};
// clang-format on
auto prep = ParsePrep(data);
ASSERT_FALSE(prep);
}
} // namespace common
} // namespace wlan