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/load_balancer/load_balancer_encoder.h"
6 
7 #include <cstddef>
8 #include <cstdint>
9 #include <cstring>
10 #include <optional>
11 #include <queue>
12 
13 #include "absl/numeric/int128.h"
14 #include "absl/strings/string_view.h"
15 #include "absl/types/span.h"
16 #include "quiche/quic/core/crypto/quic_random.h"
17 #include "quiche/quic/core/quic_connection_id.h"
18 #include "quiche/quic/core/quic_versions.h"
19 #include "quiche/quic/load_balancer/load_balancer_config.h"
20 #include "quiche/quic/load_balancer/load_balancer_server_id.h"
21 #include "quiche/quic/platform/api/quic_expect_bug.h"
22 #include "quiche/quic/platform/api/quic_test.h"
23 #include "quiche/quic/test_tools/quic_test_utils.h"
24 
25 namespace quic {
26 
27 namespace test {
28 
29 class LoadBalancerEncoderPeer {
30  public:
SetNumNoncesLeft(LoadBalancerEncoder & encoder,uint64_t nonces_remaining)31   static void SetNumNoncesLeft(LoadBalancerEncoder &encoder,
32                                uint64_t nonces_remaining) {
33     encoder.num_nonces_left_ = absl::uint128(nonces_remaining);
34   }
35 };
36 
37 namespace {
38 
39 class TestLoadBalancerEncoderVisitor
40     : public LoadBalancerEncoderVisitorInterface {
41  public:
~TestLoadBalancerEncoderVisitor()42   ~TestLoadBalancerEncoderVisitor() override {}
43 
OnConfigAdded(const uint8_t config_id)44   void OnConfigAdded(const uint8_t config_id) override {
45     num_adds_++;
46     current_config_id_ = config_id;
47   }
48 
OnConfigChanged(const uint8_t old_config_id,const uint8_t new_config_id)49   void OnConfigChanged(const uint8_t old_config_id,
50                        const uint8_t new_config_id) override {
51     num_adds_++;
52     num_deletes_++;
53     EXPECT_EQ(old_config_id, current_config_id_);
54     current_config_id_ = new_config_id;
55   }
56 
OnConfigDeleted(const uint8_t config_id)57   void OnConfigDeleted(const uint8_t config_id) override {
58     EXPECT_EQ(config_id, current_config_id_);
59     current_config_id_.reset();
60     num_deletes_++;
61   }
62 
num_adds() const63   uint32_t num_adds() const { return num_adds_; }
num_deletes() const64   uint32_t num_deletes() const { return num_deletes_; }
65 
66  private:
67   uint32_t num_adds_ = 0, num_deletes_ = 0;
68   std::optional<uint8_t> current_config_id_ = std::optional<uint8_t>();
69 };
70 
71 // Allows the caller to specify the exact results in 64-bit chunks.
72 class TestRandom : public QuicRandom {
73  public:
RandUint64()74   uint64_t RandUint64() override {
75     if (next_values_.empty()) {
76       return base_;
77     }
78     uint64_t value = next_values_.front();
79     next_values_.pop();
80     return value;
81   }
82 
RandBytes(void * data,size_t len)83   void RandBytes(void *data, size_t len) override {
84     size_t written = 0;
85     uint8_t *ptr = static_cast<uint8_t *>(data);
86     while (written < len) {
87       uint64_t result = RandUint64();
88       size_t to_write = (len - written > sizeof(uint64_t)) ? sizeof(uint64_t)
89                                                            : (len - written);
90       memcpy(ptr + written, &result, to_write);
91       written += to_write;
92     }
93   }
94 
InsecureRandBytes(void * data,size_t len)95   void InsecureRandBytes(void *data, size_t len) override {
96     RandBytes(data, len);
97   }
98 
InsecureRandUint64()99   uint64_t InsecureRandUint64() override { return RandUint64(); }
100 
AddNextValues(uint64_t hi,uint64_t lo)101   void AddNextValues(uint64_t hi, uint64_t lo) {
102     next_values_.push(hi);
103     next_values_.push(lo);
104   }
105 
106  private:
107   std::queue<uint64_t> next_values_;
108   uint64_t base_ = 0xDEADBEEFDEADBEEF;
109 };
110 
111 class LoadBalancerEncoderTest : public QuicTest {
112  public:
113   TestRandom random_;
114 };
115 
116 // Convenience function to shorten the code. Does not check if |array| is long
117 // enough or |length| is valid for a server ID.
MakeServerId(const uint8_t array[],const uint8_t length)118 LoadBalancerServerId MakeServerId(const uint8_t array[], const uint8_t length) {
119   return LoadBalancerServerId(absl::Span<const uint8_t>(array, length));
120 }
121 
122 constexpr char kRawKey[] = {0x8f, 0x95, 0xf0, 0x92, 0x45, 0x76, 0x5f, 0x80,
123                             0x25, 0x69, 0x34, 0xe5, 0x0c, 0x66, 0x20, 0x7f};
124 constexpr absl::string_view kKey(kRawKey, kLoadBalancerKeyLen);
125 constexpr uint64_t kNonceLow = 0xe5d1c048bf0d08ee;
126 constexpr uint64_t kNonceHigh = 0x9321e7e34dde525d;
127 constexpr uint8_t kServerId[] = {0xed, 0x79, 0x3a, 0x51, 0xd4, 0x9b, 0x8f, 0x5f,
128                                  0xab, 0x65, 0xba, 0x04, 0xc3, 0x33, 0x0a};
129 
TEST_F(LoadBalancerEncoderTest,BadUnroutableLength)130 TEST_F(LoadBalancerEncoderTest, BadUnroutableLength) {
131   EXPECT_QUIC_BUG(
132       EXPECT_FALSE(
133           LoadBalancerEncoder::Create(random_, nullptr, false, 0).has_value()),
134       "Invalid unroutable_connection_id_len = 0");
135   EXPECT_QUIC_BUG(
136       EXPECT_FALSE(
137           LoadBalancerEncoder::Create(random_, nullptr, false, 21).has_value()),
138       "Invalid unroutable_connection_id_len = 21");
139 }
140 
TEST_F(LoadBalancerEncoderTest,BadServerIdLength)141 TEST_F(LoadBalancerEncoderTest, BadServerIdLength) {
142   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true);
143   ASSERT_TRUE(encoder.has_value());
144   // Expects a 3 byte server ID and got 4.
145   auto config = LoadBalancerConfig::CreateUnencrypted(1, 3, 4);
146   ASSERT_TRUE(config.has_value());
147   EXPECT_QUIC_BUG(
148       EXPECT_FALSE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 4))),
149       "Server ID length 4 does not match configured value of 3");
150   EXPECT_FALSE(encoder->IsEncoding());
151 }
152 
TEST_F(LoadBalancerEncoderTest,FailToUpdateConfigWithSameId)153 TEST_F(LoadBalancerEncoderTest, FailToUpdateConfigWithSameId) {
154   TestLoadBalancerEncoderVisitor visitor;
155   auto encoder = LoadBalancerEncoder::Create(random_, &visitor, true);
156   ASSERT_TRUE(encoder.has_value());
157   auto config = LoadBalancerConfig::CreateUnencrypted(1, 3, 4);
158   ASSERT_TRUE(config.has_value());
159   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
160   EXPECT_EQ(visitor.num_adds(), 1u);
161   EXPECT_QUIC_BUG(
162       EXPECT_FALSE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3))),
163       "Attempting to change config with same ID");
164   EXPECT_EQ(visitor.num_adds(), 1u);
165 }
166 
167 struct LoadBalancerEncoderTestCase {
168   LoadBalancerConfig config;
169   QuicConnectionId connection_id;
170   LoadBalancerServerId server_id;
171 };
172 
TEST_F(LoadBalancerEncoderTest,UnencryptedConnectionIdTestVectors)173 TEST_F(LoadBalancerEncoderTest, UnencryptedConnectionIdTestVectors) {
174   const struct LoadBalancerEncoderTestCase test_vectors[2] = {
175       {
176           *LoadBalancerConfig::CreateUnencrypted(0, 3, 4),
177           QuicConnectionId({0x07, 0xed, 0x79, 0x3a, 0x80, 0x49, 0x71, 0x8a}),
178           MakeServerId(kServerId, 3),
179       },
180       {
181           *LoadBalancerConfig::CreateUnencrypted(1, 8, 5),
182           QuicConnectionId({0x2d, 0xed, 0x79, 0x3a, 0x51, 0xd4, 0x9b, 0x8f,
183                             0x5f, 0x8e, 0x98, 0x53, 0xfe, 0x93}),
184           MakeServerId(kServerId, 8),
185       },
186   };
187   for (const auto &test : test_vectors) {
188     random_.AddNextValues(kNonceHigh, kNonceLow);
189     auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true, 8);
190     EXPECT_TRUE(encoder->UpdateConfig(test.config, test.server_id));
191     absl::uint128 nonces_left = encoder->num_nonces_left();
192     EXPECT_EQ(encoder->GenerateConnectionId(), test.connection_id);
193     EXPECT_EQ(encoder->num_nonces_left(), nonces_left - 1);
194   }
195 }
196 
197 // Follow example in draft-ietf-quic-load-balancers-19.
TEST_F(LoadBalancerEncoderTest,FollowSpecExample)198 TEST_F(LoadBalancerEncoderTest, FollowSpecExample) {
199   const uint8_t config_id = 0, server_id_len = 3, nonce_len = 4;
200   const uint8_t raw_server_id[] = {
201       0x31,
202       0x44,
203       0x1a,
204   };
205   const char raw_key[] = {
206       0xfd, 0xf7, 0x26, 0xa9, 0x89, 0x3e, 0xc0, 0x5c,
207       0x06, 0x32, 0xd3, 0x95, 0x66, 0x80, 0xba, 0xf0,
208   };
209   random_.AddNextValues(0, 0x75c2699c);
210   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true, 8);
211   ASSERT_TRUE(encoder.has_value());
212   auto config = LoadBalancerConfig::Create(config_id, server_id_len, nonce_len,
213                                            absl::string_view(raw_key));
214   ASSERT_TRUE(config.has_value());
215   EXPECT_TRUE(
216       encoder->UpdateConfig(*config, LoadBalancerServerId(raw_server_id)));
217   EXPECT_TRUE(encoder->IsEncoding());
218   const char raw_connection_id[] = {0x07, 0x67, 0x94, 0x7d,
219                                     0x29, 0xbe, 0x05, 0x4a};
220   auto expected =
221       QuicConnectionId(raw_connection_id, 1 + server_id_len + nonce_len);
222   EXPECT_EQ(encoder->GenerateConnectionId(), expected);
223 }
224 
225 // Compare test vectors from Appendix B of draft-ietf-quic-load-balancers-19.
TEST_F(LoadBalancerEncoderTest,EncoderTestVectors)226 TEST_F(LoadBalancerEncoderTest, EncoderTestVectors) {
227   // Try (1) the "standard" ConnectionId length of 8
228   // (2) server_id_len > nonce_len, so there is a fourth decryption pass
229   // (3) the single-pass encryption case
230   // (4) An even total length.
231   const LoadBalancerEncoderTestCase test_vectors[4] = {
232       {
233           *LoadBalancerConfig::Create(0, 3, 4, kKey),
234           QuicConnectionId({0x07, 0x20, 0xb1, 0xd0, 0x7b, 0x35, 0x9d, 0x3c}),
235           MakeServerId(kServerId, 3),
236       },
237       {
238           *LoadBalancerConfig::Create(1, 10, 5, kKey),
239           QuicConnectionId({0x2f, 0xcc, 0x38, 0x1b, 0xc7, 0x4c, 0xb4, 0xfb,
240                             0xad, 0x28, 0x23, 0xa3, 0xd1, 0xf8, 0xfe, 0xd2}),
241           MakeServerId(kServerId, 10),
242       },
243       {
244           *LoadBalancerConfig::Create(2, 8, 8, kKey),
245           QuicConnectionId({0x50, 0x4d, 0xd2, 0xd0, 0x5a, 0x7b, 0x0d, 0xe9,
246                             0xb2, 0xb9, 0x90, 0x7a, 0xfb, 0x5e, 0xcf, 0x8c,
247                             0xc3}),
248           MakeServerId(kServerId, 8),
249       },
250       {
251           *LoadBalancerConfig::Create(0, 9, 9, kKey),
252           QuicConnectionId({0x12, 0x57, 0x79, 0xc9, 0xcc, 0x86, 0xbe, 0xb3,
253                             0xa3, 0xa4, 0xa3, 0xca, 0x96, 0xfc, 0xe4, 0xbf,
254                             0xe0, 0xcd, 0xbc}),
255           MakeServerId(kServerId, 9),
256       },
257   };
258   for (const auto &test : test_vectors) {
259     auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true, 8);
260     ASSERT_TRUE(encoder.has_value());
261     random_.AddNextValues(kNonceHigh, kNonceLow);
262     EXPECT_TRUE(encoder->UpdateConfig(test.config, test.server_id));
263     EXPECT_EQ(encoder->GenerateConnectionId(), test.connection_id);
264   }
265 }
266 
TEST_F(LoadBalancerEncoderTest,RunOutOfNonces)267 TEST_F(LoadBalancerEncoderTest, RunOutOfNonces) {
268   const uint8_t server_id_len = 3;
269   TestLoadBalancerEncoderVisitor visitor;
270   auto encoder = LoadBalancerEncoder::Create(random_, &visitor, true, 8);
271   ASSERT_TRUE(encoder.has_value());
272   auto config = LoadBalancerConfig::Create(0, server_id_len, 4, kKey);
273   ASSERT_TRUE(config.has_value());
274   EXPECT_TRUE(
275       encoder->UpdateConfig(*config, MakeServerId(kServerId, server_id_len)));
276   EXPECT_EQ(visitor.num_adds(), 1u);
277   LoadBalancerEncoderPeer::SetNumNoncesLeft(*encoder, 2);
278   EXPECT_EQ(encoder->num_nonces_left(), 2);
279   EXPECT_EQ(encoder->GenerateConnectionId(),
280             QuicConnectionId({0x07, 0x29, 0xd8, 0xc2, 0x17, 0xce, 0x2d, 0x92}));
281   EXPECT_EQ(encoder->num_nonces_left(), 1);
282   encoder->GenerateConnectionId();
283   EXPECT_EQ(encoder->IsEncoding(), false);
284   // No retire_calls except for the initial UpdateConfig.
285   EXPECT_EQ(visitor.num_deletes(), 1u);
286 }
287 
TEST_F(LoadBalancerEncoderTest,UnroutableConnectionId)288 TEST_F(LoadBalancerEncoderTest, UnroutableConnectionId) {
289   random_.AddNextValues(0x83, kNonceHigh);
290   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, false);
291   ASSERT_TRUE(encoder.has_value());
292   EXPECT_EQ(encoder->num_nonces_left(), 0);
293   auto connection_id = encoder->GenerateConnectionId();
294   // The first byte is the config_id (0xe0) xored with (0x83 & 0x1f).
295   // The remaining bytes are random, and therefore match kNonceHigh.
296   QuicConnectionId expected({0xe3, 0x5d, 0x52, 0xde, 0x4d, 0xe3, 0xe7, 0x21});
297   EXPECT_EQ(expected, connection_id);
298 }
299 
TEST_F(LoadBalancerEncoderTest,NonDefaultUnroutableConnectionIdLength)300 TEST_F(LoadBalancerEncoderTest, NonDefaultUnroutableConnectionIdLength) {
301   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true, 9);
302   ASSERT_TRUE(encoder.has_value());
303   QuicConnectionId connection_id = encoder->GenerateConnectionId();
304   EXPECT_EQ(connection_id.length(), 9);
305 }
306 
TEST_F(LoadBalancerEncoderTest,DeleteConfigWhenNoConfigExists)307 TEST_F(LoadBalancerEncoderTest, DeleteConfigWhenNoConfigExists) {
308   TestLoadBalancerEncoderVisitor visitor;
309   auto encoder = LoadBalancerEncoder::Create(random_, &visitor, true);
310   ASSERT_TRUE(encoder.has_value());
311   encoder->DeleteConfig();
312   EXPECT_EQ(visitor.num_deletes(), 0u);
313 }
314 
TEST_F(LoadBalancerEncoderTest,AddConfig)315 TEST_F(LoadBalancerEncoderTest, AddConfig) {
316   auto config = LoadBalancerConfig::CreateUnencrypted(0, 3, 4);
317   ASSERT_TRUE(config.has_value());
318   TestLoadBalancerEncoderVisitor visitor;
319   auto encoder = LoadBalancerEncoder::Create(random_, &visitor, true);
320   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
321   EXPECT_EQ(visitor.num_adds(), 1u);
322   absl::uint128 left = encoder->num_nonces_left();
323   EXPECT_EQ(left, (0x1ull << 32));
324   EXPECT_TRUE(encoder->IsEncoding());
325   EXPECT_FALSE(encoder->IsEncrypted());
326   encoder->GenerateConnectionId();
327   EXPECT_EQ(encoder->num_nonces_left(), left - 1);
328   EXPECT_EQ(visitor.num_deletes(), 0u);
329 }
330 
TEST_F(LoadBalancerEncoderTest,UpdateConfig)331 TEST_F(LoadBalancerEncoderTest, UpdateConfig) {
332   auto config = LoadBalancerConfig::CreateUnencrypted(0, 3, 4);
333   ASSERT_TRUE(config.has_value());
334   TestLoadBalancerEncoderVisitor visitor;
335   auto encoder = LoadBalancerEncoder::Create(random_, &visitor, true);
336   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
337   config = LoadBalancerConfig::Create(1, 4, 4, kKey);
338   ASSERT_TRUE(config.has_value());
339   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 4)));
340   EXPECT_EQ(visitor.num_adds(), 2u);
341   EXPECT_EQ(visitor.num_deletes(), 1u);
342   EXPECT_TRUE(encoder->IsEncoding());
343   EXPECT_TRUE(encoder->IsEncrypted());
344 }
345 
TEST_F(LoadBalancerEncoderTest,DeleteConfig)346 TEST_F(LoadBalancerEncoderTest, DeleteConfig) {
347   auto config = LoadBalancerConfig::CreateUnencrypted(0, 3, 4);
348   ASSERT_TRUE(config.has_value());
349   TestLoadBalancerEncoderVisitor visitor;
350   auto encoder = LoadBalancerEncoder::Create(random_, &visitor, true);
351   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
352   encoder->DeleteConfig();
353   EXPECT_EQ(visitor.num_adds(), 1u);
354   EXPECT_EQ(visitor.num_deletes(), 1u);
355   EXPECT_FALSE(encoder->IsEncoding());
356   EXPECT_FALSE(encoder->IsEncrypted());
357   EXPECT_EQ(encoder->num_nonces_left(), 0);
358 }
359 
TEST_F(LoadBalancerEncoderTest,DeleteConfigNoVisitor)360 TEST_F(LoadBalancerEncoderTest, DeleteConfigNoVisitor) {
361   auto config = LoadBalancerConfig::CreateUnencrypted(0, 3, 4);
362   ASSERT_TRUE(config.has_value());
363   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true);
364   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
365   encoder->DeleteConfig();
366   EXPECT_FALSE(encoder->IsEncoding());
367   EXPECT_FALSE(encoder->IsEncrypted());
368   EXPECT_EQ(encoder->num_nonces_left(), 0);
369 }
370 
TEST_F(LoadBalancerEncoderTest,MaybeReplaceConnectionIdReturnsNoChange)371 TEST_F(LoadBalancerEncoderTest, MaybeReplaceConnectionIdReturnsNoChange) {
372   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, false);
373   ASSERT_TRUE(encoder.has_value());
374   EXPECT_EQ(encoder->MaybeReplaceConnectionId(TestConnectionId(1),
375                                               ParsedQuicVersion::Q046()),
376             std::nullopt);
377 }
378 
TEST_F(LoadBalancerEncoderTest,MaybeReplaceConnectionIdReturnsChange)379 TEST_F(LoadBalancerEncoderTest, MaybeReplaceConnectionIdReturnsChange) {
380   random_.AddNextValues(0x83, kNonceHigh);
381   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, false);
382   ASSERT_TRUE(encoder.has_value());
383   // The first byte is the config_id (0xc0) xored with (0x83 & 0x3f).
384   // The remaining bytes are random, and therefore match kNonceHigh.
385   QuicConnectionId expected({0xe3, 0x5d, 0x52, 0xde, 0x4d, 0xe3, 0xe7, 0x21});
386   EXPECT_EQ(*encoder->MaybeReplaceConnectionId(TestConnectionId(1),
387                                                ParsedQuicVersion::RFCv1()),
388             expected);
389 }
390 
TEST_F(LoadBalancerEncoderTest,GenerateNextConnectionIdReturnsNoChange)391 TEST_F(LoadBalancerEncoderTest, GenerateNextConnectionIdReturnsNoChange) {
392   auto config = LoadBalancerConfig::CreateUnencrypted(0, 3, 4);
393   ASSERT_TRUE(config.has_value());
394   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true);
395   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
396   EXPECT_EQ(encoder->GenerateNextConnectionId(TestConnectionId(1)),
397             std::nullopt);
398 }
399 
TEST_F(LoadBalancerEncoderTest,GenerateNextConnectionIdReturnsChange)400 TEST_F(LoadBalancerEncoderTest, GenerateNextConnectionIdReturnsChange) {
401   random_.AddNextValues(0x83, kNonceHigh);
402   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, false);
403   ASSERT_TRUE(encoder.has_value());
404   // The first byte is the config_id (0xc0) xored with (0x83 & 0x3f).
405   // The remaining bytes are random, and therefore match kNonceHigh.
406   QuicConnectionId expected({0xe3, 0x5d, 0x52, 0xde, 0x4d, 0xe3, 0xe7, 0x21});
407   EXPECT_EQ(*encoder->GenerateNextConnectionId(TestConnectionId(1)), expected);
408 }
409 
TEST_F(LoadBalancerEncoderTest,ConnectionIdLengthsEncoded)410 TEST_F(LoadBalancerEncoderTest, ConnectionIdLengthsEncoded) {
411   // The first byte literally encodes the length.
412   auto len_encoder = LoadBalancerEncoder::Create(random_, nullptr, true);
413   ASSERT_TRUE(len_encoder.has_value());
414   EXPECT_EQ(len_encoder->ConnectionIdLength(0xe8), 9);
415   EXPECT_EQ(len_encoder->ConnectionIdLength(0x4a), 11);
416   EXPECT_EQ(len_encoder->ConnectionIdLength(0x09), 10);
417   // The length is not self-encoded anymore.
418   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, false);
419   ASSERT_TRUE(encoder.has_value());
420   EXPECT_EQ(encoder->ConnectionIdLength(0xe8), kQuicDefaultConnectionIdLength);
421   EXPECT_EQ(encoder->ConnectionIdLength(0x4a), kQuicDefaultConnectionIdLength);
422   EXPECT_EQ(encoder->ConnectionIdLength(0x09), kQuicDefaultConnectionIdLength);
423   // Add config ID 0, so that ID now returns a different length.
424   uint8_t config_id = 0;
425   uint8_t server_id_len = 3;
426   uint8_t nonce_len = 6;
427   uint8_t config_0_len = server_id_len + nonce_len + 1;
428   auto config0 = LoadBalancerConfig::CreateUnencrypted(config_id, server_id_len,
429                                                        nonce_len);
430   ASSERT_TRUE(config0.has_value());
431   EXPECT_TRUE(
432       encoder->UpdateConfig(*config0, MakeServerId(kServerId, server_id_len)));
433   EXPECT_EQ(encoder->ConnectionIdLength(0xe8), kQuicDefaultConnectionIdLength);
434   EXPECT_EQ(encoder->ConnectionIdLength(0x4a), kQuicDefaultConnectionIdLength);
435   EXPECT_EQ(encoder->ConnectionIdLength(0x09), config_0_len);
436   // Replace config ID 0 with 1. There are probably still packets with config
437   // ID 0 arriving, so keep that length in memory.
438   config_id = 1;
439   nonce_len++;
440   uint8_t config_1_len = server_id_len + nonce_len + 1;
441   auto config1 = LoadBalancerConfig::CreateUnencrypted(config_id, server_id_len,
442                                                        nonce_len);
443   ASSERT_TRUE(config1.has_value());
444   // Old config length still there after replacement
445   EXPECT_TRUE(
446       encoder->UpdateConfig(*config1, MakeServerId(kServerId, server_id_len)));
447   EXPECT_EQ(encoder->ConnectionIdLength(0xe8), kQuicDefaultConnectionIdLength);
448   EXPECT_EQ(encoder->ConnectionIdLength(0x2a), config_1_len);
449   EXPECT_EQ(encoder->ConnectionIdLength(0x09), config_0_len);
450   // Old config length still there after delete
451   encoder->DeleteConfig();
452   EXPECT_EQ(encoder->ConnectionIdLength(0xe8), kQuicDefaultConnectionIdLength);
453   EXPECT_EQ(encoder->ConnectionIdLength(0x2a), config_1_len);
454   EXPECT_EQ(encoder->ConnectionIdLength(0x09), config_0_len);
455 }
456 
457 }  // namespace
458 
459 }  // namespace test
460 
461 }  // namespace quic
462