Implement comparator for TransportParameters.

This will be used to compare what's held in the session and what's stored in the session cache, so that we can avoid unnecessary copying.

gfe-relnote: no behavior change. not protected.
PiperOrigin-RevId: 305724142
Change-Id: Ia728fb93e37f58e9f2848b5078630d304d9ee46d
diff --git a/quic/core/crypto/crypto_handshake_message.cc b/quic/core/crypto/crypto_handshake_message.cc
index d5b4635..d0e66d8 100644
--- a/quic/core/crypto/crypto_handshake_message.cc
+++ b/quic/core/crypto/crypto_handshake_message.cc
@@ -50,6 +50,12 @@
 CryptoHandshakeMessage& CryptoHandshakeMessage::operator=(
     CryptoHandshakeMessage&& other) = default;
 
+bool CryptoHandshakeMessage::operator==(
+    const CryptoHandshakeMessage& rhs) const {
+  return tag_ == rhs.tag_ && tag_value_map_ == rhs.tag_value_map_ &&
+         minimum_size_ == rhs.minimum_size_;
+}
+
 void CryptoHandshakeMessage::Clear() {
   tag_ = 0;
   tag_value_map_.clear();
diff --git a/quic/core/crypto/crypto_handshake_message.h b/quic/core/crypto/crypto_handshake_message.h
index 409738a..b5996de 100644
--- a/quic/core/crypto/crypto_handshake_message.h
+++ b/quic/core/crypto/crypto_handshake_message.h
@@ -30,6 +30,8 @@
   CryptoHandshakeMessage& operator=(const CryptoHandshakeMessage& other);
   CryptoHandshakeMessage& operator=(CryptoHandshakeMessage&& other);
 
+  bool operator==(const CryptoHandshakeMessage& rhs) const;
+
   // Clears state.
   void Clear();
 
diff --git a/quic/core/crypto/transport_parameters.cc b/quic/core/crypto/transport_parameters.cc
index 4a6a0c7..422be3d 100644
--- a/quic/core/crypto/transport_parameters.cc
+++ b/quic/core/crypto/transport_parameters.cc
@@ -312,6 +312,14 @@
 
 TransportParameters::PreferredAddress::~PreferredAddress() {}
 
+bool TransportParameters::PreferredAddress::operator==(
+    const PreferredAddress& rhs) const {
+  return ipv4_socket_address == rhs.ipv4_socket_address &&
+         ipv6_socket_address == rhs.ipv6_socket_address &&
+         connection_id == rhs.connection_id &&
+         stateless_reset_token == rhs.stateless_reset_token;
+}
+
 std::ostream& operator<<(
     std::ostream& os,
     const TransportParameters::PreferredAddress& preferred_address) {
@@ -415,8 +423,8 @@
       max_datagram_frame_size(kMaxDatagramFrameSize)
 // Important note: any new transport parameters must be added
 // to TransportParameters::AreValid, SerializeTransportParameters and
-// ParseTransportParameters, TransportParameters's custom copy constructor, and
-// TransportParametersTest.CopyConstructor.
+// ParseTransportParameters, TransportParameters's custom copy constructor, the
+// operator==, and TransportParametersTest.Comparator.
 {}
 
 TransportParameters::TransportParameters(const TransportParameters& other)
@@ -451,6 +459,54 @@
   }
 }
 
