blob: d59fd4ec488a833ed598995972f91956cd5fe340 [file] [log] [blame]
Victor Boivie0b0afaa2021-04-11 21:35:441/*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#include "net/dcsctp/packet/chunk_validators.h"
11
12#include <utility>
13
14#include "rtc_base/gunit.h"
15#include "test/gmock.h"
16
17namespace dcsctp {
18namespace {
19using ::testing::ElementsAre;
20using ::testing::IsEmpty;
21
22TEST(ChunkValidatorsTest, NoGapAckBlocksAreValid) {
23 SackChunk sack(TSN(123), /*a_rwnd=*/456,
24 /*gap_ack_blocks=*/{}, {});
25
26 EXPECT_TRUE(ChunkValidators::Validate(sack));
27
28 SackChunk clean = ChunkValidators::Clean(std::move(sack));
29 EXPECT_THAT(clean.gap_ack_blocks(), IsEmpty());
30}
31
32TEST(ChunkValidatorsTest, OneValidAckBlock) {
33 SackChunk sack(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(2, 3)}, {});
34
35 EXPECT_TRUE(ChunkValidators::Validate(sack));
36
37 SackChunk clean = ChunkValidators::Clean(std::move(sack));
38 EXPECT_THAT(clean.gap_ack_blocks(),
39 ElementsAre(SackChunk::GapAckBlock(2, 3)));
40}
41
42TEST(ChunkValidatorsTest, TwoValidAckBlocks) {
43 SackChunk sack(TSN(123), /*a_rwnd=*/456,
44 {SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(5, 6)},
45 {});
46
47 EXPECT_TRUE(ChunkValidators::Validate(sack));
48
49 SackChunk clean = ChunkValidators::Clean(std::move(sack));
50 EXPECT_THAT(
51 clean.gap_ack_blocks(),
52 ElementsAre(SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(5, 6)));
53}
54
55TEST(ChunkValidatorsTest, OneInvalidAckBlock) {
56 SackChunk sack(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(1, 2)}, {});
57
58 EXPECT_FALSE(ChunkValidators::Validate(sack));
59
60 // It's not strictly valid, but due to the renegable nature of gap ack blocks,
61 // the cum_ack_tsn can't simply be moved.
62 SackChunk clean = ChunkValidators::Clean(std::move(sack));
63 EXPECT_THAT(clean.gap_ack_blocks(),
64 ElementsAre(SackChunk::GapAckBlock(1, 2)));
65}
66
67TEST(ChunkValidatorsTest, RemovesInvalidGapAckBlockFromSack) {
68 SackChunk sack(TSN(123), /*a_rwnd=*/456,
69 {SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(6, 4)},
70 {});
71
72 EXPECT_FALSE(ChunkValidators::Validate(sack));
73
74 SackChunk clean = ChunkValidators::Clean(std::move(sack));
75
76 EXPECT_THAT(clean.gap_ack_blocks(),
77 ElementsAre(SackChunk::GapAckBlock(2, 3)));
78}
79
80TEST(ChunkValidatorsTest, SortsGapAckBlocksInOrder) {
81 SackChunk sack(TSN(123), /*a_rwnd=*/456,
82 {SackChunk::GapAckBlock(6, 7), SackChunk::GapAckBlock(3, 4)},
83 {});
84
85 EXPECT_FALSE(ChunkValidators::Validate(sack));
86
87 SackChunk clean = ChunkValidators::Clean(std::move(sack));
88
89 EXPECT_THAT(
90 clean.gap_ack_blocks(),
91 ElementsAre(SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(6, 7)));
92}
93
94TEST(ChunkValidatorsTest, MergesAdjacentBlocks) {
95 SackChunk sack(TSN(123), /*a_rwnd=*/456,
96 {SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(5, 6)},
97 {});
98
99 EXPECT_FALSE(ChunkValidators::Validate(sack));
100
101 SackChunk clean = ChunkValidators::Clean(std::move(sack));
102
103 EXPECT_THAT(clean.gap_ack_blocks(),
104 ElementsAre(SackChunk::GapAckBlock(3, 6)));
105}
106
107TEST(ChunkValidatorsTest, MergesOverlappingByOne) {
108 SackChunk sack(TSN(123), /*a_rwnd=*/456,
109 {SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(4, 5)},
110 {});
111
112 SackChunk clean = ChunkValidators::Clean(std::move(sack));
113
114 EXPECT_FALSE(ChunkValidators::Validate(sack));
115
116 EXPECT_THAT(clean.gap_ack_blocks(),
117 ElementsAre(SackChunk::GapAckBlock(3, 5)));
118}
119
120TEST(ChunkValidatorsTest, MergesOverlappingByMore) {
121 SackChunk sack(TSN(123), /*a_rwnd=*/456,
122 {SackChunk::GapAckBlock(3, 10), SackChunk::GapAckBlock(4, 5)},
123 {});
124
125 EXPECT_FALSE(ChunkValidators::Validate(sack));
126
127 SackChunk clean = ChunkValidators::Clean(std::move(sack));
128
129 EXPECT_THAT(clean.gap_ack_blocks(),
130 ElementsAre(SackChunk::GapAckBlock(3, 10)));
131}
132
133TEST(ChunkValidatorsTest, MergesBlocksStartingWithSameStartOffset) {
134 SackChunk sack(TSN(123), /*a_rwnd=*/456,
135 {SackChunk::GapAckBlock(3, 7), SackChunk::GapAckBlock(3, 5),
136 SackChunk::GapAckBlock(3, 9)},
137 {});
138
139 EXPECT_FALSE(ChunkValidators::Validate(sack));
140
141 SackChunk clean = ChunkValidators::Clean(std::move(sack));
142
143 EXPECT_THAT(clean.gap_ack_blocks(),
144 ElementsAre(SackChunk::GapAckBlock(3, 9)));
145}
146
147TEST(ChunkValidatorsTest, MergesBlocksPartiallyOverlapping) {
148 SackChunk sack(TSN(123), /*a_rwnd=*/456,
149 {SackChunk::GapAckBlock(3, 7), SackChunk::GapAckBlock(5, 9)},
150 {});
151
152 EXPECT_FALSE(ChunkValidators::Validate(sack));
153
154 SackChunk clean = ChunkValidators::Clean(std::move(sack));
155
156 EXPECT_THAT(clean.gap_ack_blocks(),
157 ElementsAre(SackChunk::GapAckBlock(3, 9)));
158}
159
160} // namespace
161} // namespace dcsctp