1 // Copyright (c) 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/deterministic_connection_id_generator.h"
6
7 #include <optional>
8
9 #include "quiche/quic/platform/api/quic_test.h"
10 #include "quiche/quic/test_tools/quic_test_utils.h"
11
12 namespace quic {
13 namespace test {
14
15 struct TestParams {
TestParamsquic::test::TestParams16 TestParams(int connection_id_length)
17 : connection_id_length_(connection_id_length) {}
TestParamsquic::test::TestParams18 TestParams() : TestParams(kQuicDefaultConnectionIdLength) {}
19
operator <<(std::ostream & os,const TestParams & p)20 friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
21 os << "{ connection ID length: " << p.connection_id_length_ << " }";
22 return os;
23 }
24
25 int connection_id_length_;
26 };
27
28 // Constructs various test permutations.
GetTestParams()29 std::vector<struct TestParams> GetTestParams() {
30 std::vector<struct TestParams> params;
31 std::vector<int> connection_id_lengths{7, 8, 9, 16, 20};
32 for (int connection_id_length : connection_id_lengths) {
33 params.push_back(TestParams(connection_id_length));
34 }
35 return params;
36 }
37
38 class DeterministicConnectionIdGeneratorTest
39 : public QuicTestWithParam<TestParams> {
40 public:
DeterministicConnectionIdGeneratorTest()41 DeterministicConnectionIdGeneratorTest()
42 : connection_id_length_(GetParam().connection_id_length_),
43 generator_(DeterministicConnectionIdGenerator(connection_id_length_)),
44 version_(ParsedQuicVersion::RFCv1()) {}
45
46 protected:
47 int connection_id_length_;
48 DeterministicConnectionIdGenerator generator_;
49 ParsedQuicVersion version_;
50 };
51
52 INSTANTIATE_TEST_SUITE_P(DeterministicConnectionIdGeneratorTests,
53 DeterministicConnectionIdGeneratorTest,
54 ::testing::ValuesIn(GetTestParams()));
55
TEST_P(DeterministicConnectionIdGeneratorTest,NextConnectionIdIsDeterministic)56 TEST_P(DeterministicConnectionIdGeneratorTest,
57 NextConnectionIdIsDeterministic) {
58 // Verify that two equal connection IDs get the same replacement.
59 QuicConnectionId connection_id64a = TestConnectionId(33);
60 QuicConnectionId connection_id64b = TestConnectionId(33);
61 EXPECT_EQ(connection_id64a, connection_id64b);
62 EXPECT_EQ(*generator_.GenerateNextConnectionId(connection_id64a),
63 *generator_.GenerateNextConnectionId(connection_id64b));
64 QuicConnectionId connection_id72a = TestConnectionIdNineBytesLong(42);
65 QuicConnectionId connection_id72b = TestConnectionIdNineBytesLong(42);
66 EXPECT_EQ(connection_id72a, connection_id72b);
67 EXPECT_EQ(*generator_.GenerateNextConnectionId(connection_id72a),
68 *generator_.GenerateNextConnectionId(connection_id72b));
69 }
70
TEST_P(DeterministicConnectionIdGeneratorTest,NextConnectionIdLengthIsCorrect)71 TEST_P(DeterministicConnectionIdGeneratorTest,
72 NextConnectionIdLengthIsCorrect) {
73 // Verify that all generated IDs are of the correct length.
74 const char connection_id_bytes[255] = {};
75 for (uint8_t i = 0; i < sizeof(connection_id_bytes) - 1; ++i) {
76 QuicConnectionId connection_id(connection_id_bytes, i);
77 absl::optional<QuicConnectionId> replacement_connection_id =
78 generator_.GenerateNextConnectionId(connection_id);
79 ASSERT_TRUE(replacement_connection_id.has_value());
80 EXPECT_EQ(connection_id_length_, replacement_connection_id->length());
81 }
82 }
83
TEST_P(DeterministicConnectionIdGeneratorTest,NextConnectionIdHasEntropy)84 TEST_P(DeterministicConnectionIdGeneratorTest, NextConnectionIdHasEntropy) {
85 // Make sure all these test connection IDs have different replacements.
86 for (uint64_t i = 0; i < 256; ++i) {
87 QuicConnectionId connection_id_i = TestConnectionId(i);
88 absl::optional<QuicConnectionId> new_i =
89 generator_.GenerateNextConnectionId(connection_id_i);
90 ASSERT_TRUE(new_i.has_value());
91 EXPECT_NE(connection_id_i, *new_i);
92 for (uint64_t j = i + 1; j <= 256; ++j) {
93 QuicConnectionId connection_id_j = TestConnectionId(j);
94 EXPECT_NE(connection_id_i, connection_id_j);
95 absl::optional<QuicConnectionId> new_j =
96 generator_.GenerateNextConnectionId(connection_id_j);
97 ASSERT_TRUE(new_j.has_value());
98 EXPECT_NE(*new_i, *new_j);
99 }
100 }
101 }
102
TEST_P(DeterministicConnectionIdGeneratorTest,OnlyReplaceConnectionIdWithWrongLength)103 TEST_P(DeterministicConnectionIdGeneratorTest,
104 OnlyReplaceConnectionIdWithWrongLength) {
105 const char connection_id_input[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
106 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
107 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14};
108 for (int i = 0; i < kQuicMaxConnectionIdWithLengthPrefixLength; i++) {
109 QuicConnectionId input = QuicConnectionId(connection_id_input, i);
110 absl::optional<QuicConnectionId> output =
111 generator_.MaybeReplaceConnectionId(input, version_);
112 if (i == connection_id_length_) {
113 EXPECT_FALSE(output.has_value());
114 } else {
115 ASSERT_TRUE(output.has_value());
116 EXPECT_EQ(*output, generator_.GenerateNextConnectionId(input));
117 }
118 }
119 }
120
TEST_P(DeterministicConnectionIdGeneratorTest,ReturnLength)121 TEST_P(DeterministicConnectionIdGeneratorTest, ReturnLength) {
122 EXPECT_EQ(generator_.ConnectionIdLength(0x01), connection_id_length_);
123 }
124
125 } // namespace test
126 } // namespace quic
127