+bool TransportParameters::operator==(const TransportParameters& rhs) const {
+  if (!(perspective == rhs.perspective && version == rhs.version &&
+        supported_versions == rhs.supported_versions &&
+        original_connection_id == rhs.original_connection_id &&
+        idle_timeout_milliseconds.value() ==
+            rhs.idle_timeout_milliseconds.value() &&
+        stateless_reset_token == rhs.stateless_reset_token &&
+        max_packet_size.value() == rhs.max_packet_size.value() &&
+        initial_max_data.value() == rhs.initial_max_data.value() &&
+        initial_max_stream_data_bidi_local.value() ==
+            rhs.initial_max_stream_data_bidi_local.value() &&
+        initial_max_stream_data_bidi_remote.value() ==
+            rhs.initial_max_stream_data_bidi_remote.value() &&
+        initial_max_stream_data_uni.value() ==
+            rhs.initial_max_stream_data_uni.value() &&
+        initial_max_streams_bidi.value() ==
+            rhs.initial_max_streams_bidi.value() &&
+        initial_max_streams_uni.value() ==
+            rhs.initial_max_streams_uni.value() &&
+        ack_delay_exponent.value() == rhs.ack_delay_exponent.value() &&
+        max_ack_delay.value() == rhs.max_ack_delay.value() &&
+        disable_migration == rhs.disable_migration &&
+        active_connection_id_limit.value() ==
+            rhs.active_connection_id_limit.value() &&
+        max_datagram_frame_size.value() ==
+            rhs.max_datagram_frame_size.value() &&
+        custom_parameters == rhs.custom_parameters)) {
+    return false;
+  }
+
+  if ((!preferred_address && rhs.preferred_address) ||
+      (preferred_address && !rhs.preferred_address) ||
+      (!google_quic_params && rhs.google_quic_params) ||
+      (google_quic_params && !rhs.google_quic_params)) {
+    return false;
+  }
+  bool address = true;
+  if (preferred_address && rhs.preferred_address) {
+    address = (*preferred_address == *rhs.preferred_address);
+  }
+
+  bool google_quic = true;
+  if (google_quic_params && rhs.google_quic_params) {
+    google_quic = (*google_quic_params == *rhs.google_quic_params);
+  }
+  return address && google_quic;
+}
+
 bool TransportParameters::AreValid(std::string* error_details) const {
   DCHECK(perspective == Perspective::IS_CLIENT ||
          perspective == Perspective::IS_SERVER);
diff --git a/quic/core/crypto/transport_parameters.h b/quic/core/crypto/transport_parameters.h
index e4737c2..e3d6782 100644
--- a/quic/core/crypto/transport_parameters.h
+++ b/quic/core/crypto/transport_parameters.h
@@ -92,6 +92,7 @@
     PreferredAddress(const PreferredAddress& other) = default;
     PreferredAddress(PreferredAddress&& other) = default;
     ~PreferredAddress();
+    bool operator==(const PreferredAddress& rhs) const;
 
     QuicSocketAddress ipv4_socket_address;
     QuicSocketAddress ipv6_socket_address;
@@ -108,6 +109,7 @@
   TransportParameters();
   TransportParameters(const TransportParameters& other);
   ~TransportParameters();
+  bool operator==(const TransportParameters& rhs) const;
 
   // Represents the sender of the transport parameters. When |perspective| is
   // Perspective::IS_CLIENT, this struct is being used in the client_hello
diff --git a/quic/core/crypto/transport_parameters_test.cc b/quic/core/crypto/transport_parameters_test.cc
index 51e5145..2ed7d63 100644
--- a/quic/core/crypto/transport_parameters_test.cc
+++ b/quic/core/crypto/transport_parameters_test.cc
@@ -7,6 +7,7 @@
 #include <cstring>
 #include <utility>
 
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
@@ -125,10 +126,69 @@
                          ::testing::ValuesIn(AllSupportedTlsVersions()),
                          ::testing::PrintToStringParamName());
 
