dcsctp: support handover state serialization testing

dcSCTP library users can set their custom
g_handover_state_transformer_for_test that can serialize and
deserialize the state. All dcSCTP handover tests call
g_handover_state_transformer_for_test. If some part of the state is
serialized incorrectly or is forgotten, high chance that it will
fail the tests.

Bug: webrtc:13154
Change-Id: I251a099be04dda7611e9df868d36e3a76dc7d1e1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/232325
Commit-Queue: Sergey Sukhanov <sergeysu@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35035}
diff --git a/net/dcsctp/common/BUILD.gn b/net/dcsctp/common/BUILD.gn
index 591fa442..8052013 100644
--- a/net/dcsctp/common/BUILD.gn
+++ b/net/dcsctp/common/BUILD.gn
@@ -54,3 +54,12 @@
     ]
   }
 }
+
+rtc_library("handover_testing") {
+  deps = [ "../public:socket" ]
+  testonly = true
+  sources = [
+    "handover_testing.cc",
+    "handover_testing.h",
+  ]
+}
diff --git a/net/dcsctp/common/handover_testing.cc b/net/dcsctp/common/handover_testing.cc
new file mode 100644
index 0000000..1081766
--- /dev/null
+++ b/net/dcsctp/common/handover_testing.cc
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/common/handover_testing.h"
+
+namespace dcsctp {
+namespace {
+// Default transformer function does nothing - dcSCTP does not implement
+// state serialization that could be tested by setting
+// `g_handover_state_transformer_for_test`.
+void NoTransformation(DcSctpSocketHandoverState*) {}
+}  // namespace
+
+void (*g_handover_state_transformer_for_test)(DcSctpSocketHandoverState*) =
+    NoTransformation;
+}  // namespace dcsctp
diff --git a/net/dcsctp/common/handover_testing.h b/net/dcsctp/common/handover_testing.h
new file mode 100644
index 0000000..396016a
--- /dev/null
+++ b/net/dcsctp/common/handover_testing.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_COMMON_HANDOVER_TESTING_H_
+#define NET_DCSCTP_COMMON_HANDOVER_TESTING_H_
+
+#include "net/dcsctp/public/dcsctp_handover_state.h"
+
+namespace dcsctp {
+// This global function is to facilitate testing of the socket handover state
+// (`DcSctpSocketHandoverState`) serialization. dcSCTP library users have to
+// implement state serialization if it's needed. To test the serialization one
+// can set a custom `g_handover_state_transformer_for_test` at startup, link to
+// the dcSCTP tests and run the resulting binary. Custom function can serialize
+// and deserialize the passed state. All dcSCTP handover tests call
+// `g_handover_state_transformer_for_test`. If some part of the state is
+// serialized incorrectly or is forgotten, high chance that it will fail the
+// tests.
+extern void (*g_handover_state_transformer_for_test)(
+    DcSctpSocketHandoverState*);
+}  // namespace dcsctp
+
+#endif  // NET_DCSCTP_COMMON_HANDOVER_TESTING_H_
diff --git a/net/dcsctp/rx/BUILD.gn b/net/dcsctp/rx/BUILD.gn
index cdb4653..c5023a5 100644
--- a/net/dcsctp/rx/BUILD.gn
+++ b/net/dcsctp/rx/BUILD.gn
@@ -108,6 +108,7 @@
       "../../../rtc_base:gunit_helpers",
       "../../../rtc_base:rtc_base_approved",
       "../../../test:test_support",
+      "../common:handover_testing",
       "../common:sequence_numbers",
       "../packet:chunk",
       "../packet:data",
diff --git a/net/dcsctp/rx/data_tracker_test.cc b/net/dcsctp/rx/data_tracker_test.cc
index e59f8a9..6140241 100644
--- a/net/dcsctp/rx/data_tracker_test.cc
+++ b/net/dcsctp/rx/data_tracker_test.cc
@@ -15,6 +15,7 @@
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
+#include "net/dcsctp/common/handover_testing.h"
 #include "net/dcsctp/packet/chunk/sack_chunk.h"
 #include "net/dcsctp/timer/fake_timeout.h"
 #include "net/dcsctp/timer/timer.h"
