Reduce QUIC load balancer copies by passing the result as an argument.
Code is not in production.
Performance numbers (Unenc/3 pass/1 pass, ns)
Tip of tree: 20.2 / 103 / 33.2
This CL: 21.4 / 101/ 26.3
PiperOrigin-RevId: 599890068
diff --git a/quiche/quic/load_balancer/load_balancer_config.cc b/quiche/quic/load_balancer/load_balancer_config.cc
index 2373e6c..b4b989e 100644
--- a/quiche/quic/load_balancer/load_balancer_config.cc
+++ b/quiche/quic/load_balancer/load_balancer_config.cc
@@ -89,10 +89,13 @@
: std::optional<LoadBalancerConfig>();
}
-LoadBalancerServerId LoadBalancerConfig::FourPassDecrypt(
- absl::Span<const uint8_t> ciphertext) const {
+bool LoadBalancerConfig::FourPassDecrypt(
+ absl::Span<const uint8_t> ciphertext,
+ LoadBalancerServerId& server_id) const {
+ QUIC_BUG_IF(quic_bug_599862571_02, ciphertext.size() < plaintext_len())
+ << "Called FourPassDecrypt with a short Connection ID";
if (!key_.has_value()) {
- return LoadBalancerServerId();
+ return false;
}
// Do 3 or 4 passes. Only 3 are necessary if the server_id is short enough
// to fit in the first half of the connection ID (the decoder doesn't need
@@ -112,18 +115,22 @@
if (server_id_len_ < half_len ||
(server_id_len_ == half_len && !is_length_odd)) {
// There is no half-byte to handle
- return LoadBalancerServerId(absl::Span<uint8_t>(&left[2], server_id_len_));
+ memcpy(server_id.mutable_data(), &left[2], server_id_len_);
+ return true;
}
if (is_length_odd) {
right[2] |= left[half_len-- + 1]; // Combine the halves of the odd byte.
}
- return LoadBalancerServerId(
- absl::Span<uint8_t>(&left[2], half_len),
- absl::Span<uint8_t>(&right[2], server_id_len_ - half_len));
+ memcpy(server_id.mutable_data(), &left[2], half_len);
+ memcpy(server_id.mutable_data() + half_len, &right[2],
+ server_id_len_ - half_len);
+ return true;
}
QuicConnectionId LoadBalancerConfig::FourPassEncrypt(
absl::Span<uint8_t> plaintext) const {
+ QUIC_BUG_IF(quic_bug_599862571_03, plaintext.size() < total_len())
+ << "Called FourPassEncrypt with a short Connection ID";
if (!key_.has_value()) {
return QuicConnectionId();
}
diff --git a/quiche/quic/load_balancer/load_balancer_config.h b/quiche/quic/load_balancer/load_balancer_config.h
index 9ad396c..cb4521c 100644
--- a/quiche/quic/load_balancer/load_balancer_config.h
+++ b/quiche/quic/load_balancer/load_balancer_config.h
@@ -31,8 +31,6 @@
// find the maximum number of configs.
inline constexpr uint8_t kNumLoadBalancerConfigs = (1 << kConfigIdBits) - 1;
inline constexpr uint8_t kLoadBalancerKeyLen = 16;
-// Regardless of key length, the AES block size is always 16 Bytes.
-inline constexpr uint8_t kLoadBalancerBlockSize = 16;
// The spec says nonces can be 18 bytes, but 16 lets it be a uint128.
inline constexpr uint8_t kLoadBalancerMaxNonceLen = 16;
inline constexpr uint8_t kLoadBalancerMinNonceLen = 4;
@@ -64,8 +62,13 @@
// Returns an invalid Server ID if ciphertext is too small, or needed keys are
// missing. |ciphertext| contains the full connection ID minus the first byte.
- LoadBalancerServerId FourPassDecrypt(
- absl::Span<const uint8_t> ciphertext) const;
+ //
+ // IMPORTANT: The decoder data path is likely the most performance-sensitive
+ // part of the load balancer design, and this code has been carefully
+ // optimized for performance. Please do not make changes without running the
+ // benchmark tests to ensure there is no regression.
+ bool FourPassDecrypt(absl::Span<const uint8_t> ciphertext,
+ LoadBalancerServerId& server_id) const;
// Returns an empty connection ID if the plaintext is too small, or needed
// keys are missing. |plaintext| contains the full unencrypted connection ID,
// including the first byte.
diff --git a/quiche/quic/load_balancer/load_balancer_config_test.cc b/quiche/quic/load_balancer/load_balancer_config_test.cc
index fd40412..0e1b2f6 100644
--- a/quiche/quic/load_balancer/load_balancer_config_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_config_test.cc
@@ -193,15 +193,16 @@
// LoadBalancerDecoderTest, respectively.
TEST_F(LoadBalancerConfigTest, InvalidBlockEncryption) {
- uint8_t pt[kLoadBalancerBlockSize], ct[kLoadBalancerBlockSize];
+ uint8_t pt[kLoadBalancerBlockSize + 1], ct[kLoadBalancerBlockSize];
auto pt_config = LoadBalancerConfig::CreateUnencrypted(0, 8, 8);
ASSERT_TRUE(pt_config.has_value());
EXPECT_FALSE(pt_config->BlockEncrypt(pt, ct));
EXPECT_FALSE(pt_config->BlockDecrypt(ct, pt));
EXPECT_TRUE(pt_config->FourPassEncrypt(absl::Span<uint8_t>(pt, sizeof(pt)))
.IsEmpty());
- EXPECT_FALSE(pt_config->FourPassDecrypt(absl::Span<uint8_t>(pt, sizeof(pt)))
- .IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_FALSE(pt_config->FourPassDecrypt(
+ absl::Span<uint8_t>(pt, sizeof(pt) - 1), answer));
auto small_cid_config =
LoadBalancerConfig::Create(0, 3, 4, absl::string_view(raw_key, 16));
ASSERT_TRUE(small_cid_config.has_value());
@@ -247,6 +248,20 @@
EXPECT_EQ(memcmp(result, ctext, sizeof(ctext)), 0);
}
+TEST_F(LoadBalancerConfigTest, FourPassInputTooShort) {
+ auto config =
+ LoadBalancerConfig::Create(0, 3, 4, absl::string_view(raw_key, 16));
+ uint8_t input[] = {0x0d, 0xd2, 0xd0, 0x5a, 0x7b, 0x0d, 0xe9};
+ LoadBalancerServerId answer;
+ EXPECT_QUIC_BUG(
+ config->FourPassDecrypt(
+ absl::Span<const uint8_t>(input, sizeof(input) - 1), answer),
+ "Called FourPassDecrypt with a short Connection ID");
+ EXPECT_QUIC_BUG(
+ config->FourPassEncrypt(absl::Span<uint8_t>(input, sizeof(input))),
+ "Called FourPassEncrypt with a short Connection ID");
+}
+
} // namespace
} // namespace test
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.cc b/quiche/quic/load_balancer/load_balancer_decoder.cc
index 0bbb804..05d8696 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.cc
+++ b/quiche/quic/load_balancer/load_balancer_decoder.cc
@@ -36,36 +36,34 @@
// This is the core logic to extract a server ID given a valid config and
// connection ID of sufficient length.
-LoadBalancerServerId LoadBalancerDecoder::GetServerId(
- const QuicConnectionId& connection_id) const {
+bool LoadBalancerDecoder::GetServerId(const QuicConnectionId& connection_id,
+ LoadBalancerServerId& server_id) const {
std::optional<uint8_t> config_id = GetConfigId(connection_id);
if (!config_id.has_value()) {
- return LoadBalancerServerId();
+ return false;
}
std::optional<LoadBalancerConfig> config = config_[*config_id];
if (!config.has_value()) {
- return LoadBalancerServerId();
+ return false;
}
// Benchmark tests show that minimizing the computation inside
// LoadBalancerConfig saves CPU cycles.
if (connection_id.length() < config->total_len()) {
- return LoadBalancerServerId();
+ return false;
}
const uint8_t* data =
reinterpret_cast<const uint8_t*>(connection_id.data()) + 1;
uint8_t server_id_len = config->server_id_len();
+ server_id.set_length(server_id_len);
if (!config->IsEncrypted()) {
- return LoadBalancerServerId(absl::Span<const uint8_t>(data, server_id_len));
+ memcpy(server_id.mutable_data(), connection_id.data() + 1, server_id_len);
+ return true;
}
if (config->plaintext_len() == kLoadBalancerBlockSize) {
- uint8_t scratch[kLoadBalancerBlockSize];
- if (!config->BlockDecrypt(data, scratch)) {
- return LoadBalancerServerId();
- }
- return LoadBalancerServerId(absl::Span<uint8_t>(scratch, server_id_len));
+ return config->BlockDecrypt(data, server_id.mutable_data());
}
return config->FourPassDecrypt(
- absl::MakeConstSpan(data, connection_id.length() - 1));
+ absl::MakeConstSpan(data, connection_id.length() - 1), server_id);
}
std::optional<uint8_t> LoadBalancerDecoder::GetConfigId(
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.h b/quiche/quic/load_balancer/load_balancer_decoder.h
index 21eb8b7..a352711 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.h
+++ b/quiche/quic/load_balancer/load_balancer_decoder.h
@@ -8,14 +8,21 @@
#include <cstdint>
#include <optional>
+#include "absl/base/attributes.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/load_balancer/load_balancer_config.h"
#include "quiche/quic/load_balancer/load_balancer_server_id.h"
+#include "quiche/quic/platform/api/quic_export.h"
namespace quic {
// Manages QUIC-LB configurations to extract a server ID from a properly
// encoded connection ID, usually on behalf of a load balancer.
+//
+// IMPORTANT: The decoder data path is likely the most performance-sensitive
+// part of the load balancer design, and this code has been carefully
+// optimized for performance. Please do not make changes without running the
+// benchmark tests to ensure there is no regression.
class QUIC_EXPORT_PRIVATE LoadBalancerDecoder {
public:
// Returns false if the config_id codepoint is already occupied.
@@ -36,11 +43,13 @@
return &*config_[config_id];
}
- // Extract a server ID from |connection_id|. If there is no config for the
- // codepoint, |connection_id| is too short, or there's a decrypt error,
- // returns empty. Will accept |connection_id| that is longer than necessary
- // without error.
- LoadBalancerServerId GetServerId(const QuicConnectionId& connection_id) const;
+ // Extract a server ID from |connection_id| and write it into |server_id|. If
+ // there is no config for the codepoint, |connection_id| is too short, or
+ // there's a decrypt error, returns false. Will accept |connection_id| that is
+ // longer than necessary without error. If GetServerId() returns false, there
+ // are no guarantees about the properties of |server_id|.
+ ABSL_MUST_USE_RESULT bool GetServerId(const QuicConnectionId& connection_id,
+ LoadBalancerServerId& server_id) const;
// Returns the config ID stored in the first two bits of |connection_id|, or
// empty if |connection_id| is empty, or the first two bits of the first byte
diff --git a/quiche/quic/load_balancer/load_balancer_decoder_test.cc b/quiche/quic/load_balancer/load_balancer_decoder_test.cc
index cc86d25..6e8a399 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_decoder_test.cc
@@ -56,8 +56,10 @@
}};
for (const auto& test : test_vectors) {
LoadBalancerDecoder decoder;
+ LoadBalancerServerId answer;
EXPECT_TRUE(decoder.AddConfig(test.config));
- EXPECT_EQ(decoder.GetServerId(test.connection_id), test.server_id);
+ EXPECT_TRUE(decoder.GetServerId(test.connection_id, answer));
+ EXPECT_EQ(answer, test.server_id);
}
}
@@ -97,21 +99,12 @@
for (const auto& test : test_vectors) {
LoadBalancerDecoder decoder;
EXPECT_TRUE(decoder.AddConfig(test.config));
- EXPECT_EQ(decoder.GetServerId(test.connection_id), test.server_id);
+ LoadBalancerServerId answer;
+ EXPECT_TRUE(decoder.GetServerId(test.connection_id, answer));
+ EXPECT_EQ(answer, test.server_id);
}
}
-TEST_F(LoadBalancerDecoderTest, NoServerIdEntry) {
- LoadBalancerServerId server_id({0x01, 0x02, 0x03});
- EXPECT_TRUE(server_id.IsValid());
- LoadBalancerDecoder decoder;
- EXPECT_TRUE(
- decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(0, 3, 4)));
- QuicConnectionId no_server_id_entry(
- {0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08});
- EXPECT_TRUE(decoder.GetServerId(no_server_id_entry).IsValid());
-}
-
TEST_F(LoadBalancerDecoderTest, InvalidConfigId) {
LoadBalancerServerId server_id({0x01, 0x02, 0x03});
EXPECT_TRUE(server_id.IsValid());
@@ -120,10 +113,10 @@
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(1, 3, 4)));
QuicConnectionId wrong_config_id(
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07});
- EXPECT_FALSE(decoder
- .GetServerId(QuicConnectionId(
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}))
- .IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_FALSE(decoder.GetServerId(
+ QuicConnectionId({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}),
+ answer));
}
TEST_F(LoadBalancerDecoderTest, UnroutableCodepoint) {
@@ -132,10 +125,10 @@
LoadBalancerDecoder decoder;
EXPECT_TRUE(
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(1, 3, 4)));
- EXPECT_FALSE(decoder
- .GetServerId(QuicConnectionId(
- {0xe0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}))
- .IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_FALSE(decoder.GetServerId(
+ QuicConnectionId({0xe0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}),
+ answer));
}
TEST_F(LoadBalancerDecoderTest, UnroutableCodepointAnyLength) {
@@ -144,7 +137,8 @@
LoadBalancerDecoder decoder;
EXPECT_TRUE(
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(1, 3, 4)));
- EXPECT_FALSE(decoder.GetServerId(QuicConnectionId({0xff})).IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_FALSE(decoder.GetServerId(QuicConnectionId({0xff}), answer));
}
TEST_F(LoadBalancerDecoderTest, ConnectionIdTooShort) {
@@ -153,10 +147,9 @@
LoadBalancerDecoder decoder;
EXPECT_TRUE(
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(0, 3, 4)));
- EXPECT_FALSE(decoder
- .GetServerId(QuicConnectionId(
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}))
- .IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_FALSE(decoder.GetServerId(
+ QuicConnectionId({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), answer));
}
TEST_F(LoadBalancerDecoderTest, ConnectionIdTooLongIsOK) {
@@ -164,10 +157,11 @@
LoadBalancerDecoder decoder;
EXPECT_TRUE(
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(0, 3, 4)));
- auto server_id_result = decoder.GetServerId(
- QuicConnectionId({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}));
- EXPECT_TRUE(server_id_result.IsValid());
- EXPECT_EQ(server_id_result, server_id);
+ LoadBalancerServerId answer;
+ EXPECT_TRUE(decoder.GetServerId(
+ QuicConnectionId({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}),
+ answer));
+ EXPECT_EQ(answer, server_id);
}
TEST_F(LoadBalancerDecoderTest, DeleteConfigBadId) {
@@ -176,20 +170,20 @@
decoder.DeleteConfig(0);
EXPECT_QUIC_BUG(decoder.DeleteConfig(7),
"Decoder deleting config with invalid config_id 7");
- EXPECT_TRUE(decoder
- .GetServerId(QuicConnectionId(
- {0x40, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}))
- .IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_TRUE(decoder.GetServerId(
+ QuicConnectionId({0x40, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}),
+ answer));
}
TEST_F(LoadBalancerDecoderTest, DeleteConfigGoodId) {
LoadBalancerDecoder decoder;
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(2, 3, 4));
decoder.DeleteConfig(2);
- EXPECT_FALSE(decoder
- .GetServerId(QuicConnectionId(
- {0x40, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}))
- .IsValid());
+ LoadBalancerServerId answer;
+ EXPECT_FALSE(decoder.GetServerId(
+ QuicConnectionId({0x40, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}),
+ answer));
}
// Create two server IDs and make sure the decoder decodes the correct one.
@@ -200,12 +194,15 @@
LoadBalancerDecoder decoder;
EXPECT_TRUE(
decoder.AddConfig(*LoadBalancerConfig::CreateUnencrypted(0, 3, 4)));
- EXPECT_EQ(decoder.GetServerId(QuicConnectionId(
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07})),
- server_id1);
- EXPECT_EQ(decoder.GetServerId(QuicConnectionId(
- {0x00, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a})),
- server_id2);
+ LoadBalancerServerId answer;
+ EXPECT_TRUE(decoder.GetServerId(
+ QuicConnectionId({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}),
+ answer));
+ EXPECT_EQ(answer, server_id1);
+ EXPECT_TRUE(decoder.GetServerId(
+ QuicConnectionId({0x00, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a}),
+ answer));
+ EXPECT_EQ(answer, server_id2);
}
TEST_F(LoadBalancerDecoderTest, GetConfigId) {
@@ -250,8 +247,9 @@
*LoadBalancerConfig::Create(0, 8, 8, absl::string_view(kRawKey, 16)));
LoadBalancerServerId original_server_id(absl::Span<uint8_t>(&ptext[1], 8));
QuicConnectionId cid(absl::Span<uint8_t>(ctext, sizeof(ctext)));
- LoadBalancerServerId server_id = decoder.GetServerId(cid);
- EXPECT_EQ(server_id, original_server_id);
+ LoadBalancerServerId answer;
+ EXPECT_TRUE(decoder.GetServerId(cid, answer));
+ EXPECT_EQ(answer, original_server_id);
}
} // namespace
diff --git a/quiche/quic/load_balancer/load_balancer_server_id.cc b/quiche/quic/load_balancer/load_balancer_server_id.cc
index 9a4685c..4861adb 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id.cc
+++ b/quiche/quic/load_balancer/load_balancer_server_id.cc
@@ -17,17 +17,11 @@
namespace quic {
LoadBalancerServerId::LoadBalancerServerId(absl::string_view data)
- : LoadBalancerServerId(
- absl::MakeSpan(reinterpret_cast<const uint8_t*>(data.data()),
- data.length()),
- absl::Span<const uint8_t>()) {}
+ : LoadBalancerServerId(absl::MakeSpan(
+ reinterpret_cast<const uint8_t*>(data.data()), data.length())) {}
LoadBalancerServerId::LoadBalancerServerId(absl::Span<const uint8_t> data)
- : LoadBalancerServerId(data, absl::Span<const uint8_t>()) {}
-
-LoadBalancerServerId::LoadBalancerServerId(absl::Span<const uint8_t> data1,
- absl::Span<const uint8_t> data2)
- : length_(data1.length() + data2.length()) {
+ : length_(data.length()) {
if (length_ == 0 || length_ > kLoadBalancerMaxServerIdLen) {
QUIC_BUG(quic_bug_433312504_02)
<< "Attempted to create LoadBalancerServerId with length "
@@ -35,11 +29,15 @@
length_ = 0;
return;
}
- memcpy(data_.data(), data1.data(), data1.length());
- if (data2.empty()) {
- return;
- }
- memcpy(data_.data() + data1.length(), data2.data(), data2.length());
+ memcpy(data_.data(), data.data(), data.length());
+}
+
+void LoadBalancerServerId::set_length(uint8_t length) {
+ QUIC_BUG_IF(quic_bug_599862571_01,
+ length == 0 || length > kLoadBalancerMaxServerIdLen)
+ << "Attempted to set LoadBalancerServerId length to "
+ << static_cast<int>(length);
+ length_ = length;
}
std::string LoadBalancerServerId::ToString() const {
diff --git a/quiche/quic/load_balancer/load_balancer_server_id.h b/quiche/quic/load_balancer/load_balancer_server_id.h
index d60d308..713f3e2 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id.h
+++ b/quiche/quic/load_balancer/load_balancer_server_id.h
@@ -17,6 +17,10 @@
// The maximum number of bytes in a LoadBalancerServerId.
inline constexpr uint8_t kLoadBalancerMaxServerIdLen = 15;
+// Regardless of key length, the AES block size is always 16 Bytes.
+inline constexpr uint8_t kLoadBalancerBlockSize = 16;
+static_assert(kLoadBalancerMaxServerIdLen <= kLoadBalancerBlockSize,
+ "LoadBalancerServerId array not large enough to hold Server ID");
// LoadBalancerServerId is the globally understood identifier for a given pool
// member. It is unique to any given QUIC-LB configuration. See
@@ -33,10 +37,6 @@
// Copies all the bytes from |data| into a new LoadBalancerServerId.
explicit LoadBalancerServerId(absl::Span<const uint8_t> data);
explicit LoadBalancerServerId(absl::string_view data);
- // Concatenates |data1| and |data2| into a single LoadBalancerServerId. This
- // is useful to reduce copying for certain decoder configurations.
- explicit LoadBalancerServerId(absl::Span<const uint8_t> data1,
- absl::Span<const uint8_t> data2);
// Server IDs are opaque bytes, but defining these operators allows us to sort
// them into a tree and define ranges.
@@ -57,7 +57,10 @@
absl::Span<const uint8_t> data() const {
return absl::MakeConstSpan(data_.data(), length_);
}
+ uint8_t* mutable_data() { return data_.data(); }
+
uint8_t length() const { return length_; }
+ void set_length(uint8_t length);
// Returns the server ID in hex format.
std::string ToString() const;
@@ -66,7 +69,9 @@
bool IsValid() { return length_ != 0; }
private:
- std::array<uint8_t, kLoadBalancerMaxServerIdLen> data_;
+ // Make the array large enough to hold an entire decrypt result, to save a
+ // copy from the decrypt result into LoadBalancerServerId.
+ std::array<uint8_t, kLoadBalancerBlockSize> data_;
uint8_t length_;
};
diff --git a/quiche/quic/load_balancer/load_balancer_server_id_test.cc b/quiche/quic/load_balancer/load_balancer_server_id_test.cc
index 08b5e6d..6b3bc52 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_server_id_test.cc
@@ -30,27 +30,11 @@
absl::Span<const uint8_t>(kRawServerId, 16))
.IsValid()),
"Attempted to create LoadBalancerServerId with length 16");
- EXPECT_QUIC_BUG(EXPECT_FALSE(LoadBalancerServerId(
- absl::Span<const uint8_t>(kRawServerId, 9),
- absl::Span<const uint8_t>(kRawServerId, 7))
- .IsValid()),
- "Attempted to create LoadBalancerServerId with length 16");
EXPECT_QUIC_BUG(
EXPECT_FALSE(LoadBalancerServerId(absl::Span<const uint8_t>()).IsValid()),
"Attempted to create LoadBalancerServerId with length 0");
}
-TEST_F(LoadBalancerServerIdTest, TwoPartConstructor) {
- LoadBalancerServerId server_id1(absl::Span<const uint8_t>(kRawServerId, 15));
- ASSERT_TRUE(server_id1.IsValid());
- LoadBalancerServerId server_id2(
- absl::Span<const uint8_t>(kRawServerId, 8),
- absl::Span<const uint8_t>(&kRawServerId[8], 7));
- ASSERT_TRUE(server_id2.IsValid());
- EXPECT_TRUE(server_id1 == server_id2);
- ;
-}
-
TEST_F(LoadBalancerServerIdTest, CompareIdenticalExceptLength) {
LoadBalancerServerId server_id(absl::Span<const uint8_t>(kRawServerId, 15));
ASSERT_TRUE(server_id.IsValid());
@@ -111,6 +95,18 @@
}));
}
+TEST_F(LoadBalancerServerIdTest, SetLengthInvalid) {
+ LoadBalancerServerId server_id;
+ EXPECT_QUIC_BUG(server_id.set_length(16),
+ "Attempted to set LoadBalancerServerId length to 16");
+ EXPECT_QUIC_BUG(server_id.set_length(0),
+ "Attempted to set LoadBalancerServerId length to 0");
+ server_id.set_length(1);
+ EXPECT_EQ(server_id.length(), 1);
+ server_id.set_length(15);
+ EXPECT_EQ(server_id.length(), 15);
+}
+
} // namespace
} // namespace test