+TEST_P(TransportParametersTest, Comparator) {
+  TransportParameters orig_params;
+  TransportParameters new_params;
+  // Test comparison on primitive members.
+  orig_params.perspective = Perspective::IS_CLIENT;
+  new_params.perspective = Perspective::IS_SERVER;
+  EXPECT_FALSE(orig_params == new_params);
+  new_params.perspective = Perspective::IS_CLIENT;
+  orig_params.version = kFakeVersionLabel;
+  new_params.version = kFakeVersionLabel;
+  orig_params.disable_migration = true;
+  new_params.disable_migration = true;
+  EXPECT_EQ(orig_params, new_params);
+
+  // Test comparison on vectors.
+  orig_params.supported_versions.push_back(kFakeVersionLabel);
+  new_params.supported_versions.push_back(kFakeVersionLabel2);
+  EXPECT_FALSE(orig_params == new_params);
+  new_params.supported_versions.pop_back();
+  new_params.supported_versions.push_back(kFakeVersionLabel);
+  orig_params.stateless_reset_token = CreateFakeStatelessResetToken();
+  new_params.stateless_reset_token = CreateFakeStatelessResetToken();
+  EXPECT_EQ(orig_params, new_params);
+
+  // Test comparison on IntegerParameters.
+  orig_params.max_packet_size.set_value(kFakeMaxPacketSize);
+  new_params.max_packet_size.set_value(kFakeMaxPacketSize + 1);
+  EXPECT_FALSE(orig_params == new_params);
+  new_params.max_packet_size.set_value(kFakeMaxPacketSize);
+  EXPECT_EQ(orig_params, new_params);
+
+  // Test comparison on PreferredAddress
+  orig_params.preferred_address = CreateFakePreferredAddress();
+  EXPECT_FALSE(orig_params == new_params);
+  new_params.preferred_address = CreateFakePreferredAddress();
+  EXPECT_EQ(orig_params, new_params);
+
+  // Test comparison on CryptoHandshakeMessage.
+  orig_params.google_quic_params = std::make_unique<CryptoHandshakeMessage>();
+  const std::string kTestString = "test string";
+  orig_params.google_quic_params->SetStringPiece(42, kTestString);
+  const uint32_t kTestValue = 12;
+  orig_params.google_quic_params->SetValue(1337, kTestValue);
+  EXPECT_FALSE(orig_params == new_params);
+
+  new_params.google_quic_params = std::make_unique<CryptoHandshakeMessage>();
+  new_params.google_quic_params->SetStringPiece(42, kTestString);
+  new_params.google_quic_params->SetValue(1337, kTestValue + 1);
+  EXPECT_FALSE(orig_params == new_params);
+  new_params.google_quic_params->SetValue(1337, kTestValue);
+  EXPECT_EQ(orig_params, new_params);
+
+  // Test comparison on CustomMap
+  orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
+  orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
+
+  new_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
+  new_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value;
+  EXPECT_EQ(orig_params, new_params);
+}
+
 TEST_P(TransportParametersTest, CopyConstructor) {
   TransportParameters orig_params;
-  orig_params.perspective = Perspective::IS_SERVER;
-  orig_params.version = kFakeVersionLabel;
   orig_params.supported_versions.push_back(kFakeVersionLabel);
   orig_params.supported_versions.push_back(kFakeVersionLabel2);
   orig_params.original_connection_id = CreateFakeOriginalConnectionId();
@@ -154,46 +214,7 @@
   orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
 
   TransportParameters new_params(orig_params);
-  EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
-  EXPECT_EQ(kFakeVersionLabel, new_params.version);
-  EXPECT_EQ(2u, new_params.supported_versions.size());
-  EXPECT_EQ(kFakeVersionLabel, new_params.supported_versions[0]);
-  EXPECT_EQ(kFakeVersionLabel2, new_params.supported_versions[1]);
-  EXPECT_EQ(CreateFakeOriginalConnectionId(),
-            new_params.original_connection_id);
-  EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
-            new_params.idle_timeout_milliseconds.value());
-  EXPECT_EQ(CreateFakeStatelessResetToken(), new_params.stateless_reset_token);
-  EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
-  EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
-            new_params.initial_max_stream_data_bidi_local.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
-            new_params.initial_max_stream_data_bidi_remote.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataUni,
-            new_params.initial_max_stream_data_uni.value());
-  EXPECT_EQ(kFakeInitialMaxStreamsBidi,
-            new_params.initial_max_streams_bidi.value());
-  EXPECT_EQ(kFakeInitialMaxStreamsUni,
-            new_params.initial_max_streams_uni.value());
-  EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
-  EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
-  EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
-  ASSERT_NE(nullptr, new_params.preferred_address.get());
-  EXPECT_EQ(CreateFakeV4SocketAddress(),
-            new_params.preferred_address->ipv4_socket_address);
-  EXPECT_EQ(CreateFakeV6SocketAddress(),
-            new_params.preferred_address->ipv6_socket_address);
-  EXPECT_EQ(CreateFakePreferredConnectionId(),
-            new_params.preferred_address->connection_id);
-  EXPECT_EQ(CreateFakePreferredStatelessResetToken(),
-            new_params.preferred_address->stateless_reset_token);
-  EXPECT_EQ(kFakeActiveConnectionIdLimit,
-            new_params.active_connection_id_limit.value());
-  EXPECT_THAT(
-      new_params.custom_parameters,
-      UnorderedElementsAre(Pair(kCustomParameter1, kCustomParameter1Value),
-                           Pair(kCustomParameter2, kCustomParameter2Value)));
+  EXPECT_EQ(new_params, orig_params);
 }
 
 TEST_P(TransportParametersTest, RoundTripClient) {
@@ -229,34 +250,7 @@
                                        &new_params, &error_details))
       << error_details;
   EXPECT_TRUE(error_details.empty());