@@ -54,6 +55,7 @@
     EXPECT_TRUE(tracker_->GetHandoverReadiness().IsReady());
     DcSctpSocketHandoverState state;
     tracker_->AddHandoverState(state);
+    g_handover_state_transformer_for_test(&state);
     tracker_ = std::make_unique<DataTracker>("log: ", timer_.get(), kInitialTSN,
                                              &state);
   }
diff --git a/net/dcsctp/rx/reassembly_queue_test.cc b/net/dcsctp/rx/reassembly_queue_test.cc
index 8f98ef1..d1e3bf6 100644
--- a/net/dcsctp/rx/reassembly_queue_test.cc
+++ b/net/dcsctp/rx/reassembly_queue_test.cc
@@ -18,6 +18,7 @@
 #include <vector>
 
 #include "api/array_view.h"
+#include "net/dcsctp/common/handover_testing.h"
 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
 #include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
@@ -367,6 +368,7 @@
   EXPECT_EQ(reasm1.GetHandoverReadiness(), HandoverReadinessStatus());
   DcSctpSocketHandoverState state;
   reasm1.AddHandoverState(state);
+  g_handover_state_transformer_for_test(&state);
   ReassemblyQueue reasm2("log: ", TSN(100), kBufferSize, &state);
 
   reasm2.Add(TSN(10), gen_.Ordered({1, 2, 3, 4}, "BE"));
@@ -381,6 +383,7 @@
   EXPECT_EQ(reasm1.GetHandoverReadiness(), HandoverReadinessStatus());
   DcSctpSocketHandoverState state;
   reasm1.AddHandoverState(state);
+  g_handover_state_transformer_for_test(&state);
   ReassemblyQueue reasm2("log: ", TSN(100), kBufferSize, &state);
 
   reasm2.Add(TSN(11), gen_.Ordered({1, 2, 3, 4}, "BE"));
diff --git a/net/dcsctp/rx/traditional_reassembly_streams_test.cc b/net/dcsctp/rx/traditional_reassembly_streams_test.cc
index f58bfed..3e6f560 100644
--- a/net/dcsctp/rx/traditional_reassembly_streams_test.cc
+++ b/net/dcsctp/rx/traditional_reassembly_streams_test.cc
@@ -13,6 +13,7 @@
 #include <memory>
 #include <utility>
 
+#include "net/dcsctp/common/handover_testing.h"
 #include "net/dcsctp/common/sequence_numbers.h"
 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
@@ -156,6 +157,7 @@
 
   DcSctpSocketHandoverState state;
   streams1.AddHandoverState(state);
+  g_handover_state_transformer_for_test(&state);
   TraditionalReassemblyStreams streams2("", on_assembled.AsStdFunction(),
                                         &state);
 
@@ -191,6 +193,7 @@
 
   DcSctpSocketHandoverState state;
   streams1.AddHandoverState(state);
+  g_handover_state_transformer_for_test(&state);
   TraditionalReassemblyStreams streams2("", on_assembled.AsStdFunction(),
                                         &state);
   EXPECT_EQ(streams2.Add(tsn(4), gen_.Ordered({7})), 1);
@@ -223,6 +226,7 @@
 
   DcSctpSocketHandoverState state;
   streams1.AddHandoverState(state);
+  g_handover_state_transformer_for_test(&state);
   TraditionalReassemblyStreams streams2("", on_assembled.AsStdFunction(),
                                         &state);
   EXPECT_EQ(streams2.Add(tsn(4), gen_.Unordered({7})), 1);
