/* * 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 #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