-  EXPECT_EQ(Perspective::IS_CLIENT, new_params.perspective);
-  EXPECT_EQ(kFakeVersionLabel, new_params.version);
-  EXPECT_TRUE(new_params.supported_versions.empty());
-  EXPECT_EQ(EmptyQuicConnectionId(), new_params.original_connection_id);
-  EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
-            new_params.idle_timeout_milliseconds.value());
-  EXPECT_TRUE(new_params.stateless_reset_token.empty());
-  EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
-  EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
-            new_params.initial_max_stream_data_bidi_local.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
-            new_params.initial_max_stream_data_bidi_remote.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataUni,
-            new_params.initial_max_stream_data_uni.value());
-  EXPECT_EQ(kFakeInitialMaxStreamsBidi,
-            new_params.initial_max_streams_bidi.value());
-  EXPECT_EQ(kFakeInitialMaxStreamsUni,
-            new_params.initial_max_streams_uni.value());
-  EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
-  EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
-  EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
-  EXPECT_EQ(kFakeActiveConnectionIdLimit,
-            new_params.active_connection_id_limit.value());
-  EXPECT_THAT(
-      new_params.custom_parameters,
-      UnorderedElementsAre(Pair(kCustomParameter1, kCustomParameter1Value),
-                           Pair(kCustomParameter2, kCustomParameter2Value)));
+  EXPECT_EQ(new_params, orig_params);
 }
 
 TEST_P(TransportParametersTest, RoundTripServer) {
@@ -295,43 +289,7 @@
                                        &new_params, &error_details))
       << error_details;
   EXPECT_TRUE(error_details.empty());
-  EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
-  EXPECT_EQ(kFakeVersionLabel, new_params.version);
-  EXPECT_EQ(2u, new_params.supported_versions.size());
-  EXPECT_EQ(kFakeVersionLabel, new_params.supported_versions[0]);
-  EXPECT_EQ(kFakeVersionLabel2, new_params.supported_versions[1]);
-  EXPECT_EQ(CreateFakeOriginalConnectionId(),
-            new_params.original_connection_id);
-  EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
-            new_params.idle_timeout_milliseconds.value());
-  EXPECT_EQ(CreateFakeStatelessResetToken(), new_params.stateless_reset_token);
-  EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
-  EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
-            new_params.initial_max_stream_data_bidi_local.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
-            new_params.initial_max_stream_data_bidi_remote.value());
-  EXPECT_EQ(kFakeInitialMaxStreamDataUni,
-            new_params.initial_max_stream_data_uni.value());
-  EXPECT_EQ(kFakeInitialMaxStreamsBidi,
-            new_params.initial_max_streams_bidi.value());
-  EXPECT_EQ(kFakeInitialMaxStreamsUni,
-            new_params.initial_max_streams_uni.value());
-  EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
-  EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
-  EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
-  ASSERT_NE(nullptr, new_params.preferred_address.get());
-  EXPECT_EQ(CreateFakeV4SocketAddress(),
-            new_params.preferred_address->ipv4_socket_address);
-  EXPECT_EQ(CreateFakeV6SocketAddress(),
-            new_params.preferred_address->ipv6_socket_address);
-  EXPECT_EQ(CreateFakePreferredConnectionId(),
-            new_params.preferred_address->connection_id);
-  EXPECT_EQ(CreateFakePreferredStatelessResetToken(),
-            new_params.preferred_address->stateless_reset_token);
-  EXPECT_EQ(kFakeActiveConnectionIdLimit,
-            new_params.active_connection_id_limit.value());
-  EXPECT_EQ(0u, new_params.custom_parameters.size());
+  EXPECT_EQ(new_params, orig_params);
 }
 
 TEST_P(TransportParametersTest, AreValid) {