blob: d59fd4ec488a833ed598995972f91956cd5fe340 [file] [log] [blame]
/*
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "net/dcsctp/packet/chunk_validators.h"
#include <utility>
#include "rtc_base/gunit.h"
#include "test/gmock.h"
namespace dcsctp {
namespace {
using ::testing::ElementsAre;
using ::testing::IsEmpty;
TEST(ChunkValidatorsTest, NoGapAckBlocksAreValid) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
/*gap_ack_blocks=*/{}, {});
EXPECT_TRUE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(), IsEmpty());
}
TEST(ChunkValidatorsTest, OneValidAckBlock) {
SackChunk sack(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(2, 3)}, {});
EXPECT_TRUE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(2, 3)));
}
TEST(ChunkValidatorsTest, TwoValidAckBlocks) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(5, 6)},
{});
EXPECT_TRUE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(
clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(5, 6)));
}
TEST(ChunkValidatorsTest, OneInvalidAckBlock) {
SackChunk sack(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(1, 2)}, {});
EXPECT_FALSE(ChunkValidators::Validate(sack));
// It's not strictly valid, but due to the renegable nature of gap ack blocks,
// the cum_ack_tsn can't simply be moved.
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(1, 2)));
}
TEST(ChunkValidatorsTest, RemovesInvalidGapAckBlockFromSack) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(6, 4)},
{});
EXPECT_FALSE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(2, 3)));
}
TEST(ChunkValidatorsTest, SortsGapAckBlocksInOrder) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(6, 7), SackChunk::GapAckBlock(3, 4)},
{});
EXPECT_FALSE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(
clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(6, 7)));
}
TEST(ChunkValidatorsTest, MergesAdjacentBlocks) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(5, 6)},
{});
EXPECT_FALSE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(3, 6)));
}
TEST(ChunkValidatorsTest, MergesOverlappingByOne) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(4, 5)},
{});
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_FALSE(ChunkValidators::Validate(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(3, 5)));
}
TEST(ChunkValidatorsTest, MergesOverlappingByMore) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(3, 10), SackChunk::GapAckBlock(4, 5)},
{});
EXPECT_FALSE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(3, 10)));
}
TEST(ChunkValidatorsTest, MergesBlocksStartingWithSameStartOffset) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(3, 7), SackChunk::GapAckBlock(3, 5),
SackChunk::GapAckBlock(3, 9)},
{});
EXPECT_FALSE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(3, 9)));
}
TEST(ChunkValidatorsTest, MergesBlocksPartiallyOverlapping) {
SackChunk sack(TSN(123), /*a_rwnd=*/456,
{SackChunk::GapAckBlock(3, 7), SackChunk::GapAckBlock(5, 9)},
{});
EXPECT_FALSE(ChunkValidators::Validate(sack));
SackChunk clean = ChunkValidators::Clean(std::move(sack));
EXPECT_THAT(clean.gap_ack_blocks(),
ElementsAre(SackChunk::GapAckBlock(3, 9)));
}
} // namespace
} // namespace dcsctp