|  | // Copyright (c) 2019 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/third_party/quiche/src/quic/quartc/quartc_multiplexer.h" | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_bandwidth.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_time.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_types.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h" | 
|  | #include "net/third_party/quiche/src/quic/quartc/counting_packet_filter.h" | 
|  | #include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h" | 
|  | #include "net/third_party/quiche/src/quic/quartc/quartc_fakes.h" | 
|  | #include "net/third_party/quiche/src/quic/quartc/quartc_session.h" | 
|  | #include "net/third_party/quiche/src/quic/quartc/quartc_stream.h" | 
|  | #include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/simulator/link.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h" | 
|  |  | 
|  | namespace quic { | 
|  | namespace { | 
|  |  | 
|  | using ::testing::ElementsAreArray; | 
|  | using ::testing::Gt; | 
|  | using ::testing::IsEmpty; | 
|  | using ::testing::Pair; | 
|  |  | 
|  | constexpr QuicTime::Delta kPropagationDelay = | 
|  | QuicTime::Delta::FromMilliseconds(10); | 
|  |  | 
|  | class FakeSessionEventDelegate : public QuartcSessionEventDelegate { | 
|  | public: | 
|  | void OnSessionCreated(QuartcSession* session) override { | 
|  | session->StartCryptoHandshake(); | 
|  | session_ = session; | 
|  | } | 
|  |  | 
|  | void OnConnectionWritable() override { ++writable_count_; } | 
|  |  | 
|  | void OnCryptoHandshakeComplete() override { ++handshake_count_; } | 
|  |  | 
|  | void OnConnectionClosed(const QuicConnectionCloseFrame& frame, | 
|  | ConnectionCloseSource source) override { | 
|  | error_ = frame.quic_error_code; | 
|  | close_source_ = source; | 
|  | } | 
|  |  | 
|  | void OnCongestionControlChange(QuicBandwidth bandwidth_estimate, | 
|  | QuicBandwidth pacing_rate, | 
|  | QuicTime::Delta latest_rtt) override { | 
|  | latest_bandwidth_estimate_ = bandwidth_estimate; | 
|  | latest_pacing_rate_ = pacing_rate; | 
|  | latest_rtt_ = latest_rtt; | 
|  | } | 
|  |  | 
|  | QuartcSession* session() { return session_; } | 
|  | int writable_count() const { return writable_count_; } | 
|  | int handshake_count() const { return handshake_count_; } | 
|  | QuicErrorCode error() const { return error_; } | 
|  | ConnectionCloseSource close_source() const { return close_source_; } | 
|  | QuicBandwidth latest_bandwidth_estimate() const { | 
|  | return latest_bandwidth_estimate_; | 
|  | } | 
|  | QuicBandwidth latest_pacing_rate() const { return latest_pacing_rate_; } | 
|  | QuicTime::Delta latest_rtt() const { return latest_rtt_; } | 
|  |  | 
|  | private: | 
|  | QuartcSession* session_ = nullptr; | 
|  | int writable_count_ = 0; | 
|  | int handshake_count_ = 0; | 
|  | QuicErrorCode error_ = QUIC_NO_ERROR; | 
|  | ConnectionCloseSource close_source_; | 
|  | QuicBandwidth latest_bandwidth_estimate_ = QuicBandwidth::Zero(); | 
|  | QuicBandwidth latest_pacing_rate_ = QuicBandwidth::Zero(); | 
|  | QuicTime::Delta latest_rtt_ = QuicTime::Delta::Zero(); | 
|  | }; | 
|  |  | 
|  | class FakeSendDelegate : public QuartcSendChannel::Delegate { | 
|  | public: | 
|  | void OnMessageSent(int64_t datagram_id) override { | 
|  | datagrams_sent_.push_back(datagram_id); | 
|  | } | 
|  |  | 
|  | void OnMessageAcked(int64_t datagram_id, | 
|  | QuicTime receive_timestamp) override { | 
|  | datagrams_acked_.push_back({datagram_id, receive_timestamp}); | 
|  | } | 
|  |  | 
|  | void OnMessageLost(int64_t datagram_id) override { | 
|  | datagrams_lost_.push_back(datagram_id); | 
|  | } | 
|  |  | 
|  | const std::vector<int64_t>& datagrams_sent() const { return datagrams_sent_; } | 
|  | const std::vector<std::pair<int64_t, QuicTime>>& datagrams_acked() const { | 
|  | return datagrams_acked_; | 
|  | } | 
|  | const std::vector<int64_t>& datagrams_lost() const { return datagrams_lost_; } | 
|  |  | 
|  | private: | 
|  | std::vector<int64_t> datagrams_sent_; | 
|  | std::vector<std::pair<int64_t, QuicTime>> datagrams_acked_; | 
|  | std::vector<int64_t> datagrams_lost_; | 
|  | }; | 
|  |  | 
|  | class FakeReceiveDelegate : public QuartcReceiveChannel, | 
|  | public QuartcStream::Delegate { | 
|  | public: | 
|  | const std::vector<std::pair<uint64_t, std::string>> messages_received() | 
|  | const { | 
|  | return messages_received_; | 
|  | } | 
|  |  | 
|  | void OnIncomingStream(uint64_t channel_id, QuartcStream* stream) override { | 
|  | stream->SetDelegate(this); | 
|  | stream_to_channel_id_[stream] = channel_id; | 
|  | } | 
|  |  | 
|  | void OnMessageReceived(uint64_t channel_id, | 
|  | QuicStringPiece message) override { | 
|  | messages_received_.emplace_back(channel_id, message); | 
|  | } | 
|  |  | 
|  | // Stream delegate overrides. | 
|  | size_t OnReceived(QuartcStream* stream, | 
|  | iovec* iov, | 
|  | size_t iov_length, | 
|  | bool fin) override { | 
|  | if (!fin) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | size_t bytes = 0; | 
|  | std::string message; | 
|  | for (size_t i = 0; i < iov_length; ++i) { | 
|  | message += | 
|  | std::string(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); | 
|  | bytes += iov[i].iov_len; | 
|  | } | 
|  | QUIC_LOG(INFO) << "Received " << bytes << " byte message on channel " | 
|  | << stream_to_channel_id_[stream]; | 
|  | messages_received_.emplace_back(stream_to_channel_id_[stream], message); | 
|  | return bytes; | 
|  | } | 
|  |  | 
|  | void OnClose(QuartcStream* stream) override { | 
|  | stream_to_channel_id_.erase(stream); | 
|  | } | 
|  |  | 
|  | void OnBufferChanged(QuartcStream* /*stream*/) override {} | 
|  |  | 
|  | private: | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_received_; | 
|  | QuicUnorderedMap<QuartcStream*, uint64_t> stream_to_channel_id_; | 
|  | }; | 
|  |  | 
|  | class QuartcMultiplexerTest : public QuicTest { | 
|  | public: | 
|  | QuartcMultiplexerTest() | 
|  | : simulator_(), | 
|  | client_transport_(&simulator_, | 
|  | "client_transport", | 
|  | "server_transport", | 
|  | 10 * kDefaultMaxPacketSize), | 
|  | server_transport_(&simulator_, | 
|  | "server_transport", | 
|  | "client_transport", | 
|  | 10 * kDefaultMaxPacketSize), | 
|  | client_filter_(&simulator_, "client_filter", &client_transport_), | 
|  | client_server_link_(&client_filter_, | 
|  | &server_transport_, | 
|  | QuicBandwidth::FromKBitsPerSecond(10 * 1000), | 
|  | kPropagationDelay), | 
|  | client_multiplexer_(simulator_.GetStreamSendBufferAllocator(), | 
|  | &client_session_delegate_, | 
|  | &client_default_receiver_), | 
|  | server_multiplexer_(simulator_.GetStreamSendBufferAllocator(), | 
|  | &server_session_delegate_, | 
|  | &server_default_receiver_), | 
|  | client_endpoint_(QuicMakeUnique<QuartcClientEndpoint>( | 
|  | simulator_.GetAlarmFactory(), | 
|  | simulator_.GetClock(), | 
|  | simulator_.GetRandomGenerator(), | 
|  | &client_multiplexer_, | 
|  | quic::QuartcSessionConfig(), | 
|  | /*serialized_server_config=*/"")), | 
|  | server_endpoint_(QuicMakeUnique<QuartcServerEndpoint>( | 
|  | simulator_.GetAlarmFactory(), | 
|  | simulator_.GetClock(), | 
|  | simulator_.GetRandomGenerator(), | 
|  | &server_multiplexer_, | 
|  | quic::QuartcSessionConfig())) { | 
|  | // TODO(b/134175506): Remove when IETF QUIC supports receive timestamps. | 
|  | SetQuicReloadableFlag(quic_enable_version_99, false); | 
|  | } | 
|  |  | 
|  | void Connect() { | 
|  | client_endpoint_->Connect(&client_transport_); | 
|  | server_endpoint_->Connect(&server_transport_); | 
|  | ASSERT_TRUE(simulator_.RunUntil([this]() { | 
|  | return client_session_delegate_.writable_count() > 0 && | 
|  | server_session_delegate_.writable_count() > 0; | 
|  | })); | 
|  | } | 
|  |  | 
|  | void Disconnect() { | 
|  | client_session_delegate_.session()->CloseConnection("test"); | 
|  | server_session_delegate_.session()->CloseConnection("test"); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | QuartcMultiplexer* client_multiplexer() { return &client_multiplexer_; } | 
|  |  | 
|  | QuartcMultiplexer* server_multiplexer() { return &server_multiplexer_; } | 
|  |  | 
|  | simulator::Simulator simulator_; | 
|  |  | 
|  | simulator::SimulatedQuartcPacketTransport client_transport_; | 
|  | simulator::SimulatedQuartcPacketTransport server_transport_; | 
|  | simulator::CountingPacketFilter client_filter_; | 
|  | simulator::SymmetricLink client_server_link_; | 
|  |  | 
|  | FakeSessionEventDelegate client_session_delegate_; | 
|  | FakeSessionEventDelegate server_session_delegate_; | 
|  |  | 
|  | FakeReceiveDelegate client_default_receiver_; | 
|  | FakeReceiveDelegate server_default_receiver_; | 
|  |  | 
|  | QuartcMultiplexer client_multiplexer_; | 
|  | QuartcMultiplexer server_multiplexer_; | 
|  |  | 
|  | std::unique_ptr<QuartcClientEndpoint> client_endpoint_; | 
|  | std::unique_ptr<QuartcServerEndpoint> server_endpoint_; | 
|  | }; | 
|  |  | 
|  | TEST_F(QuartcMultiplexerTest, MultiplexMessages) { | 
|  | Connect(); | 
|  |  | 
|  | FakeSendDelegate send_delegate_1; | 
|  | QuartcSendChannel* send_channel_1 = | 
|  | client_multiplexer()->CreateSendChannel(1, &send_delegate_1); | 
|  | FakeSendDelegate send_delegate_2; | 
|  | QuartcSendChannel* send_channel_2 = | 
|  | client_multiplexer()->CreateSendChannel(2, &send_delegate_2); | 
|  |  | 
|  | FakeReceiveDelegate receive_delegate_1; | 
|  | server_multiplexer()->RegisterReceiveChannel(1, &receive_delegate_1); | 
|  |  | 
|  | int num_messages = 10; | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_1; | 
|  | messages_1.reserve(num_messages); | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_2; | 
|  | messages_2.reserve(num_messages); | 
|  | std::vector<int64_t> messages_sent_1; | 
|  | std::vector<int64_t> messages_sent_2; | 
|  | std::vector<testing::Matcher<std::pair<int64_t, QuicTime>>> ack_matchers_1; | 
|  | std::vector<testing::Matcher<std::pair<int64_t, QuicTime>>> ack_matchers_2; | 
|  | for (int i = 0; i < num_messages; ++i) { | 
|  | messages_1.emplace_back(1, QuicStrCat("message for 1: ", i)); | 
|  | test::QuicTestMemSliceVector slice_1( | 
|  | {std::make_pair(const_cast<char*>(messages_1.back().second.data()), | 
|  | messages_1.back().second.size())}); | 
|  | send_channel_1->SendOrQueueMessage(slice_1.span(), i); | 
|  | messages_sent_1.push_back(i); | 
|  | ack_matchers_1.push_back(Pair(i, Gt(QuicTime::Zero()))); | 
|  |  | 
|  | messages_2.emplace_back(2, QuicStrCat("message for 2: ", i)); | 
|  | test::QuicTestMemSliceVector slice_2( | 
|  | {std::make_pair(const_cast<char*>(messages_2.back().second.data()), | 
|  | messages_2.back().second.size())}); | 
|  | // Use i + 5 as the datagram id for channel 2, so that some of the ids | 
|  | // overlap and some are disjoint. | 
|  | send_channel_2->SendOrQueueMessage(slice_2.span(), i + 5); | 
|  | messages_sent_2.push_back(i + 5); | 
|  | ack_matchers_2.push_back(Pair(i + 5, Gt(QuicTime::Zero()))); | 
|  | } | 
|  |  | 
|  | EXPECT_TRUE(simulator_.RunUntil([&send_delegate_1, &send_delegate_2]() { | 
|  | return send_delegate_1.datagrams_acked().size() == 10 && | 
|  | send_delegate_2.datagrams_acked().size() == 10; | 
|  | })); | 
|  |  | 
|  | EXPECT_EQ(send_delegate_1.datagrams_sent(), messages_sent_1); | 
|  | EXPECT_EQ(send_delegate_2.datagrams_sent(), messages_sent_2); | 
|  |  | 
|  | EXPECT_EQ(receive_delegate_1.messages_received(), messages_1); | 
|  | EXPECT_EQ(server_default_receiver_.messages_received(), messages_2); | 
|  |  | 
|  | EXPECT_THAT(send_delegate_1.datagrams_acked(), | 
|  | ElementsAreArray(ack_matchers_1)); | 
|  | EXPECT_THAT(send_delegate_2.datagrams_acked(), | 
|  | ElementsAreArray(ack_matchers_2)); | 
|  | } | 
|  |  | 
|  | TEST_F(QuartcMultiplexerTest, MultiplexStreams) { | 
|  | FakeSendDelegate send_delegate_1; | 
|  | QuartcSendChannel* send_channel_1 = | 
|  | client_multiplexer()->CreateSendChannel(1, &send_delegate_1); | 
|  | FakeSendDelegate send_delegate_2; | 
|  | QuartcSendChannel* send_channel_2 = | 
|  | client_multiplexer()->CreateSendChannel(2, &send_delegate_2); | 
|  |  | 
|  | FakeQuartcStreamDelegate fake_send_stream_delegate; | 
|  |  | 
|  | FakeReceiveDelegate receive_delegate_1; | 
|  | server_multiplexer()->RegisterReceiveChannel(1, &receive_delegate_1); | 
|  |  | 
|  | Connect(); | 
|  |  | 
|  | int num_messages = 10; | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_1; | 
|  | messages_1.reserve(num_messages); | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_2; | 
|  | messages_2.reserve(num_messages); | 
|  | for (int i = 0; i < num_messages; ++i) { | 
|  | messages_1.emplace_back(1, QuicStrCat("message for 1: ", i)); | 
|  | test::QuicTestMemSliceVector slice_1( | 
|  | {std::make_pair(const_cast<char*>(messages_1.back().second.data()), | 
|  | messages_1.back().second.size())}); | 
|  | QuartcStream* stream_1 = | 
|  | send_channel_1->CreateOutgoingBidirectionalStream(); | 
|  | stream_1->SetDelegate(&fake_send_stream_delegate); | 
|  | stream_1->WriteMemSlices(slice_1.span(), /*fin=*/true); | 
|  |  | 
|  | messages_2.emplace_back(2, QuicStrCat("message for 2: ", i)); | 
|  | test::QuicTestMemSliceVector slice_2( | 
|  | {std::make_pair(const_cast<char*>(messages_2.back().second.data()), | 
|  | messages_2.back().second.size())}); | 
|  | QuartcStream* stream_2 = | 
|  | send_channel_2->CreateOutgoingBidirectionalStream(); | 
|  | stream_2->SetDelegate(&fake_send_stream_delegate); | 
|  | stream_2->WriteMemSlices(slice_2.span(), /*fin=*/true); | 
|  | } | 
|  |  | 
|  | EXPECT_TRUE(simulator_.RunUntilOrTimeout( | 
|  | [this, &receive_delegate_1]() { | 
|  | return receive_delegate_1.messages_received().size() == 10 && | 
|  | server_default_receiver_.messages_received().size() == 10; | 
|  | }, | 
|  | QuicTime::Delta::FromSeconds(5))); | 
|  |  | 
|  | EXPECT_EQ(receive_delegate_1.messages_received(), messages_1); | 
|  | EXPECT_EQ(server_default_receiver_.messages_received(), messages_2); | 
|  | } | 
|  |  | 
|  | // Tests that datagram-lost callbacks are invoked on the right send channel | 
|  | // delegate, and that they work with overlapping datagram ids. | 
|  | TEST_F(QuartcMultiplexerTest, MultiplexLostDatagrams) { | 
|  | Connect(); | 
|  | ASSERT_TRUE(simulator_.RunUntil([this]() { | 
|  | return client_session_delegate_.handshake_count() > 0 && | 
|  | server_session_delegate_.handshake_count() > 0; | 
|  | })); | 
|  |  | 
|  | // Just drop everything we try to send. | 
|  | client_filter_.set_packets_to_drop(30); | 
|  |  | 
|  | FakeSendDelegate send_delegate_1; | 
|  | QuartcSendChannel* send_channel_1 = | 
|  | client_multiplexer()->CreateSendChannel(1, &send_delegate_1); | 
|  | FakeSendDelegate send_delegate_2; | 
|  | QuartcSendChannel* send_channel_2 = | 
|  | client_multiplexer()->CreateSendChannel(2, &send_delegate_2); | 
|  |  | 
|  | FakeQuartcStreamDelegate fake_send_stream_delegate; | 
|  |  | 
|  | FakeReceiveDelegate receive_delegate_1; | 
|  | server_multiplexer()->RegisterReceiveChannel(1, &receive_delegate_1); | 
|  |  | 
|  | int num_messages = 10; | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_1; | 
|  | messages_1.reserve(num_messages); | 
|  | std::vector<std::pair<uint64_t, std::string>> messages_2; | 
|  | messages_2.reserve(num_messages); | 
|  | std::vector<int64_t> messages_sent_1; | 
|  | std::vector<int64_t> messages_sent_2; | 
|  | for (int i = 0; i < num_messages; ++i) { | 
|  | messages_1.emplace_back(1, QuicStrCat("message for 1: ", i)); | 
|  | test::QuicTestMemSliceVector slice_1( | 
|  | {std::make_pair(const_cast<char*>(messages_1.back().second.data()), | 
|  | messages_1.back().second.size())}); | 
|  | send_channel_1->SendOrQueueMessage(slice_1.span(), i); | 
|  | messages_sent_1.push_back(i); | 
|  |  | 
|  | messages_2.emplace_back(2, QuicStrCat("message for 2: ", i)); | 
|  | test::QuicTestMemSliceVector slice_2( | 
|  | {std::make_pair(const_cast<char*>(messages_2.back().second.data()), | 
|  | messages_2.back().second.size())}); | 
|  | // Use i + 5 as the datagram id for channel 2, so that some of the ids | 
|  | // overlap and some are disjoint. | 
|  | send_channel_2->SendOrQueueMessage(slice_2.span(), i + 5); | 
|  | messages_sent_2.push_back(i + 5); | 
|  | } | 
|  |  | 
|  | // Now send something retransmittable to prompt loss detection. | 
|  | // If we never send anything retransmittable, we will never get acks, and | 
|  | // never detect losses. | 
|  | messages_1.emplace_back(1, QuicStrCat("message for 1: ", num_messages)); | 
|  | test::QuicTestMemSliceVector slice( | 
|  | {std::make_pair(const_cast<char*>(messages_1.back().second.data()), | 
|  | messages_1.back().second.size())}); | 
|  | QuartcStream* stream_1 = send_channel_1->CreateOutgoingBidirectionalStream(); | 
|  | stream_1->SetDelegate(&fake_send_stream_delegate); | 
|  | stream_1->WriteMemSlices(slice.span(), /*fin=*/true); | 
|  |  | 
|  | EXPECT_TRUE(simulator_.RunUntilOrTimeout( | 
|  | [&send_delegate_1, &send_delegate_2]() { | 
|  | return send_delegate_1.datagrams_lost().size() == 10 && | 
|  | send_delegate_2.datagrams_lost().size() == 10; | 
|  | }, | 
|  | QuicTime::Delta::FromSeconds(60))); | 
|  |  | 
|  | EXPECT_EQ(send_delegate_1.datagrams_lost(), messages_sent_1); | 
|  | EXPECT_EQ(send_delegate_2.datagrams_lost(), messages_sent_2); | 
|  |  | 
|  | EXPECT_THAT(send_delegate_1.datagrams_acked(), IsEmpty()); | 
|  | EXPECT_THAT(send_delegate_2.datagrams_acked(), IsEmpty()); | 
|  |  | 
|  | EXPECT_THAT(receive_delegate_1.messages_received(), IsEmpty()); | 
|  | EXPECT_THAT(server_default_receiver_.messages_received(), IsEmpty()); | 
|  | } | 
|  |  | 
|  | TEST_F(QuartcMultiplexerTest, UnregisterReceiveChannel) { | 
|  | Connect(); | 
|  |  | 
|  | FakeSendDelegate send_delegate; | 
|  | QuartcSendChannel* send_channel = | 
|  | client_multiplexer()->CreateSendChannel(1, &send_delegate); | 
|  | FakeQuartcStreamDelegate fake_send_stream_delegate; | 
|  |  | 
|  | FakeReceiveDelegate receive_delegate; | 
|  | server_multiplexer()->RegisterReceiveChannel(1, &receive_delegate); | 
|  | server_multiplexer()->RegisterReceiveChannel(1, nullptr); | 
|  |  | 
|  | int num_messages = 10; | 
|  | std::vector<std::pair<uint64_t, std::string>> messages; | 
|  | messages.reserve(num_messages); | 
|  | std::vector<int64_t> messages_sent; | 
|  | std::vector<testing::Matcher<std::pair<int64_t, QuicTime>>> ack_matchers; | 
|  | for (int i = 0; i < num_messages; ++i) { | 
|  | messages.emplace_back(1, QuicStrCat("message for 1: ", i)); | 
|  | test::QuicTestMemSliceVector slice( | 
|  | {std::make_pair(const_cast<char*>(messages.back().second.data()), | 
|  | messages.back().second.size())}); | 
|  | send_channel->SendOrQueueMessage(slice.span(), i); | 
|  | messages_sent.push_back(i); | 
|  | ack_matchers.push_back(Pair(i, Gt(QuicTime::Zero()))); | 
|  | } | 
|  |  | 
|  | EXPECT_TRUE(simulator_.RunUntil([&send_delegate]() { | 
|  | return send_delegate.datagrams_acked().size() == 10; | 
|  | })); | 
|  |  | 
|  | EXPECT_EQ(send_delegate.datagrams_sent(), messages_sent); | 
|  | EXPECT_EQ(server_default_receiver_.messages_received(), messages); | 
|  | EXPECT_THAT(send_delegate.datagrams_acked(), ElementsAreArray(ack_matchers)); | 
|  | } | 
|  |  | 
|  | TEST_F(QuartcMultiplexerTest, CloseEvent) { | 
|  | Connect(); | 
|  | Disconnect(); | 
|  |  | 
|  | EXPECT_EQ(client_session_delegate_.error(), QUIC_CONNECTION_CANCELLED); | 
|  | EXPECT_EQ(server_session_delegate_.error(), QUIC_CONNECTION_CANCELLED); | 
|  | } | 
|  |  | 
|  | TEST_F(QuartcMultiplexerTest, CongestionEvent) { | 
|  | Connect(); | 
|  | ASSERT_TRUE(simulator_.RunUntil([this]() { | 
|  | return client_session_delegate_.handshake_count() > 0 && | 
|  | server_session_delegate_.handshake_count() > 0; | 
|  | })); | 
|  |  | 
|  | EXPECT_GT(client_session_delegate_.latest_bandwidth_estimate(), | 
|  | QuicBandwidth::Zero()); | 
|  | EXPECT_GT(client_session_delegate_.latest_pacing_rate(), | 
|  | QuicBandwidth::Zero()); | 
|  | EXPECT_GT(client_session_delegate_.latest_rtt(), QuicTime::Delta::Zero()); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace quic |