diff --git a/net/dcsctp/socket/BUILD.gn b/net/dcsctp/socket/BUILD.gn
index 8952920..69307ac 100644
--- a/net/dcsctp/socket/BUILD.gn
+++ b/net/dcsctp/socket/BUILD.gn
@@ -225,6 +225,7 @@
       "../../../rtc_base:gunit_helpers",
       "../../../rtc_base:rtc_base_approved",
       "../../../test:test_support",
+      "../common:handover_testing",
       "../common:internal_types",
       "../packet:chunk",
       "../packet:error_cause",
diff --git a/net/dcsctp/socket/dcsctp_socket_test.cc b/net/dcsctp/socket/dcsctp_socket_test.cc
index 2fadde8..9f5190b 100644
--- a/net/dcsctp/socket/dcsctp_socket_test.cc
+++ b/net/dcsctp/socket/dcsctp_socket_test.cc
@@ -21,6 +21,7 @@
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 #include "api/array_view.h"
+#include "net/dcsctp/common/handover_testing.h"
 #include "net/dcsctp/packet/chunk/chunk.h"
 #include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
 #include "net/dcsctp/packet/chunk/data_chunk.h"
@@ -324,6 +325,7 @@
     absl::optional<DcSctpSocketHandoverState> handover_state =
         sock_z_->GetHandoverStateAndClose();
     EXPECT_TRUE(handover_state.has_value());
+    g_handover_state_transformer_for_test(&*handover_state);
     cb_z_.Reset();
     sock_z_ = std::make_unique<DcSctpSocket>("Z", cb_z_, GetPacketObserver("Z"),
                                              options_);
diff --git a/net/dcsctp/socket/stream_reset_handler_test.cc b/net/dcsctp/socket/stream_reset_handler_test.cc
index 4fa7e1b..894f486 100644
--- a/net/dcsctp/socket/stream_reset_handler_test.cc
+++ b/net/dcsctp/socket/stream_reset_handler_test.cc
@@ -17,6 +17,7 @@
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
+#include "net/dcsctp/common/handover_testing.h"
 #include "net/dcsctp/common/internal_types.h"
 #include "net/dcsctp/packet/chunk/reconfig_chunk.h"
 #include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
@@ -186,6 +187,8 @@
 
     retransmission_queue_->AddHandoverState(state);
 
+    g_handover_state_transformer_for_test(&state);
+
     data_tracker_ = std::make_unique<DataTracker>(
         "log: ", delayed_ack_timer_.get(), kPeerInitialTsn, &state);
     reasm_ = std::make_unique<ReassemblyQueue>("log: ", kPeerInitialTsn, kArwnd,
diff --git a/net/dcsctp/tx/BUILD.gn b/net/dcsctp/tx/BUILD.gn
index a02f5dc..6bf439f 100644
--- a/net/dcsctp/tx/BUILD.gn
+++ b/net/dcsctp/tx/BUILD.gn
@@ -121,6 +121,7 @@
       "../../../rtc_base:gunit_helpers",
       "../../../rtc_base:rtc_base_approved",
       "../../../test:test_support",
+      "../common:handover_testing",
       "../packet:chunk",
       "../packet:data",
       "../public:socket",
diff --git a/net/dcsctp/tx/retransmission_queue_test.cc b/net/dcsctp/tx/retransmission_queue_test.cc
index 5f524de..b34927a 100644
--- a/net/dcsctp/tx/retransmission_queue_test.cc
+++ b/net/dcsctp/tx/retransmission_queue_test.cc
@@ -18,6 +18,7 @@
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
+#include "net/dcsctp/common/handover_testing.h"
 #include "net/dcsctp/packet/chunk/data_chunk.h"
 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
@@ -93,6 +94,7 @@
     EXPECT_EQ(queue.GetHandoverReadiness(), HandoverReadinessStatus());
     DcSctpSocketHandoverState state;
     queue.AddHandoverState(state);
+    g_handover_state_transformer_for_test(&state);
     return RetransmissionQueue(
         "", TSN(10), kArwnd, producer_, on_rtt_.AsStdFunction(),
         on_clear_retransmission_counter_.AsStdFunction(), *timer_, options_,