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