Fix memory safety issues in e2e test

This test contained multiple memory safety issues that would trigger if something failed. For example, if the handshake fails, there might not be a server connection and session created, and our code would previously use uninitialized memory as its session. Similarly, we would dereference header values even if we failed to find the right header, leading to use of uninitialized memory.

To fix these issues, this CL refactors some code to convenience methods that perform proper checks, and make sure the test is marked as failed if any of the convenience methods return early due to a missing object.

Note that we need to pause the server thread in order to safely access server variables, and we need to then resume the server thread even if there were failures, therefore tests cannot use ASSERTs when the server thread is paused.

gf-relnote: n/a, test-only change
PiperOrigin-RevId: 319255234
Change-Id: Ic1281bb2dd1217e1303fca1f20cb4275a343cc1c
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index f333264..02e1c66 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -122,8 +122,8 @@
     }
     for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
       params.push_back(TestParams(version, congestion_control_tag));
-    }    // End of outer version loop.
-  }      // End of congestion_control_tag loop.
+    }  // End of outer version loop.
+  }    // End of congestion_control_tag loop.
 
   return params;
 }
@@ -292,24 +292,72 @@
   }
 
   const QuicSentPacketManager* GetSentPacketManagerFromFirstServerSession() {
-    return &GetServerConnection()->sent_packet_manager();
+    QuicConnection* server_connection = GetServerConnection();
+    if (server_connection == nullptr) {
+      ADD_FAILURE() << "Missing server connection";
+      return nullptr;
+    }
+    return &server_connection->sent_packet_manager();
+  }
+
+  const QuicSentPacketManager* GetSentPacketManagerFromClientSession() {
+    QuicConnection* client_connection = GetClientConnection();
+    if (client_connection == nullptr) {
+      ADD_FAILURE() << "Missing client connection";
+      return nullptr;
+    }
+    return &client_connection->sent_packet_manager();
   }
 
   QuicSpdyClientSession* GetClientSession() {
+    if (!client_) {
+      ADD_FAILURE() << "Missing QuicTestClient";
+      return nullptr;
+    }
+    if (client_->client() == nullptr) {
+      ADD_FAILURE() << "Missing MockableQuicClient";
+      return nullptr;
+    }
     return client_->client()->client_session();
   }
 
   QuicConnection* GetClientConnection() {
-    return GetClientSession()->connection();
+    QuicSpdyClientSession* client_session = GetClientSession();
+    if (client_session == nullptr) {
+      ADD_FAILURE() << "Missing client session";
+      return nullptr;
+    }
+    return client_session->connection();
   }
 
   QuicConnection* GetServerConnection() {
-    return GetServerSession()->connection();
+    QuicSpdySession* server_session = GetServerSession();
+    if (server_session == nullptr) {
+      ADD_FAILURE() << "Missing server session";
+      return nullptr;
+    }
+    return server_session->connection();
   }
 
   QuicSpdySession* GetServerSession() {
-    QuicDispatcher* dispatcher =
-        QuicServerPeer::GetDispatcher(server_thread_->server());
+    if (!server_thread_) {
+      ADD_FAILURE() << "Missing server thread";
+      return nullptr;
+    }
+    QuicServer* quic_server = server_thread_->server();
+    if (quic_server == nullptr) {
+      ADD_FAILURE() << "Missing server";
+      return nullptr;
+    }
+    QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(quic_server);
+    if (dispatcher == nullptr) {
+      ADD_FAILURE() << "Missing dispatcher";
+      return nullptr;
+    }
+    if (dispatcher->session_map().empty()) {
+      ADD_FAILURE() << "Empty dispatcher session map";
+      return nullptr;
+    }
     EXPECT_EQ(1u, dispatcher->session_map().size());
     return static_cast<QuicSpdySession*>(
         dispatcher->session_map().begin()->second.get());
@@ -324,7 +372,7 @@
     // client as well according to the test parameter.
     copt.push_back(GetParam().congestion_control_tag);
     copt.push_back(k2PTO);
-    if (VersionHasIetfQuicFrames(version_.transport_version)) {
+    if (version_.HasIetfQuicFrames()) {
       copt.push_back(kILD0);
     }
     copt.push_back(kPLE1);
@@ -340,15 +388,29 @@
     }
 
     CreateClientWithWriter();
+    if (!client_) {
+      ADD_FAILURE() << "Missing QuicTestClient";
+      return false;
+    }
+    MockableQuicClient* client = client_->client();
+    if (client == nullptr) {
+      ADD_FAILURE() << "Missing MockableQuicClient";
+      return false;
+    }
     static QuicEpollEvent event(EPOLLOUT);
     if (client_writer_ != nullptr) {
+      QuicConnection* client_connection = GetClientConnection();
+      if (client_connection == nullptr) {
+        ADD_FAILURE() << "Missing client connection";
+        return false;
+      }
       client_writer_->Initialize(
-          QuicConnectionPeer::GetHelper(GetClientConnection()),
-          QuicConnectionPeer::GetAlarmFactory(GetClientConnection()),
-          std::make_unique<ClientDelegate>(client_->client()));
+          QuicConnectionPeer::GetHelper(client_connection),
+          QuicConnectionPeer::GetAlarmFactory(client_connection),
+          std::make_unique<ClientDelegate>(client));
     }
     initialized_ = true;
-    return client_->client()->connected();
+    return client->connected();
   }
 
   void SetUp() override {
@@ -359,9 +421,14 @@
   }
 
   void TearDown() override {
-    ASSERT_TRUE(initialized_) << "You must call Initialize() in every test "
+    EXPECT_TRUE(initialized_) << "You must call Initialize() in every test "
                               << "case. Otherwise, your test will leak memory.";
-    GetClientConnection()->set_debug_visitor(nullptr);
+    QuicConnection* client_connection = GetClientConnection();
+    if (client_connection != nullptr) {
+      client_connection->set_debug_visitor(nullptr);
+    } else {
+      ADD_FAILURE() << "Missing client connection";
+    }
     StopServer();
   }
 
@@ -430,7 +497,12 @@
   // Calls server_thread_ Pause() and Resume(), which may only be called once
   // per test.
   void VerifyCleanConnection(bool had_packet_loss) {
-    QuicConnectionStats client_stats = GetClientConnection()->GetStats();
+    QuicConnection* client_connection = GetClientConnection();
+    if (client_connection == nullptr) {
+      ADD_FAILURE() << "Missing client connection";
+      return;
+    }
+    QuicConnectionStats client_stats = client_connection->GetStats();
     // TODO(ianswett): Determine why this becomes even more flaky with BBR
     // enabled.  b/62141144
     if (!had_packet_loss && !GetQuicReloadableFlag(quic_default_to_bbr)) {
@@ -452,18 +524,32 @@
       EXPECT_EQ(client_stats.packets_received, client_stats.packets_processed);
     }
 
-    server_thread_->Pause();
-    QuicConnectionStats server_stats = GetServerConnection()->GetStats();
-    if (!had_packet_loss) {
-      EXPECT_EQ(0u, server_stats.packets_lost);
+    if (!server_thread_) {
+      ADD_FAILURE() << "Missing server thread";
+      return;
     }
-    EXPECT_EQ(0u, server_stats.packets_discarded);
-    if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
-      EXPECT_EQ(
-          GetServerSession()->user_agent_id().value_or("MissingUserAgent"),
-          kTestUserAgentId);
+    server_thread_->Pause();
+    QuicSpdySession* server_session = GetServerSession();
+    if (server_session != nullptr) {
+      QuicConnection* server_connection = server_session->connection();
+      if (server_connection != nullptr) {
+        QuicConnectionStats server_stats = server_connection->GetStats();
+        if (!had_packet_loss) {
+          EXPECT_EQ(0u, server_stats.packets_lost);
+        }
+        EXPECT_EQ(0u, server_stats.packets_discarded);
+        if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
+          EXPECT_EQ(
+              server_session->user_agent_id().value_or("MissingUserAgent"),
+              kTestUserAgentId);
+        } else {
+          EXPECT_FALSE(server_session->user_agent_id().has_value());
+        }
+      } else {
+        ADD_FAILURE() << "Missing server connection";
+      }
     } else {
-      EXPECT_FALSE(GetServerSession()->user_agent_id().has_value());
+      ADD_FAILURE() << "Missing server session";
     }
     // TODO(ianswett): Restore the check for packets_dropped equals 0.
     // The expect for packets received is equal to packets processed fails
@@ -478,7 +564,7 @@
   }
 
   bool SupportsIetfQuicWithTls(ParsedQuicVersion version) {
-    return VersionHasIetfInvariantHeader(version.transport_version) &&
+    return version.HasIetfInvariantHeader() &&
            version.handshake_protocol == PROTOCOL_TLS1_3;
   }
 
@@ -508,12 +594,90 @@
 
   QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
     return GetNthClientInitiatedBidirectionalStreamId(
-        GetClientConnection()->transport_version(), n);
+        version_.transport_version, n);
   }
 
   QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
     return GetNthServerInitiatedBidirectionalStreamId(
-        GetClientConnection()->transport_version(), n);
+        version_.transport_version, n);
+  }
+
+  bool CheckResponseHeaders(QuicTestClient* client,
+                            const std::string& expected_status) {
+    const spdy::SpdyHeaderBlock* response_headers = client->response_headers();
+    auto it = response_headers->find(":status");
+    if (it == response_headers->end()) {
+      ADD_FAILURE() << "Did not find :status header in response";
+      return false;
+    }
+    if (it->second != expected_status) {
+      ADD_FAILURE() << "Got bad :status response: \"" << it->second << "\"";
+      return false;
+    }
+    return true;
+  }
+
+  bool CheckResponseHeaders(QuicTestClient* client) {
+    return CheckResponseHeaders(client, "200");
+  }
+
+  bool CheckResponseHeaders(const std::string& expected_status) {
+    return CheckResponseHeaders(client_.get(), expected_status);
+  }
+
+  bool CheckResponseHeaders() { return CheckResponseHeaders(client_.get()); }
+
+  bool CheckResponse(QuicTestClient* client,
+                     const std::string& received_response,
+                     const std::string& expected_response) {
+    if (received_response.empty() && !expected_response.empty()) {
+      ADD_FAILURE() << "Failed to get any response for request";
+      return false;
+    }
+    if (received_response != expected_response) {
+      ADD_FAILURE() << "Got wrong response: \"" << received_response << "\"";
+      return false;
+    }
+    return CheckResponseHeaders(client);
+  }
+
+  bool SendSynchronousRequestAndCheckResponse(
+      QuicTestClient* client,
+      const std::string& request,
+      const std::string& expected_response) {
+    std::string received_response = client->SendSynchronousRequest(request);
+    return CheckResponse(client, received_response, expected_response);
+  }
+
+  bool SendSynchronousRequestAndCheckResponse(
+      const std::string& request,
+      const std::string& expected_response) {
+    return SendSynchronousRequestAndCheckResponse(client_.get(), request,
+                                                  expected_response);
+  }
+
+  bool SendSynchronousFooRequestAndCheckResponse(QuicTestClient* client) {
+    return SendSynchronousRequestAndCheckResponse(client, "/foo",
+                                                  kFooResponseBody);
+  }
+
+  bool SendSynchronousFooRequestAndCheckResponse() {
+    return SendSynchronousFooRequestAndCheckResponse(client_.get());
+  }
+
+  bool SendSynchronousBarRequestAndCheckResponse() {
+    std::string received_response = client_->SendSynchronousRequest("/bar");
+    return CheckResponse(client_.get(), received_response, kBarResponseBody);
+  }
+
+  bool WaitForFooResponseAndCheckIt(QuicTestClient* client) {
+    client->WaitForResponse();
+    std::string received_response = client->response_body();
+    return CheckResponse(client_.get(), received_response, kFooResponseBody);
+  }
+
+  bool WaitForFooResponseAndCheckIt() {
+    return WaitForFooResponseAndCheckIt(client_.get());
   }
 
   ScopedEnvironmentForThreads environment_;
@@ -554,39 +718,79 @@
 TEST_P(EndToEndTest, HandshakeSuccessful) {
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
+  ASSERT_TRUE(server_thread_);
   server_thread_->WaitForCryptoHandshakeConfirmed();
-  QuicCryptoStream* crypto_stream =
-      QuicSessionPeer::GetMutableCryptoStream(GetClientSession());
-  QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream);
-  EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
-  server_thread_->Pause();
-  crypto_stream = QuicSessionPeer::GetMutableCryptoStream(GetServerSession());
-  sequencer = QuicStreamPeer::sequencer(crypto_stream);
-  EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  QuicCryptoStream* client_crypto_stream =
+      QuicSessionPeer::GetMutableCryptoStream(client_session);
+  ASSERT_TRUE(client_crypto_stream);
+  QuicStreamSequencer* client_sequencer =
+      QuicStreamPeer::sequencer(client_crypto_stream);
+  ASSERT_TRUE(client_sequencer);
+  EXPECT_FALSE(
+      QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(client_sequencer));
 
   // We've had bugs in the past where the connections could end up on the wrong
   // version. This was never diagnosed but could have been due to in-connection
   // version negotiation back when that existed. At this point in time, our test
   // setup ensures that connections here always use |version_|, but we add this
   // sanity check out of paranoia to catch a regression of this type.
-  EXPECT_EQ(GetClientConnection()->version(), version_);
-  EXPECT_EQ(GetServerConnection()->version(), version_);
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_EQ(client_connection->version(), version_);
+
+  server_thread_->Pause();
+  QuicSpdySession* server_session = GetServerSession();
+  QuicConnection* server_connection = nullptr;
+  QuicCryptoStream* server_crypto_stream = nullptr;
+  QuicStreamSequencer* server_sequencer = nullptr;
+  if (server_session != nullptr) {
+    server_connection = server_session->connection();
+    server_crypto_stream =
+        QuicSessionPeer::GetMutableCryptoStream(server_session);
+  } else {
+    ADD_FAILURE() << "Missing server session";
+  }
+  if (server_crypto_stream != nullptr) {
+    server_sequencer = QuicStreamPeer::sequencer(server_crypto_stream);
+  } else {
+    ADD_FAILURE() << "Missing server crypto stream";
+  }
+  if (server_sequencer != nullptr) {
+    EXPECT_FALSE(
+        QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(server_sequencer));
+  } else {
+    ADD_FAILURE() << "Missing server sequencer";
+  }
+  if (server_connection != nullptr) {
+    EXPECT_EQ(server_connection->version(), version_);
+  } else {
+    ADD_FAILURE() << "Missing server connection";
+  }
+  server_thread_->Resume();
 }
 
 TEST_P(EndToEndTest, SimpleRequestResponse) {
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
-  if (VersionUsesHttp3(GetClientConnection()->transport_version())) {
-    EXPECT_TRUE(QuicSpdySessionPeer::GetSendControlStream(GetClientSession()));
-    EXPECT_TRUE(
-        QuicSpdySessionPeer::GetReceiveControlStream(GetClientSession()));
-    EXPECT_TRUE(QuicSpdySessionPeer::GetSendControlStream(GetServerSession()));
-    EXPECT_TRUE(
-        QuicSpdySessionPeer::GetReceiveControlStream(GetServerSession()));
+  if (version_.UsesHttp3()) {
+    QuicSpdyClientSession* client_session = GetClientSession();
+    ASSERT_TRUE(client_session);
+    EXPECT_TRUE(QuicSpdySessionPeer::GetSendControlStream(client_session));
+    EXPECT_TRUE(QuicSpdySessionPeer::GetReceiveControlStream(client_session));
+    server_thread_->Pause();
+    QuicSpdySession* server_session = GetServerSession();
+    if (server_session != nullptr) {
+      EXPECT_TRUE(QuicSpdySessionPeer::GetSendControlStream(server_session));
+      EXPECT_TRUE(QuicSpdySessionPeer::GetReceiveControlStream(server_session));
+    } else {
+      ADD_FAILURE() << "Missing server session";
+    }
+    server_thread_->Resume();
   }
 }
 
@@ -595,25 +799,32 @@
   if (!version_.UsesTls()) {
     return;
   }
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   // Verify handshake state.
-  EXPECT_EQ(HANDSHAKE_CONFIRMED, GetClientSession()->GetHandshakeState());
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_EQ(HANDSHAKE_CONFIRMED, client_session->GetHandshakeState());
   server_thread_->Pause();
-  EXPECT_EQ(HANDSHAKE_CONFIRMED, GetServerSession()->GetHandshakeState());
+  QuicSpdySession* server_session = GetServerSession();
+  if (server_session != nullptr) {
+    EXPECT_EQ(HANDSHAKE_CONFIRMED, server_session->GetHandshakeState());
+  } else {
+    ADD_FAILURE() << "Missing server session";
+  }
   server_thread_->Resume();
   client_->Disconnect();
 }
 
 TEST_P(EndToEndTest, SendAndReceiveCoalescedPackets) {
   ASSERT_TRUE(Initialize());
-  if (!GetClientConnection()->version().CanSendCoalescedPackets()) {
+  if (!version_.CanSendCoalescedPackets()) {
     return;
   }
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   // Verify client successfully processes coalesced packets.
-  QuicConnectionStats client_stats = GetClientConnection()->GetStats();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  QuicConnectionStats client_stats = client_connection->GetStats();
   EXPECT_LT(0u, client_stats.num_coalesced_packets_received);
   EXPECT_EQ(client_stats.num_coalesced_packets_processed,
             client_stats.num_coalesced_packets_received);
@@ -628,13 +839,21 @@
   client_config_.SetMaxAckDelayToSendMs(kClientMaxAckDelay);
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
-  EXPECT_EQ(kClientMaxAckDelay, GetSentPacketManagerFromFirstServerSession()
-                                    ->peer_max_ack_delay()
-                                    .ToMilliseconds());
+
+  server_thread_->Pause();
+  const QuicSentPacketManager* server_sent_packet_manager =
+      GetSentPacketManagerFromFirstServerSession();
+  if (server_sent_packet_manager != nullptr) {
+    EXPECT_EQ(
+        kClientMaxAckDelay,
+        server_sent_packet_manager->peer_max_ack_delay().ToMilliseconds());
+  } else {
+    ADD_FAILURE() << "Missing server sent packet manager";
+  }
+  server_thread_->Resume();
 }
 
 // Simple transaction, but set a non-default ack exponent at the client
@@ -647,23 +866,29 @@
   client_config_.SetAckDelayExponentToSend(kClientAckDelayExponent);
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
-  if (version_.UsesTls()) {
-    // Should be only sent with QUIC+TLS.
-    EXPECT_EQ(kClientAckDelayExponent,
-              GetServerConnection()->framer().peer_ack_delay_exponent());
-  } else {
-    // No change for QUIC_CRYPTO.
+  server_thread_->Pause();
+  QuicConnection* server_connection = GetServerConnection();
+  if (server_connection != nullptr) {
+    if (version_.UsesTls()) {
+      // Should be only sent with QUIC+TLS.
+      EXPECT_EQ(kClientAckDelayExponent,
+                server_connection->framer().peer_ack_delay_exponent());
+    } else {
+      // No change for QUIC_CRYPTO.
+      EXPECT_EQ(kDefaultAckDelayExponent,
+                server_connection->framer().peer_ack_delay_exponent());
+    }
+    // No change, regardless of version.
     EXPECT_EQ(kDefaultAckDelayExponent,
-              GetServerConnection()->framer().peer_ack_delay_exponent());
+              server_connection->framer().local_ack_delay_exponent());
+  } else {
+    ADD_FAILURE() << "Missing server connection";
   }
-  // No change, regardless of version.
-  EXPECT_EQ(kDefaultAckDelayExponent,
-            GetServerConnection()->framer().local_ack_delay_exponent());
+  server_thread_->Resume();
 }
 
 TEST_P(EndToEndTest, SimpleRequestResponseForcedVersionNegotiation) {
@@ -675,8 +900,7 @@
   ASSERT_TRUE(Initialize());
   ASSERT_TRUE(ServerSendsVersionNegotiation());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
@@ -688,8 +912,7 @@
   ASSERT_TRUE(Initialize());
   ASSERT_TRUE(ServerSendsVersionNegotiation());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
@@ -701,11 +924,12 @@
   expected_server_connection_id_length_ = 0;
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
-  EXPECT_EQ(GetClientConnection()->connection_id(),
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_EQ(client_connection->connection_id(),
             QuicUtils::CreateZeroConnectionId(version_.transport_version));
 }
 
@@ -718,9 +942,10 @@
   expected_server_connection_id_length_ = 0;
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_EQ(GetClientConnection()->connection_id(),
+  SendSynchronousFooRequestAndCheckResponse();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_EQ(client_connection->connection_id(),
             QuicUtils::CreateZeroConnectionId(version_.transport_version));
 }
 
@@ -731,8 +956,7 @@
   }
   override_server_connection_id_length_ = 9;
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
                                                 ->client_session()
                                                 ->connection()
@@ -749,8 +973,7 @@
   }
   override_server_connection_id_length_ = 16;
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
                                                 ->client_session()
                                                 ->connection()
@@ -765,8 +988,7 @@
   }
   override_client_connection_id_length_ = kQuicDefaultConnectionIdLength;
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(override_client_connection_id_length_, client_->client()
                                                        ->client_session()
                                                        ->connection()
@@ -784,8 +1006,7 @@
   override_client_connection_id_length_ = kQuicDefaultConnectionIdLength;
   ASSERT_TRUE(Initialize());
   ASSERT_TRUE(ServerSendsVersionNegotiation());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(override_client_connection_id_length_, client_->client()
                                                        ->client_session()
                                                        ->connection()
@@ -803,8 +1024,7 @@
   override_server_connection_id_length_ = 9;
   ASSERT_TRUE(Initialize());
   ASSERT_TRUE(ServerSendsVersionNegotiation());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
                                                 ->client_session()
                                                 ->connection()
@@ -826,8 +1046,7 @@
   override_client_connection_id_length_ = 18;
   ASSERT_TRUE(Initialize());
   ASSERT_TRUE(ServerSendsVersionNegotiation());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
                                                 ->client_session()
                                                 ->connection()
@@ -862,17 +1081,14 @@
   client2->SendMessage(headers, "", /*fin=*/false);
   client2->SendData("eep", true);
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
                                                 ->client_session()
                                                 ->connection()
                                                 ->connection_id()
                                                 .length());
 
-  client2->WaitForResponse();
-  EXPECT_EQ(kFooResponseBody, client2->response_body());
-  EXPECT_EQ("200", client2->response_headers()->find(":status")->second);
+  WaitForFooResponseAndCheckIt(client2.get());
   EXPECT_EQ(kQuicDefaultConnectionIdLength, client2->client()
                                                 ->client_session()
                                                 ->connection()
@@ -888,16 +1104,14 @@
   QuicVersionInitializeSupportForIetfDraft();
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) {
   chlo_multiplier_ = 1;
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   if (version_.UsesTls()) {
     // REJ messages are a QUIC crypto feature, so TLS always returns false.
@@ -912,24 +1126,21 @@
       QuicSocketAddress(QuicIpAddress::Loopback6(), server_address_.port());
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest,
        ClientDoesNotAllowServerDataOnServerInitiatedBidirectionalStreams) {
   set_client_initial_max_stream_data_incoming_bidirectional(0);
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest,
        ServerDoesNotAllowClientDataOnServerInitiatedBidirectionalStreams) {
   set_server_initial_max_stream_data_outgoing_bidirectional(0);
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest,
@@ -937,8 +1148,7 @@
   set_client_initial_max_stream_data_incoming_bidirectional(0);
   set_server_initial_max_stream_data_outgoing_bidirectional(0);
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 // Regression test for a bug where we would always fail to decrypt the first
@@ -948,19 +1158,25 @@
 TEST_P(EndToEndTest, NoUndecryptablePacketsBeforeHandshakeComplete) {
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
-  QuicConnectionStats client_stats = GetClientConnection()->GetStats();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  QuicConnectionStats client_stats = client_connection->GetStats();
   EXPECT_EQ(
       0u,
       client_stats.undecryptable_packets_received_before_handshake_complete);
 
   server_thread_->Pause();
-  QuicConnectionStats server_stats = GetServerConnection()->GetStats();
-  EXPECT_EQ(
-      0u,
-      server_stats.undecryptable_packets_received_before_handshake_complete);
+  QuicConnection* server_connection = GetServerConnection();
+  if (server_connection != nullptr) {
+    QuicConnectionStats server_stats = server_connection->GetStats();
+    EXPECT_EQ(
+        0u,
+        server_stats.undecryptable_packets_received_before_handshake_complete);
+  } else {
+    ADD_FAILURE() << "Missing server connection";
+  }
   server_thread_->Resume();
 }
 
@@ -975,26 +1191,20 @@
   headers[":authority"] = server_hostname_;
   client_->SendMessage(headers, "", /*fin=*/false);
   client_->SendData("", true);
-  client_->WaitForResponse();
-  EXPECT_EQ(kFooResponseBody, client_->response_body());
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  WaitForFooResponseAndCheckIt();
 
   // Now do the same thing but with a content length.
   headers["content-length"] = "3";
   client_->SendMessage(headers, "", /*fin=*/false);
   client_->SendData("foo", true);
-  client_->WaitForResponse();
-  EXPECT_EQ(kFooResponseBody, client_->response_body());
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  WaitForFooResponseAndCheckIt();
 }
 
 TEST_P(EndToEndTest, MultipleRequestResponse) {
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
+  SendSynchronousBarRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, MultipleRequestResponseZeroConnectionID) {
@@ -1006,10 +1216,8 @@
   expected_server_connection_id_length_ = 0;
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
+  SendSynchronousBarRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, MultipleStreams) {
@@ -1031,9 +1239,7 @@
 
   while (kNumRequests > client_->num_responses()) {
     client_->ClearPerRequestState();
-    client_->WaitForResponse();
-    EXPECT_EQ(kFooResponseBody, client_->response_body());
-    EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+    WaitForFooResponseAndCheckIt();
   }
 }
 
@@ -1052,14 +1258,10 @@
   client2->SendMessage(headers, "", /*fin=*/false);
 
   client_->SendData("bar", true);
-  client_->WaitForResponse();
-  EXPECT_EQ(kFooResponseBody, client_->response_body());
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  WaitForFooResponseAndCheckIt();
 
   client2->SendData("eep", true);
-  client2->WaitForResponse();
-  EXPECT_EQ(kFooResponseBody, client2->response_body());
-  EXPECT_EQ("200", client2->response_headers()->find(":status")->second);
+  WaitForFooResponseAndCheckIt(client2.get());
 }
 
 TEST_P(EndToEndTest, RequestOverMultiplePackets) {
@@ -1070,8 +1272,7 @@
 
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest(huge_request));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousRequestAndCheckResponse(huge_request, kBarResponseBody);
 }
 
 TEST_P(EndToEndTest, MultiplePacketsRandomOrder) {
@@ -1084,8 +1285,7 @@
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
   SetReorderPercentage(50);
 
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest(huge_request));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousRequestAndCheckResponse(huge_request, kBarResponseBody);
 }
 
 TEST_P(EndToEndTest, PostMissingBytes) {
@@ -1104,7 +1304,7 @@
   client_->SendCustomSynchronousRequest(headers, "");
   EXPECT_EQ(QuicSimpleServerStream::kErrorResponseBody,
             client_->response_body());
-  EXPECT_EQ("500", client_->response_headers()->find(":status")->second);
+  CheckResponseHeaders("500");
 }
 
 TEST_P(EndToEndTest, LargePostNoPacketLoss) {
@@ -1182,8 +1382,14 @@
   // kMaxConsecutiveNonRetransmittablePackets ack-only packets. Setting the max
   // to 0 to reliably reproduce b/80090281.
   server_thread_->Schedule([this]() {
-    QuicConnectionPeer::SetMaxConsecutiveNumPacketsWithNoRetransmittableFrames(
-        GetServerConnection(), 0);
+    QuicConnection* server_connection = GetServerConnection();
+    if (server_connection != nullptr) {
+      QuicConnectionPeer::
+          SetMaxConsecutiveNumPacketsWithNoRetransmittableFrames(
+              server_connection, 0);
+    } else {
+      ADD_FAILURE() << "Missing server connection";
+    }
   });
 
   SetPacketLossPercentage(30);
@@ -1257,8 +1463,10 @@
 
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
-  EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
-  EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_FALSE(client_session->EarlyDataAccepted());
+  EXPECT_FALSE(client_session->ReceivedInchoateReject());
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
 
@@ -1271,7 +1479,9 @@
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
 
-  EXPECT_TRUE(GetClientSession()->EarlyDataAccepted());
+  client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_TRUE(client_session->EarlyDataAccepted());
   EXPECT_TRUE(client_->client()->EarlyDataAccepted());
 
   client_->Disconnect();
@@ -1286,8 +1496,10 @@
   ASSERT_TRUE(client_->client()->connected());
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
-  EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
-  EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+  client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_FALSE(client_session->EarlyDataAccepted());
+  EXPECT_FALSE(client_session->ReceivedInchoateReject());
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
 
@@ -1300,8 +1512,10 @@
   ASSERT_TRUE(Initialize());
 
   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
-  EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_FALSE(client_session->EarlyDataAccepted());
+  EXPECT_FALSE(client_session->ReceivedInchoateReject());
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
 
@@ -1313,7 +1527,9 @@
   ASSERT_TRUE(client_->client()->connected());
   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
 
-  EXPECT_TRUE(GetClientSession()->EarlyDataAccepted());
+  client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_TRUE(client_session->EarlyDataAccepted());
   EXPECT_TRUE(client_->client()->EarlyDataAccepted());
 
   client_->Disconnect();
@@ -1328,8 +1544,10 @@
   ASSERT_TRUE(client_->client()->connected());
   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
 
-  EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
-  EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+  client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_FALSE(client_session->EarlyDataAccepted());
+  EXPECT_FALSE(client_session->ReceivedInchoateReject());
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
 
@@ -1350,8 +1568,10 @@
 
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
-  EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
-  EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_FALSE(client_session->EarlyDataAccepted());
+  EXPECT_FALSE(client_session->ReceivedInchoateReject());
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
 
@@ -1364,7 +1584,9 @@
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
 
-  EXPECT_TRUE(GetClientSession()->EarlyDataAccepted());
+  client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_TRUE(client_session->EarlyDataAccepted());
   EXPECT_TRUE(client_->client()->EarlyDataAccepted());
 
   client_->Disconnect();
@@ -1380,8 +1602,10 @@
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
 
-  EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
-  EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+  client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  EXPECT_FALSE(client_session->EarlyDataAccepted());
+  EXPECT_FALSE(client_session->ReceivedInchoateReject());
   EXPECT_FALSE(client_->client()->EarlyDataAccepted());
   EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
 
@@ -1462,6 +1686,7 @@
       server_config_.GetInitialStreamFlowControlWindowToSend();
   QuicSpdyClientStream* stream = client_->GetOrCreateStream();
   QuicSession* session = GetClientSession();
+  ASSERT_TRUE(session);
   QuicFlowControllerPeer::SetSendWindowOffset(stream->flow_controller(), 0);
   QuicFlowControllerPeer::SetSendWindowOffset(session->flow_controller(), 0);
   EXPECT_TRUE(stream->flow_controller()->IsBlocked());
@@ -1502,6 +1727,7 @@
   // Force the client to write with a stream ID belonging to a nonexistent
   // server-side stream.
   QuicSpdySession* session = GetClientSession();
+  ASSERT_TRUE(session);
   QuicSessionPeer::SetNextOutgoingBidirectionalStreamId(
       session, GetNthServerInitiatedBidirectionalId(0));
 
@@ -1529,7 +1755,7 @@
 
   client_->SendCustomSynchronousRequest(headers, body);
 
-  if (VersionUsesHttp3(GetClientConnection()->transport_version())) {
+  if (version_.UsesHttp3()) {
     // QuicSpdyStream::OnHeadersTooLarge() resets the stream with
     // QUIC_HEADERS_TOO_LARGE.  This is sent as H3_EXCESSIVE_LOAD, the closest
     // HTTP/3 error code, and translated back to QUIC_STREAM_EXCESSIVE_LOAD on
@@ -1558,7 +1784,7 @@
 
   client_->SendCustomSynchronousRequest(headers, large_body);
   EXPECT_EQ("bad", client_->response_body());
-  EXPECT_EQ("500", client_->response_headers()->find(":status")->second);
+  CheckResponseHeaders("500");
   EXPECT_THAT(client_->stream_error(), IsQuicStreamNoError());
   EXPECT_THAT(client_->connection_error(), IsQuicNoError());
 }
@@ -1600,7 +1826,7 @@
   const uint32_t kServerMaxDynamicStreams = 1;
   server_config_.SetMaxBidirectionalStreamsToSend(kServerMaxDynamicStreams);
   ASSERT_TRUE(Initialize());
-  if (VersionHasIetfQuicFrames(version_.transport_version)) {
+  if (version_.HasIetfQuicFrames()) {
     // Do not run this test for /IETF QUIC. This test relies on the fact that
     // Google QUIC allows a small number of additional streams beyond the
     // negotiated limit, which is not supported in IETF QUIC. Note that the test
@@ -1614,7 +1840,9 @@
 
   // Make the client misbehave after negotiation.
   const int kServerMaxStreams = kMaxStreamsMinimumIncrement + 1;
-  QuicSessionPeer::SetMaxOpenOutgoingStreams(GetClientSession(),
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  QuicSessionPeer::SetMaxOpenOutgoingStreams(client_session,
                                              kServerMaxStreams + 1);
 
   SpdyHeaderBlock headers;
@@ -1650,6 +1878,7 @@
 
   // The client has received the server's limit and vice versa.
   QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
   // The value returned by max_allowed... includes the Crypto and Header
   // stream (created as a part of initialization). The config. values,
   // above, are treated as "number of requests/responses" - that is, they do
@@ -1657,15 +1886,13 @@
   // returned by max_allowed... by 2 to remove the static streams from the
   // count.
   size_t client_max_open_outgoing_bidirectional_streams =
-      VersionHasIetfQuicFrames(
-          client_session->connection()->transport_version())
+      version_.HasIetfQuicFrames()
           ? QuicSessionPeer::v99_streamid_manager(client_session)
                 ->max_outgoing_bidirectional_streams()
           : QuicSessionPeer::GetStreamIdManager(client_session)
                 ->max_open_outgoing_streams();
   size_t client_max_open_outgoing_unidirectional_streams =
-      VersionHasIetfQuicFrames(
-          client_session->connection()->transport_version())
+      version_.HasIetfQuicFrames()
           ? QuicSessionPeer::v99_streamid_manager(client_session)
                     ->max_outgoing_unidirectional_streams() -
                 kHttp3StaticUnidirectionalStreamCount
@@ -1677,26 +1904,27 @@
             client_max_open_outgoing_unidirectional_streams);
   server_thread_->Pause();
   QuicSession* server_session = GetServerSession();
-  size_t server_max_open_outgoing_bidirectional_streams =
-      VersionHasIetfQuicFrames(
-          server_session->connection()->transport_version())
-          ? QuicSessionPeer::v99_streamid_manager(server_session)
-                ->max_outgoing_bidirectional_streams()
-          : QuicSessionPeer::GetStreamIdManager(server_session)
-                ->max_open_outgoing_streams();
-  size_t server_max_open_outgoing_unidirectional_streams =
-      VersionHasIetfQuicFrames(
-          server_session->connection()->transport_version())
-          ? QuicSessionPeer::v99_streamid_manager(server_session)
-                    ->max_outgoing_unidirectional_streams() -
-                kHttp3StaticUnidirectionalStreamCount
-          : QuicSessionPeer::GetStreamIdManager(server_session)
-                ->max_open_outgoing_streams();
-  EXPECT_EQ(kClientMaxDynamicStreams,
-            server_max_open_outgoing_bidirectional_streams);
-  EXPECT_EQ(kClientMaxDynamicStreams,
-            server_max_open_outgoing_unidirectional_streams);
-
+  if (server_session != nullptr) {
+    size_t server_max_open_outgoing_bidirectional_streams =
+        version_.HasIetfQuicFrames()
+            ? QuicSessionPeer::v99_streamid_manager(server_session)
+                  ->max_outgoing_bidirectional_streams()
+            : QuicSessionPeer::GetStreamIdManager(server_session)
+                  ->max_open_outgoing_streams();
+    size_t server_max_open_outgoing_unidirectional_streams =
+        version_.HasIetfQuicFrames()
+            ? QuicSessionPeer::v99_streamid_manager(server_session)
+                      ->max_outgoing_unidirectional_streams() -
+                  kHttp3StaticUnidirectionalStreamCount
+            : QuicSessionPeer::GetStreamIdManager(server_session)
+                  ->max_open_outgoing_streams();
+    EXPECT_EQ(kClientMaxDynamicStreams,
+              server_max_open_outgoing_bidirectional_streams);
+    EXPECT_EQ(kClientMaxDynamicStreams,
+              server_max_open_outgoing_unidirectional_streams);
+  } else {
+    ADD_FAILURE() << "Missing server session";
+  }
   server_thread_->Resume();
 }
 
@@ -1724,10 +1952,16 @@
   }
 
   server_thread_->Pause();
-  EXPECT_EQ(expected_congestion_control_type,
-            QuicSentPacketManagerPeer::GetSendAlgorithm(
-                *GetSentPacketManagerFromFirstServerSession())
-                ->GetCongestionControlType());
+  const QuicSentPacketManager* server_sent_packet_manager =
+      GetSentPacketManagerFromFirstServerSession();
+  if (server_sent_packet_manager != nullptr) {
+    EXPECT_EQ(
+        expected_congestion_control_type,
+        QuicSentPacketManagerPeer::GetSendAlgorithm(*server_sent_packet_manager)
+            ->GetCongestionControlType());
+  } else {
+    ADD_FAILURE() << "Missing server sent packet manager";
+  }
   server_thread_->Resume();
 }
 
@@ -1738,22 +1972,24 @@
 
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
+  ASSERT_TRUE(server_thread_);
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Pause the server so we can access the server's internals without races.
   server_thread_->Pause();
-  QuicDispatcher* dispatcher =
-      QuicServerPeer::GetDispatcher(server_thread_->server());
-  ASSERT_EQ(1u, dispatcher->session_map().size());
-  const QuicSentPacketManager& client_sent_packet_manager =
-      GetClientConnection()->sent_packet_manager();
+  const QuicSentPacketManager* client_sent_packet_manager =
+      GetSentPacketManagerFromClientSession();
   const QuicSentPacketManager* server_sent_packet_manager =
       GetSentPacketManagerFromFirstServerSession();
-
-  EXPECT_EQ(kInitialRTT,
-            client_sent_packet_manager.GetRttStats()->initial_rtt());
-  EXPECT_EQ(kInitialRTT,
-            server_sent_packet_manager->GetRttStats()->initial_rtt());
+  if (client_sent_packet_manager != nullptr &&
+      server_sent_packet_manager != nullptr) {
+    EXPECT_EQ(kInitialRTT,
+              client_sent_packet_manager->GetRttStats()->initial_rtt());
+    EXPECT_EQ(kInitialRTT,
+              server_sent_packet_manager->GetRttStats()->initial_rtt());
+  } else {
+    ADD_FAILURE() << "Missing sent packet manager";
+  }
   server_thread_->Resume();
 }
 
@@ -1767,22 +2003,24 @@
 
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
+  ASSERT_TRUE(server_thread_);
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Pause the server so we can access the server's internals without races.
   server_thread_->Pause();
-  QuicDispatcher* dispatcher =
-      QuicServerPeer::GetDispatcher(server_thread_->server());
-  ASSERT_EQ(1u, dispatcher->session_map().size());
-  const QuicSentPacketManager& client_sent_packet_manager =
-      GetClientConnection()->sent_packet_manager();
+  const QuicSentPacketManager* client_sent_packet_manager =
+      GetSentPacketManagerFromClientSession();
   const QuicSentPacketManager* server_sent_packet_manager =
       GetSentPacketManagerFromFirstServerSession();
-
-  EXPECT_EQ(kInitialRTT,
-            client_sent_packet_manager.GetRttStats()->initial_rtt());
-  EXPECT_EQ(kInitialRTT,
-            server_sent_packet_manager->GetRttStats()->initial_rtt());
+  if (client_sent_packet_manager != nullptr &&
+      server_sent_packet_manager != nullptr) {
+    EXPECT_EQ(kInitialRTT,
+              client_sent_packet_manager->GetRttStats()->initial_rtt());
+    EXPECT_EQ(kInitialRTT,
+              server_sent_packet_manager->GetRttStats()->initial_rtt());
+  } else {
+    ADD_FAILURE() << "Missing sent packet manager";
+  }
   server_thread_->Resume();
 }
 
@@ -1794,23 +2032,30 @@
 
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
+  ASSERT_TRUE(server_thread_);
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Pause the server so we can access the server's internals without races.
   server_thread_->Pause();
-  const QuicSentPacketManager& client_sent_packet_manager =
-      GetClientConnection()->sent_packet_manager();
-
-  // Now that acks have been exchanged, the RTT estimate has decreased on the
-  // server and is not infinite on the client.
-  EXPECT_FALSE(
-      client_sent_packet_manager.GetRttStats()->smoothed_rtt().IsInfinite());
-  const RttStats& server_rtt_stats =
-      *GetServerConnection()->sent_packet_manager().GetRttStats();
-  EXPECT_EQ(static_cast<int64_t>(kMaxInitialRoundTripTimeUs),
-            server_rtt_stats.initial_rtt().ToMicroseconds());
-  EXPECT_GE(static_cast<int64_t>(kMaxInitialRoundTripTimeUs),
-            server_rtt_stats.smoothed_rtt().ToMicroseconds());
+  const QuicSentPacketManager* client_sent_packet_manager =
+      GetSentPacketManagerFromClientSession();
+  const QuicSentPacketManager* server_sent_packet_manager =
+      GetSentPacketManagerFromFirstServerSession();
+  if (client_sent_packet_manager != nullptr &&
+      server_sent_packet_manager != nullptr) {
+    // Now that acks have been exchanged, the RTT estimate has decreased on the
+    // server and is not infinite on the client.
+    EXPECT_FALSE(
+        client_sent_packet_manager->GetRttStats()->smoothed_rtt().IsInfinite());
+    const RttStats* server_rtt_stats =
+        server_sent_packet_manager->GetRttStats();
+    EXPECT_EQ(static_cast<int64_t>(kMaxInitialRoundTripTimeUs),
+              server_rtt_stats->initial_rtt().ToMicroseconds());
+    EXPECT_GE(static_cast<int64_t>(kMaxInitialRoundTripTimeUs),
+              server_rtt_stats->smoothed_rtt().ToMicroseconds());
+  } else {
+    ADD_FAILURE() << "Missing sent packet manager";
+  }
   server_thread_->Resume();
 }
 
@@ -1824,26 +2069,30 @@
 
   // Pause the server so we can access the server's internals without races.
   server_thread_->Pause();
-  const QuicSentPacketManager& client_sent_packet_manager =
-      GetClientConnection()->sent_packet_manager();
-  const QuicSentPacketManager& server_sent_packet_manager =
-      GetServerConnection()->sent_packet_manager();
-
-  // Now that acks have been exchanged, the RTT estimate has decreased on the
-  // server and is not infinite on the client.
-  EXPECT_FALSE(
-      client_sent_packet_manager.GetRttStats()->smoothed_rtt().IsInfinite());
-  // Expect the default rtt of 100ms.
-  EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
-            server_sent_packet_manager.GetRttStats()->initial_rtt());
-  // Ensure the bandwidth is valid.
-  client_sent_packet_manager.BandwidthEstimate();
-  server_sent_packet_manager.BandwidthEstimate();
+  const QuicSentPacketManager* client_sent_packet_manager =
+      GetSentPacketManagerFromClientSession();
+  const QuicSentPacketManager* server_sent_packet_manager =
+      GetSentPacketManagerFromFirstServerSession();
+  if (client_sent_packet_manager != nullptr &&
+      server_sent_packet_manager != nullptr) {
+    // Now that acks have been exchanged, the RTT estimate has decreased on the
+    // server and is not infinite on the client.
+    EXPECT_FALSE(
+        client_sent_packet_manager->GetRttStats()->smoothed_rtt().IsInfinite());
+    // Expect the default rtt of 100ms.
+    EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
+              server_sent_packet_manager->GetRttStats()->initial_rtt());
+    // Ensure the bandwidth is valid.
+    client_sent_packet_manager->BandwidthEstimate();
+    server_sent_packet_manager->BandwidthEstimate();
+  } else {
+    ADD_FAILURE() << "Missing sent packet manager";
+  }
   server_thread_->Resume();
 }
 
 TEST_P(EndToEndTest, 0ByteConnectionId) {
-  if (VersionHasIetfInvariantHeader(version_.transport_version)) {
+  if (version_.HasIetfInvariantHeader()) {
     // SetBytesForConnectionIdToSend only applies to Google QUIC encoding.
     ASSERT_TRUE(Initialize());
     return;
@@ -1851,16 +2100,16 @@
   client_config_.SetBytesForConnectionIdToSend(0);
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicPacketHeader* header =
       QuicConnectionPeer::GetLastHeader(client_connection);
   EXPECT_EQ(CONNECTION_ID_ABSENT, header->source_connection_id_included);
 }
 
 TEST_P(EndToEndTest, 8ByteConnectionId) {
-  if (VersionHasIetfInvariantHeader(version_.transport_version)) {
+  if (version_.HasIetfInvariantHeader()) {
     // SetBytesForConnectionIdToSend only applies to Google QUIC encoding.
     ASSERT_TRUE(Initialize());
     return;
@@ -1868,16 +2117,16 @@
   client_config_.SetBytesForConnectionIdToSend(8);
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicPacketHeader* header =
       QuicConnectionPeer::GetLastHeader(client_connection);
   EXPECT_EQ(CONNECTION_ID_PRESENT, header->destination_connection_id_included);
 }
 
 TEST_P(EndToEndTest, 15ByteConnectionId) {
-  if (VersionHasIetfInvariantHeader(version_.transport_version)) {
+  if (version_.HasIetfInvariantHeader()) {
     // SetBytesForConnectionIdToSend only applies to Google QUIC encoding.
     ASSERT_TRUE(Initialize());
     return;
@@ -1886,9 +2135,9 @@
   ASSERT_TRUE(Initialize());
 
   // Our server is permissive and allows for out of bounds values.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicPacketHeader* header =
       QuicConnectionPeer::GetLastHeader(client_connection);
   EXPECT_EQ(CONNECTION_ID_PRESENT, header->destination_connection_id_included);
@@ -1897,12 +2146,10 @@
 TEST_P(EndToEndTest, ResetConnection) {
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
   client_->ResetConnection();
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousBarRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, MaxStreamsUberTest) {
@@ -1937,6 +2184,7 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
 
   QuicSession* session = GetClientSession();
+  ASSERT_TRUE(session);
   // Lose the request.
   SetPacketLossPercentage(100);
   EXPECT_LT(0, client_->SendRequest("/small_response"));
@@ -1957,8 +2205,7 @@
 
 TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) {
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Store the client IP address which was used to send the first request.
   QuicIpAddress old_host =
@@ -1970,8 +2217,7 @@
   ASSERT_TRUE(client_->client()->MigrateSocket(new_host));
 
   // Send a request using the new socket.
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousBarRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
@@ -1980,8 +2226,7 @@
   // closed by the server.
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Store the client address which was used to send the first request.
   QuicSocketAddress old_address =
@@ -2006,13 +2251,11 @@
   int new_port =
       client_->client()->network_helper()->GetLatestClientAddress().port();
   QuicClientPeer::SetClientPort(client_->client(), new_port);
-  QuicConnectionPeer::SetSelfAddress(GetClientConnection(),
-                                     QuicSocketAddress(client_->client()
-                                                           ->client_session()
-                                                           ->connection()
-                                                           ->self_address()
-                                                           .host(),
-                                                       new_port));
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  QuicConnectionPeer::SetSelfAddress(
+      client_connection,
+      QuicSocketAddress(client_connection->self_address().host(), new_port));
 
   // Register the new FD for epoll events.
   int new_fd = client_->client()->GetLatestFD();
@@ -2021,8 +2264,7 @@
                   EPOLLIN | EPOLLOUT | EPOLLET);
 
   // Send a second request, using the new FD.
-  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousBarRequestAndCheckResponse();
 
   // Verify that the client's ephemeral port is different.
   QuicSocketAddress new_address =
@@ -2041,10 +2283,15 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   server_thread_->WaitForCryptoHandshakeConfirmed();
   server_thread_->Pause();
-
-  QuicPacketCount cwnd =
-      GetServerConnection()->sent_packet_manager().initial_congestion_window();
-  EXPECT_EQ(3u, cwnd);
+  QuicConnection* server_connection = GetServerConnection();
+  if (server_connection != nullptr) {
+    QuicPacketCount cwnd =
+        server_connection->sent_packet_manager().initial_congestion_window();
+    EXPECT_EQ(3u, cwnd);
+  } else {
+    ADD_FAILURE() << "Missing server connection";
+  }
+  server_thread_->Resume();
 }
 
 TEST_P(EndToEndTest, DifferentFlowControlWindows) {
@@ -2096,14 +2343,22 @@
   }
   EXPECT_EQ(kServerStreamIFCW, QuicFlowControllerPeer::SendWindowOffset(
                                    stream->flow_controller()));
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
   EXPECT_EQ(kServerSessionIFCW, QuicFlowControllerPeer::SendWindowOffset(
-                                    GetClientSession()->flow_controller()));
+                                    client_session->flow_controller()));
 
   // Server should have the right values for client's receive window.
   server_thread_->Pause();
-  QuicConfig server_config = *GetServerSession()->config();
+  QuicSpdySession* server_session = GetServerSession();
+  if (server_session == nullptr) {
+    ADD_FAILURE() << "Missing server session";
+    server_thread_->Resume();
+    return;
+  }
+  QuicConfig server_config = *server_session->config();
   EXPECT_EQ(kClientSessionIFCW, QuicFlowControllerPeer::SendWindowOffset(
-                                    GetServerSession()->flow_controller()));
+                                    server_session->flow_controller()));
   server_thread_->Resume();
   if (version_.UsesTls()) {
     // IFWA only exists with QUIC_CRYPTO.
@@ -2145,32 +2400,27 @@
   WriteHeadersOnStream(stream);
   stream->WriteOrBufferBody("hello", false);
 
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+
   if (!version_.UsesTls()) {
     // IFWA only exists with QUIC_CRYPTO.
     // Client should have the right values for server's receive window.
-    ASSERT_TRUE(client_->client()
-                    ->client_session()
-                    ->config()
+    ASSERT_TRUE(client_session->config()
                     ->HasReceivedInitialStreamFlowControlWindowBytes());
     EXPECT_EQ(kExpectedStreamIFCW,
-              client_->client()
-                  ->client_session()
-                  ->config()
+              client_session->config()
                   ->ReceivedInitialStreamFlowControlWindowBytes());
-    ASSERT_TRUE(client_->client()
-                    ->client_session()
-                    ->config()
+    ASSERT_TRUE(client_session->config()
                     ->HasReceivedInitialSessionFlowControlWindowBytes());
     EXPECT_EQ(kExpectedSessionIFCW,
-              client_->client()
-                  ->client_session()
-                  ->config()
+              client_session->config()
                   ->ReceivedInitialSessionFlowControlWindowBytes());
   }
   EXPECT_EQ(kExpectedStreamIFCW, QuicFlowControllerPeer::SendWindowOffset(
                                      stream->flow_controller()));
   EXPECT_EQ(kExpectedSessionIFCW, QuicFlowControllerPeer::SendWindowOffset(
-                                      GetClientSession()->flow_controller()));
+                                      client_session->flow_controller()));
 }
 
 TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) {
@@ -2191,22 +2441,23 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
   QuicCryptoStream* crypto_stream =
-      QuicSessionPeer::GetMutableCryptoStream(GetClientSession());
+      QuicSessionPeer::GetMutableCryptoStream(client_session);
+  ASSERT_TRUE(crypto_stream);
   // In v47 and later, the crypto handshake (sent in CRYPTO frames) is not
   // subject to flow control.
-  const QuicTransportVersion transport_version =
-      GetClientConnection()->transport_version();
-  if (!QuicVersionUsesCryptoFrames(transport_version)) {
+  if (!version_.UsesCryptoFrames()) {
     EXPECT_LT(QuicFlowControllerPeer::SendWindowSize(
                   crypto_stream->flow_controller()),
               kStreamIFCW);
   }
   // When stream type is enabled, control streams will send settings and
   // contribute to flow control windows, so this expectation is no longer valid.
-  if (!VersionUsesHttp3(transport_version)) {
+  if (!version_.UsesHttp3()) {
     EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::SendWindowSize(
-                                GetClientSession()->flow_controller()));
+                                client_session->flow_controller()));
   }
 
   // Send a request with no body, and verify that the connection level window
@@ -2214,26 +2465,31 @@
   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
 
   // No headers stream in IETF QUIC.
-  if (VersionUsesHttp3(transport_version)) {
+  if (version_.UsesHttp3()) {
     return;
   }
 
   QuicHeadersStream* headers_stream =
-      QuicSpdySessionPeer::GetHeadersStream(GetClientSession());
+      QuicSpdySessionPeer::GetHeadersStream(client_session);
+  ASSERT_TRUE(headers_stream);
   EXPECT_LT(
       QuicFlowControllerPeer::SendWindowSize(headers_stream->flow_controller()),
       kStreamIFCW);
   EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::SendWindowSize(
-                              GetClientSession()->flow_controller()));
+                              client_session->flow_controller()));
 
   // Server should be in a similar state: connection flow control window should
   // not have any bytes marked as received.
   server_thread_->Pause();
-  QuicSession* session = GetServerSession();
-  QuicFlowController* server_connection_flow_controller =
-      session->flow_controller();
-  EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::ReceiveWindowSize(
-                              server_connection_flow_controller));
+  QuicSession* server_session = GetServerSession();
+  if (server_session != nullptr) {
+    QuicFlowController* server_connection_flow_controller =
+        server_session->flow_controller();
+    EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::ReceiveWindowSize(
+                                server_connection_flow_controller));
+  } else {
+    ADD_FAILURE() << "Missing server session";
+  }
   server_thread_->Resume();
 }
 
@@ -2246,10 +2502,9 @@
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   QuicSpdySession* const client_session = GetClientSession();
-  const QuicTransportVersion version =
-      client_session->connection()->transport_version();
+  ASSERT_TRUE(client_session);
 
-  if (VersionUsesHttp3(version)) {
+  if (version_.UsesHttp3()) {
     // Make sure that the client has received the initial SETTINGS frame, which
     // is sent in the first packet on the control stream.
     while (!QuicSpdySessionPeer::GetReceiveControlStream(client_session)) {
@@ -2266,10 +2521,15 @@
   server_thread_->Pause();
 
   QuicSpdySession* const server_session = GetServerSession();
+  if (server_session == nullptr) {
+    ADD_FAILURE() << "Missing server session";
+    server_thread_->Resume();
+    return;
+  }
   ExpectFlowControlsSynced(client_session, server_session);
 
   // Check control streams.
-  if (VersionUsesHttp3(version)) {
+  if (version_.UsesHttp3()) {
     ExpectFlowControlsSynced(
         QuicSpdySessionPeer::GetReceiveControlStream(client_session),
         QuicSpdySessionPeer::GetSendControlStream(server_session));
@@ -2279,14 +2539,14 @@
   }
 
   // Check crypto stream.
-  if (!QuicVersionUsesCryptoFrames(version)) {
+  if (!version_.UsesCryptoFrames()) {
     ExpectFlowControlsSynced(
         QuicSessionPeer::GetMutableCryptoStream(client_session),
         QuicSessionPeer::GetMutableCryptoStream(server_session));
   }
 
   // Check headers stream.
-  if (!VersionUsesHttp3(version)) {
+  if (!version_.UsesHttp3()) {
     SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
     SpdySettingsIR settings_frame;
     settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE,
@@ -2347,15 +2607,18 @@
   ASSERT_TRUE(Initialize());
 
   // Send a simple headers only request, and receive response.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Now verify that the server is not waiting for a final FIN or RST.
   server_thread_->Pause();
-  QuicSession* session = GetServerSession();
-  EXPECT_EQ(
-      0u,
-      QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(session).size());
+  QuicSession* server_session = GetServerSession();
+  if (server_session != nullptr) {
+    EXPECT_EQ(0u, QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(
+                      server_session)
+                      .size());
+  } else {
+    ADD_FAILURE() << "Missing server session";
+  }
   server_thread_->Resume();
 }
 
@@ -2412,11 +2675,22 @@
     while (true) {
       // Waits for up to 50 ms.
       client_->client()->WaitForEvents();
-      if (!GetClientSession() || !GetClientSession()->qpack_encoder()) {
-        continue;
+      QuicSpdyClientSession* client_session = GetClientSession();
+      if (client_session == nullptr) {
+        ADD_FAILURE() << "Missing client session";
+        break;
+      }
+      QpackEncoder* qpack_encoder = client_session->qpack_encoder();
+      if (qpack_encoder == nullptr) {
+        ADD_FAILURE() << "Missing QPACK encoder";
+        break;
       }
       QpackHeaderTable* header_table =
-          QpackEncoderPeer::header_table(GetClientSession()->qpack_encoder());
+          QpackEncoderPeer::header_table(qpack_encoder);
+      if (header_table == nullptr) {
+        ADD_FAILURE() << "Missing header table";
+        break;
+      }
       if (QpackHeaderTablePeer::dynamic_table_capacity(header_table) > 0) {
         break;
       }
@@ -2466,9 +2740,7 @@
 
   // Send the request, and register the delegate for ACKs.
   client_->SendData(request_string, true, ack_listener);
-  client_->WaitForResponse();
-  EXPECT_EQ(kFooResponseBody, client_->response_body());
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  WaitForFooResponseAndCheckIt();
 
   // Send another request to flush out any pending ACKs on the server.
   client_->SendSynchronousRequest("/bar");
@@ -2488,19 +2760,23 @@
   ASSERT_TRUE(Initialize());
 
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-  QuicConnection* client_connection = GetClientConnection();
-  QuicConfig* config = client_->client()->session()->config();
+  QuicSpdySession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  QuicConfig* config = client_session->config();
+  ASSERT_TRUE(config);
   EXPECT_TRUE(config->HasReceivedStatelessResetToken());
   QuicUint128 stateless_reset_token = config->ReceivedStatelessResetToken();
 
   // Send the public reset.
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicConnectionId connection_id = client_connection->connection_id();
   QuicPublicResetPacket header;
   header.connection_id = connection_id;
   QuicFramer framer(server_supported_versions_, QuicTime::Zero(),
                     Perspective::IS_SERVER, kQuicDefaultConnectionIdLength);
   std::unique_ptr<QuicEncryptedPacket> packet;
-  if (VersionHasIetfInvariantHeader(client_connection->transport_version())) {
+  if (version_.HasIetfInvariantHeader()) {
     packet = framer.BuildIetfStatelessResetPacket(connection_id,
                                                   stateless_reset_token);
   } else {
@@ -2526,11 +2802,15 @@
   ASSERT_TRUE(Initialize());
 
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-  QuicConnection* client_connection = GetClientConnection();
-  QuicConfig* config = client_->client()->session()->config();
+  QuicSpdySession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  QuicConfig* config = client_session->config();
+  ASSERT_TRUE(config);
   EXPECT_TRUE(config->HasReceivedStatelessResetToken());
   QuicUint128 stateless_reset_token = config->ReceivedStatelessResetToken();
   // Send the public reset.
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicConnectionId incorrect_connection_id = TestConnectionId(
       TestConnectionIdToUInt64(client_connection->connection_id()) + 1);
   QuicPublicResetPacket header;
@@ -2539,8 +2819,8 @@
                     Perspective::IS_SERVER, kQuicDefaultConnectionIdLength);
   std::unique_ptr<QuicEncryptedPacket> packet;
   NiceMock<MockQuicConnectionDebugVisitor> visitor;
-  GetClientConnection()->set_debug_visitor(&visitor);
-  if (VersionHasIetfInvariantHeader(client_connection->transport_version())) {
+  client_connection->set_debug_visitor(&visitor);
+  if (version_.HasIetfInvariantHeader()) {
     packet = framer.BuildIetfStatelessResetPacket(incorrect_connection_id,
                                                   stateless_reset_token);
     EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id))
@@ -2558,19 +2838,18 @@
       client_->client()->network_helper()->GetLatestClientAddress(), nullptr);
   server_thread_->Resume();
 
-  if (VersionHasIetfInvariantHeader(client_connection->transport_version())) {
+  if (version_.HasIetfInvariantHeader()) {
     // The request should fail. IETF stateless reset does not include connection
     // ID.
     EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
     EXPECT_TRUE(client_->response_headers()->empty());
     EXPECT_THAT(client_->connection_error(), IsError(QUIC_PUBLIC_RESET));
-    return;
+  } else {
+    // The connection should be unaffected.
+    SendSynchronousFooRequestAndCheckResponse();
   }
-  // The connection should be unaffected.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
 
-  GetClientConnection()->set_debug_visitor(nullptr);
+  client_connection->set_debug_visitor(nullptr);
 }
 
 // Send a public reset from the client for a different connection ID.
@@ -2579,8 +2858,10 @@
   ASSERT_TRUE(Initialize());
 
   // Send the public reset.
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicConnectionId incorrect_connection_id = TestConnectionId(
-      TestConnectionIdToUInt64(GetClientConnection()->connection_id()) + 1);
+      TestConnectionIdToUInt64(client_connection->connection_id()) + 1);
   QuicPublicResetPacket header;
   header.connection_id = incorrect_connection_id;
   QuicFramer framer(server_supported_versions_, QuicTime::Zero(),
@@ -2593,8 +2874,7 @@
       server_address_, nullptr);
 
   // The connection should be unaffected.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 // Send a version negotiation packet from the server for a different
@@ -2606,13 +2886,14 @@
 
   // Send the version negotiation packet.
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   QuicConnectionId incorrect_connection_id = TestConnectionId(
       TestConnectionIdToUInt64(client_connection->connection_id()) + 1);
   std::unique_ptr<QuicEncryptedPacket> packet(
       QuicFramer::BuildVersionNegotiationPacket(
           incorrect_connection_id, EmptyQuicConnectionId(),
-          VersionHasIetfInvariantHeader(client_connection->transport_version()),
-          client_connection->version().HasLengthPrefixedConnectionIds(),
+          version_.HasIetfInvariantHeader(),
+          version_.HasLengthPrefixedConnectionIds(),
           server_supported_versions_));
   NiceMock<MockQuicConnectionDebugVisitor> visitor;
   client_connection->set_debug_visitor(&visitor);
@@ -2627,8 +2908,7 @@
   server_thread_->Resume();
 
   // The connection should be unaffected.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   client_connection->set_debug_visitor(nullptr);
 }
@@ -2639,8 +2919,7 @@
   ASSERT_TRUE(Initialize());
 
   // Start the connection.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Packet with invalid public flags.
   char packet[] = {// public flags (8 byte connection_id)
@@ -2660,8 +2939,7 @@
       QuicTime::Delta::FromSeconds(5)));
 
   // The connection should not be terminated.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 // A bad header shouldn't tear down the connection, because the receiver can't
@@ -2670,8 +2948,7 @@
   ASSERT_TRUE(Initialize());
 
   // Start the connection.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Packet with invalid public flags.
   char packet[] = {
@@ -2710,8 +2987,7 @@
       QuicTime::Delta::FromSeconds(5)));
 
   // The connection should not be terminated.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 // Send a packet from the client with bad encrypted data.  The server should not
@@ -2720,13 +2996,14 @@
   ASSERT_TRUE(Initialize());
 
   // Start the connection.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
-      GetClientConnection()->connection_id(), EmptyQuicConnectionId(), false,
-      false, 1, "At least 20 characters.", CONNECTION_ID_PRESENT,
-      CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER));
+      client_connection->connection_id(), EmptyQuicConnectionId(), false, false,
+      1, "At least 20 characters.", CONNECTION_ID_PRESENT, CONNECTION_ID_ABSENT,
+      PACKET_4BYTE_PACKET_NUMBER));
   // Damage the encrypted data.
   std::string damaged_packet(packet->data(), packet->length());
   damaged_packet[30] ^= 0x01;
@@ -2743,13 +3020,16 @@
   server_thread_->Pause();
   QuicDispatcher* dispatcher =
       QuicServerPeer::GetDispatcher(server_thread_->server());
-  EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
-              IsQuicNoError());
+  if (dispatcher != nullptr) {
+    EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
+                IsQuicNoError());
+  } else {
+    ADD_FAILURE() << "Missing dispatcher";
+  }
   server_thread_->Resume();
 
   // The connection should not be terminated.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 TEST_P(EndToEndTest, CanceledStreamDoesNotBecomeZombie) {
@@ -2768,6 +3048,7 @@
   // Cancel the stream.
   stream->Reset(QUIC_STREAM_CANCELLED);
   QuicSession* session = GetClientSession();
+  ASSERT_TRUE(session);
   // Verify canceled stream does not become zombie.
   EXPECT_TRUE(QuicSessionPeer::zombie_streams(session).empty());
   EXPECT_EQ(1u, QuicSessionPeer::closed_streams(session).size());
@@ -2979,7 +3260,7 @@
   // Send the request.
   client_->SendMessage(headers, request_body);
   client_->WaitForResponse();
-  EXPECT_EQ("500", client_->response_headers()->find(":status")->second);
+  CheckResponseHeaders("500");
 
   // Pause the server so we can access the server's internals without races.
   server_thread_->Pause();
@@ -3024,8 +3305,7 @@
                                     std::move(headers), kBody,
                                     trailers.Clone());
 
-  EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousRequestAndCheckResponse("/trailer_url", kBody);
   EXPECT_EQ(trailers, client_->response_trailers());
 }
 
@@ -3113,11 +3393,15 @@
   QUIC_DVLOG(1) << "send request for /push_example";
   EXPECT_EQ(kBody, client_->SendSynchronousRequest(
                        "https://example.com/push_example"));
-  QuicStreamSequencer* sequencer;
+  QuicStreamSequencer* sequencer = nullptr;
   if (!version_.UsesHttp3()) {
+    QuicSpdyClientSession* client_session = GetClientSession();
+    ASSERT_TRUE(client_session);
     QuicHeadersStream* headers_stream =
-        QuicSpdySessionPeer::GetHeadersStream(GetClientSession());
+        QuicSpdySessionPeer::GetHeadersStream(client_session);
+    ASSERT_TRUE(headers_stream);
     sequencer = QuicStreamPeer::sequencer(headers_stream);
+    ASSERT_TRUE(sequencer);
     // Headers stream's sequencer buffer shouldn't be released because server
     // push hasn't finished yet.
     EXPECT_TRUE(
@@ -3133,6 +3417,7 @@
     EXPECT_EQ(expected_body, response_body);
   }
   if (!version_.UsesHttp3()) {
+    ASSERT_TRUE(sequencer);
     EXPECT_FALSE(
         QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
   }
@@ -3305,9 +3590,14 @@
   // though more resources need to be pushed.
   if (!version_.HasIetfQuicFrames()) {
     server_thread_->Pause();
-    EXPECT_EQ(kNumMaxStreams,
-              QuicSessionPeer::GetStreamIdManager(GetServerSession())
-                  ->num_open_outgoing_streams());
+    QuicSession* server_session = GetServerSession();
+    if (server_session != nullptr) {
+      EXPECT_EQ(kNumMaxStreams,
+                QuicSessionPeer::GetStreamIdManager(server_session)
+                    ->num_open_outgoing_streams());
+    } else {
+      ADD_FAILURE() << "Missing server session";
+    }
     server_thread_->Resume();
   }
 
@@ -3399,9 +3689,11 @@
   client->Connect();
   client_.reset(client);
   static QuicEpollEvent event(EPOLLOUT);
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   client_writer_->Initialize(
-      QuicConnectionPeer::GetHelper(GetClientConnection()),
-      QuicConnectionPeer::GetAlarmFactory(GetClientConnection()),
+      QuicConnectionPeer::GetHelper(client_connection),
+      QuicConnectionPeer::GetAlarmFactory(client_connection),
       std::make_unique<ClientDelegate>(client_->client()));
   initialized_ = true;
   ASSERT_TRUE(client_->client()->connected());
@@ -3419,12 +3711,17 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
 
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   server_thread_->Pause();
   QuicConnection* server_connection = GetServerConnection();
-  // Verify client and server connections agree on the value of
-  // no_stop_waiting_frames.
-  EXPECT_EQ(QuicConnectionPeer::GetNoStopWaitingFrames(client_connection),
-            QuicConnectionPeer::GetNoStopWaitingFrames(server_connection));
+  if (server_connection != nullptr) {
+    // Verify client and server connections agree on the value of
+    // no_stop_waiting_frames.
+    EXPECT_EQ(QuicConnectionPeer::GetNoStopWaitingFrames(client_connection),
+              QuicConnectionPeer::GetNoStopWaitingFrames(server_connection));
+  } else {
+    ADD_FAILURE() << "Missing server connection";
+  }
   server_thread_->Resume();
 }
 
@@ -3437,12 +3734,17 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
 
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   server_thread_->Pause();
   QuicConnection* server_connection = GetServerConnection();
-  // Verify client and server connections agree on the value of
-  // no_stop_waiting_frames.
-  EXPECT_EQ(QuicConnectionPeer::GetNoStopWaitingFrames(client_connection),
-            QuicConnectionPeer::GetNoStopWaitingFrames(server_connection));
+  if (server_connection != nullptr) {
+    // Verify client and server connections agree on the value of
+    // no_stop_waiting_frames.
+    EXPECT_EQ(QuicConnectionPeer::GetNoStopWaitingFrames(client_connection),
+              QuicConnectionPeer::GetNoStopWaitingFrames(server_connection));
+  } else {
+    ADD_FAILURE() << "Missing server connection";
+  }
   server_thread_->Resume();
 }
 
@@ -3451,15 +3753,16 @@
   // PUSH_PROMISE, its headers stream's sequencer buffer should be released.
   ASSERT_TRUE(Initialize());
   client_->SendSynchronousRequest("/foo");
-  if (VersionUsesHttp3(client_->client()
-                           ->client_session()
-                           ->connection()
-                           ->transport_version())) {
+  if (version_.UsesHttp3()) {
     return;
   }
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
   QuicHeadersStream* headers_stream =
-      QuicSpdySessionPeer::GetHeadersStream(GetClientSession());
+      QuicSpdySessionPeer::GetHeadersStream(client_session);
+  ASSERT_TRUE(headers_stream);
   QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream);
+  ASSERT_TRUE(sequencer);
   EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
 }
 
@@ -3481,7 +3784,7 @@
 
   client_->SendMessage(headers, "");
   client_->WaitForResponse();
-  if (VersionUsesHttp3(version_.transport_version)) {
+  if (version_.UsesHttp3()) {
     EXPECT_THAT(client_->connection_error(),
                 IsError(QUIC_QPACK_DECOMPRESSION_FAILED));
   } else {
@@ -3517,6 +3820,7 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   WindowUpdateObserver observer;
   QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   client_connection->set_debug_visitor(&observer);
   // 100KB body.
   std::string body(100 * 1024, 'a');
@@ -3531,15 +3835,21 @@
   client_->Disconnect();
   EXPECT_LT(0u, observer.num_window_update_frames());
   EXPECT_EQ(0u, observer.num_ping_frames());
+  client_connection->set_debug_visitor(nullptr);
 }
 
 TEST_P(EndToEndTest, SendStatelessResetTokenInShlo) {
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-  QuicConfig* config = client_->client()->session()->config();
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  QuicConfig* config = client_session->config();
+  ASSERT_TRUE(config);
   EXPECT_TRUE(config->HasReceivedStatelessResetToken());
+  QuicConnection* client_connection = client_session->connection();
+  ASSERT_TRUE(client_connection);
   EXPECT_EQ(QuicUtils::GenerateStatelessResetToken(
-                client_->client()->session()->connection()->connection_id()),
+                client_connection->connection_id()),
             config->ReceivedStatelessResetToken());
   client_->Disconnect();
 }
@@ -3550,10 +3860,20 @@
   connect_to_server_on_initialize_ = false;
   ASSERT_TRUE(Initialize());
 
+  ASSERT_TRUE(server_thread_);
   server_thread_->Pause();
   QuicDispatcher* dispatcher =
       QuicServerPeer::GetDispatcher(server_thread_->server());
-  ASSERT_EQ(0u, dispatcher->session_map().size());
+  if (dispatcher == nullptr) {
+    ADD_FAILURE() << "Missing dispatcher";
+    server_thread_->Resume();
+    return;
+  }
+  if (!dispatcher->session_map().empty()) {
+    ADD_FAILURE() << "Dispatcher session map not empty";
+    server_thread_->Resume();
+    return;
+  }
   // Note: this writer will only used by the server connection, not the time
   // wait list.
   QuicDispatcherPeer::UseWriter(
@@ -3581,10 +3901,20 @@
                              kBigResponseBodySize, /*owns_buffer=*/true);
   AddToCache("/big_response", 200, big_response_body.AsStringPiece());
 
+  ASSERT_TRUE(server_thread_);
   server_thread_->Pause();
   QuicDispatcher* dispatcher =
       QuicServerPeer::GetDispatcher(server_thread_->server());
-  ASSERT_EQ(0u, dispatcher->session_map().size());
+  if (dispatcher == nullptr) {
+    ADD_FAILURE() << "Missing dispatcher";
+    server_thread_->Resume();
+    return;
+  }
+  if (!dispatcher->session_map().empty()) {
+    ADD_FAILURE() << "Dispatcher session map not empty";
+    server_thread_->Resume();
+    return;
+  }
   QuicDispatcherPeer::UseWriter(
       dispatcher,
       // This will cause an server write error with EPERM, while sending the
@@ -3595,8 +3925,7 @@
   client_.reset(CreateQuicClient(client_writer_));
 
   // First, a /foo request with small response should succeed.
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Second, a /big_response request with big response should fail.
   EXPECT_LT(client_->SendSynchronousRequest("/big_response").length(),
@@ -3629,8 +3958,7 @@
 TEST_P(EndToEndTest, LastPacketSentIsConnectivityProbing) {
   ASSERT_TRUE(Initialize());
 
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 
   // Wait for the client's ACK (of the response) to be received by the server.
   client_->WaitForDelayedAcks();
@@ -3663,8 +3991,7 @@
 
   ASSERT_TRUE(Initialize());
 
-  ASSERT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+  SendSynchronousFooRequestAndCheckResponse();
 }
 
 // TODO: reenable once we have a way to make this run faster.
@@ -3755,15 +4082,16 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   client_->WaitForDelayedAcks();
 
-  QuicSession* session = GetClientSession();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
   const QuicPacketCount packets_sent_before =
-      session->connection()->GetStats().packets_sent;
+      client_connection->GetStats().packets_sent;
 
   client_->SendRequestAndRstTogether("/test_url");
 
   // Expect exactly one packet is sent from the block above.
   ASSERT_EQ(packets_sent_before + 1,
-            session->connection()->GetStats().packets_sent);
+            client_connection->GetStats().packets_sent);
 
   // Wait for the connection to become idle.
   client_->WaitForDelayedAcks();
@@ -3790,14 +4118,16 @@
 }
 
 TEST_P(EndToEndTest, SendMessages) {
-  if (!VersionSupportsMessageFrames(version_.transport_version)) {
+  if (!version_.SupportsMessageFrames()) {
     Initialize();
     return;
   }
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   QuicSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
   QuicConnection* client_connection = client_session->connection();
+  ASSERT_TRUE(client_connection);
 
   SetPacketLossPercentage(30);
   ASSERT_GT(kMaxOutgoingPacketSize,
@@ -3814,9 +4144,7 @@
     // Verify the largest message gets successfully sent.
     EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
               client_session->SendMessage(MakeSpan(
-                  client_session->connection()
-                      ->helper()
-                      ->GetStreamSendBufferAllocator(),
+                  client_connection->helper()->GetStreamSendBufferAllocator(),
                   quiche::QuicheStringPiece(
                       message_buffer.data(),
                       client_session->GetCurrentLargestMessagePayload()),
@@ -3830,9 +4158,7 @@
               client_session->GetGuaranteedLargestMessagePayload() +
           1;
       MessageResult result = client_session->SendMessage(MakeSpan(
-          client_session->connection()
-              ->helper()
-              ->GetStreamSendBufferAllocator(),
+          client_connection->helper()->GetStreamSendBufferAllocator(),
           quiche::QuicheStringPiece(message_buffer.data(), message_length),
           &storage));
       if (result.status == MESSAGE_STATUS_BLOCKED) {
@@ -3847,9 +4173,7 @@
   EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
             client_session
                 ->SendMessage(MakeSpan(
-                    client_session->connection()
-                        ->helper()
-                        ->GetStreamSendBufferAllocator(),
+                    client_connection->helper()->GetStreamSendBufferAllocator(),
                     quiche::QuicheStringPiece(
                         message_buffer.data(),
                         client_session->GetCurrentLargestMessagePayload() + 1),
@@ -3921,15 +4245,21 @@
 
   server_thread_->Pause();
   QuicConnection* server_connection = GetServerConnection();
-  EXPECT_EQ(1u,
-            server_connection->GetStats().num_connectivity_probing_received);
+  if (server_connection != nullptr) {
+    EXPECT_EQ(1u,
+              server_connection->GetStats().num_connectivity_probing_received);
+  } else {
+    ADD_FAILURE() << "Missing server connection";
+  }
   server_thread_->Resume();
 
   // Server definitely responded to the connectivity probing. Sometime it also
   // sends a padded ping that is not a connectivity probing, which is recognized
   // as connectivity probing because client's self address is ANY.
-  EXPECT_LE(
-      1u, GetClientConnection()->GetStats().num_connectivity_probing_received);
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_LE(1u,
+            client_connection->GetStats().num_connectivity_probing_received);
 }
 
 TEST_P(EndToEndPacketReorderingTest, Buffer0RttRequest) {
@@ -3958,7 +4288,9 @@
   client_->SendMessage(headers, "");
   client_->WaitForResponse();
   EXPECT_EQ(kBarResponseBody, client_->response_body());
-  QuicConnectionStats client_stats = GetClientConnection()->GetStats();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  QuicConnectionStats client_stats = client_connection->GetStats();
   // Client sends CHLO in packet 1 and retransmitted in packet 2. Because of
   // the delay, server processes packet 2 and later drops packet 1. ACK is
   // bundled with SHLO, such that 1 can be detected loss by time threshold.
@@ -3999,14 +4331,14 @@
 TEST_P(EndToEndTest, SimpleStopSendingTest) {
   const uint16_t kStopSendingTestCode = 123;
   ASSERT_TRUE(Initialize());
-  if (!VersionHasIetfQuicFrames(version_.transport_version)) {
+  if (!version_.HasIetfQuicFrames()) {
     return;
   }
   QuicSession* client_session = GetClientSession();
-  ASSERT_NE(nullptr, client_session);
+  ASSERT_TRUE(client_session);
   StopSendingObserver observer(client_.get());
   QuicConnection* client_connection = client_session->connection();
-  ASSERT_NE(nullptr, client_connection);
+  ASSERT_TRUE(client_connection);
   client_connection->set_debug_visitor(&observer);
 
   std::string response_body(1305, 'a');
@@ -4021,9 +4353,8 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   client_->WaitForDelayedAcks();
 
-  QuicSession* session = GetClientSession();
-
-  QuicStreamId stream_id = session->next_outgoing_bidirectional_stream_id();
+  QuicStreamId stream_id =
+      client_session->next_outgoing_bidirectional_stream_id();
   client_->SendRequest("/test_url");
   // Wait for the connection to become idle.
   client_->WaitForDelayedAcks();
@@ -4031,16 +4362,20 @@
   EXPECT_THAT(client_->connection_error(), IsQuicNoError());
   QuicSimpleClientStream* client_stream =
       static_cast<QuicSimpleClientStream*>(client_->latest_created_stream());
-  ASSERT_NE(nullptr, client_stream);
-  // Ensure the stream has been write closed upon receiving STOP_SENDING.
-  EXPECT_EQ(stream_id, client_stream->id());
-  EXPECT_TRUE(client_stream->write_side_closed());
-  client_->WaitUntil(
-      -1, [&observer]() { return observer.num_stop_sending_frames() > 0; });
-  if (!observer.stream_write_side_closed_before_receiving_stop_sending()) {
-    EXPECT_EQ(kStopSendingTestCode,
-              static_cast<uint16_t>(client_stream->stream_error()));
+  if (client_stream != nullptr) {
+    // Ensure the stream has been write closed upon receiving STOP_SENDING.
+    EXPECT_EQ(stream_id, client_stream->id());
+    EXPECT_TRUE(client_stream->write_side_closed());
+    client_->WaitUntil(
+        -1, [&observer]() { return observer.num_stop_sending_frames() > 0; });
+    if (!observer.stream_write_side_closed_before_receiving_stop_sending()) {
+      EXPECT_EQ(kStopSendingTestCode,
+                static_cast<uint16_t>(client_stream->stream_error()));
+    }
+  } else {
+    ADD_FAILURE() << "Missing client stream";
   }
+  client_connection->set_debug_visitor(nullptr);
 }
 
 TEST_P(EndToEndTest, SimpleStopSendingRstStreamTest) {
@@ -4095,8 +4430,7 @@
 };
 
 TEST_P(EndToEndTest, ZeroRttProtectedConnectionClose) {
-  if (version_.UsesTls() ||
-      !VersionHasIetfInvariantHeader(version_.transport_version)) {
+  if (version_.UsesTls() || !version_.HasIetfInvariantHeader()) {
     // TODO(b/152551499): Re-enable this test when TLS supports 0-RTT.
     // Only runs for IETF QUIC header.
     Initialize();
@@ -4104,13 +4438,21 @@
   }
   // This test ensures ZERO_RTT_PROTECTED connection close could close a client
   // which has switched to forward secure.
-  connect_to_server_on_initialize_ =
-      !VersionHasIetfInvariantHeader(version_.transport_version);
+  connect_to_server_on_initialize_ = !version_.HasIetfInvariantHeader();
   ASSERT_TRUE(Initialize());
   server_thread_->Pause();
   QuicDispatcher* dispatcher =
       QuicServerPeer::GetDispatcher(server_thread_->server());
-  ASSERT_EQ(0u, dispatcher->session_map().size());
+  if (dispatcher == nullptr) {
+    ADD_FAILURE() << "Missing dispatcher";
+    server_thread_->Resume();
+    return;
+  }
+  if (!dispatcher->session_map().empty()) {
+    ADD_FAILURE() << "Dispatcher session map not empty";
+    server_thread_->Resume();
+    return;
+  }
   // Note: this writer will only used by the server connection, not the time
   // wait list.
   QuicDispatcherPeer::UseWriter(
@@ -4161,17 +4503,25 @@
 TEST_P(EndToEndTest, ForwardSecureConnectionClose) {
   // This test ensures ZERO_RTT_PROTECTED connection close is sent to a client
   // which has ZERO_RTT_PROTECTED encryption level.
-  connect_to_server_on_initialize_ =
-      !VersionHasIetfInvariantHeader(version_.transport_version);
+  connect_to_server_on_initialize_ = !version_.HasIetfInvariantHeader();
   ASSERT_TRUE(Initialize());
-  if (!VersionHasIetfInvariantHeader(version_.transport_version)) {
+  if (!version_.HasIetfInvariantHeader()) {
     // Only runs for IETF QUIC header.
     return;
   }
   server_thread_->Pause();
   QuicDispatcher* dispatcher =
       QuicServerPeer::GetDispatcher(server_thread_->server());
-  ASSERT_EQ(0u, dispatcher->session_map().size());
+  if (dispatcher == nullptr) {
+    ADD_FAILURE() << "Missing dispatcher";
+    server_thread_->Resume();
+    return;
+  }
+  if (!dispatcher->session_map().empty()) {
+    ADD_FAILURE() << "Dispatcher session map not empty";
+    server_thread_->Resume();
+    return;
+  }
   // Note: this writer will only used by the server connection, not the time
   // wait list.
   QuicDispatcherPeer::UseWriter(
@@ -4192,7 +4542,7 @@
 TEST_P(EndToEndTest, TooBigStreamIdClosesConnection) {
   // Has to be before version test, see EndToEndTest::TearDown()
   ASSERT_TRUE(Initialize());
-  if (!VersionHasIetfQuicFrames(version_.transport_version)) {
+  if (!version_.HasIetfQuicFrames()) {
     // Only runs for IETF QUIC.
     return;
   }
@@ -4206,21 +4556,23 @@
   headers[":authority"] = server_hostname_;
 
   // Force the client to write with a stream ID that exceeds the limit.
-  QuicSpdySession* session = GetClientSession();
+  QuicSpdySession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
   QuicStreamIdManager* stream_id_manager =
-      QuicSessionPeer::v99_bidirectional_stream_id_manager(session);
+      QuicSessionPeer::v99_bidirectional_stream_id_manager(client_session);
+  ASSERT_TRUE(stream_id_manager);
   QuicStreamCount max_number_of_streams =
       stream_id_manager->outgoing_max_streams();
   QuicSessionPeer::SetNextOutgoingBidirectionalStreamId(
-      session, GetNthClientInitiatedBidirectionalId(max_number_of_streams + 1));
+      client_session,
+      GetNthClientInitiatedBidirectionalId(max_number_of_streams + 1));
   client_->SendCustomSynchronousRequest(headers, body);
   EXPECT_THAT(client_->stream_error(),
               IsStreamError(QUIC_STREAM_CONNECTION_ERROR));
-  EXPECT_THAT(GetClientSession()->error(), IsError(QUIC_INVALID_STREAM_ID));
-  EXPECT_EQ(IETF_QUIC_TRANSPORT_CONNECTION_CLOSE,
-            GetClientSession()->close_type());
+  EXPECT_THAT(client_session->error(), IsError(QUIC_INVALID_STREAM_ID));
+  EXPECT_EQ(IETF_QUIC_TRANSPORT_CONNECTION_CLOSE, client_session->close_type());
   EXPECT_TRUE(
-      IS_IETF_STREAM_FRAME(GetClientSession()->transport_close_frame_type()));
+      IS_IETF_STREAM_FRAME(client_session->transport_close_frame_type()));
 }
 
 TEST_P(EndToEndTest, TestMaxPushId) {
@@ -4233,16 +4585,22 @@
   ASSERT_TRUE(Initialize());
 
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-  static_cast<QuicSpdySession*>(client_->client()->session())
-      ->SetMaxPushId(kMaxQuicStreamId);
+  QuicSpdyClientSession* client_session = GetClientSession();
+  ASSERT_TRUE(client_session);
+  client_session->SetMaxPushId(kMaxQuicStreamId);
 
   client_->SendSynchronousRequest("/foo");
 
-  EXPECT_TRUE(static_cast<QuicSpdySession*>(client_->client()->session())
-                  ->CanCreatePushStreamWithId(kMaxQuicStreamId));
+  EXPECT_TRUE(client_session->CanCreatePushStreamWithId(kMaxQuicStreamId));
 
-  EXPECT_TRUE(static_cast<QuicSpdySession*>(GetServerSession())
-                  ->CanCreatePushStreamWithId(kMaxQuicStreamId));
+  server_thread_->Pause();
+  QuicSpdySession* server_session = GetServerSession();
+  if (server_session != nullptr) {
+    EXPECT_TRUE(server_session->CanCreatePushStreamWithId(kMaxQuicStreamId));
+  } else {
+    ADD_FAILURE() << "Missing server session";
+  }
+  server_thread_->Resume();
 }
 
 TEST_P(EndToEndTest, CustomTransportParameters) {
@@ -4271,20 +4629,33 @@
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
 
   server_thread_->Pause();
-  QuicConfig server_config = *GetServerSession()->config();
-  if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
-    EXPECT_EQ(GetServerSession()->user_agent_id().value_or("MissingUserAgent"),
-              kTestUserAgentId);
+  QuicSpdySession* server_session = GetServerSession();
+  QuicConfig* server_config = nullptr;
+  if (server_session != nullptr) {
+    server_config = server_session->config();
+    if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
+      EXPECT_EQ(server_session->user_agent_id().value_or("MissingUserAgent"),
+                kTestUserAgentId);
+    } else {
+      EXPECT_FALSE(server_session->user_agent_id().has_value());
+    }
   } else {
-    EXPECT_FALSE(GetServerSession()->user_agent_id().has_value());
+    ADD_FAILURE() << "Missing server session";
+  }
+  if (server_config != nullptr) {
+    if (server_config->received_custom_transport_parameters().find(
+            kCustomParameter) !=
+        server_config->received_custom_transport_parameters().end()) {
+      EXPECT_EQ(server_config->received_custom_transport_parameters().at(
+                    kCustomParameter),
+                "test");
+    } else {
+      ADD_FAILURE() << "Did not find custom parameter";
+    }
+  } else {
+    ADD_FAILURE() << "Missing server config";
   }
   server_thread_->Resume();
-  ASSERT_NE(server_config.received_custom_transport_parameters().find(
-                kCustomParameter),
-            server_config.received_custom_transport_parameters().end());
-  EXPECT_EQ(
-      server_config.received_custom_transport_parameters().at(kCustomParameter),
-      "test");
 }
 
 TEST_P(EndToEndTest, LegacyVersionEncapsulation) {
@@ -4298,12 +4669,12 @@
   SetQuicReloadableFlag(quic_dispatcher_legacy_version_encapsulation, true);
   client_config_.SetClientConnectionOptions(QuicTagVector{kQLVE});
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_GT(GetClientConnection()
-                ->GetStats()
-                .sent_legacy_version_encapsulated_packets,
-            0u);
+  SendSynchronousFooRequestAndCheckResponse();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_GT(
+      client_connection->GetStats().sent_legacy_version_encapsulated_packets,
+      0u);
 }
 
 TEST_P(EndToEndTest, LegacyVersionEncapsulationWithMultiPacketChlo) {
@@ -4327,12 +4698,12 @@
   client_config_.custom_transport_parameters_to_send()[kCustomParameter] =
       std::string(2000, '?');
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_GT(GetClientConnection()
-                ->GetStats()
-                .sent_legacy_version_encapsulated_packets,
-            0u);
+  SendSynchronousFooRequestAndCheckResponse();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_GT(
+      client_connection->GetStats().sent_legacy_version_encapsulated_packets,
+      0u);
 }
 
 TEST_P(EndToEndTest, LegacyVersionEncapsulationWithVersionNegotiation) {
@@ -4348,12 +4719,12 @@
   SetQuicReloadableFlag(quic_dispatcher_legacy_version_encapsulation, true);
   client_config_.SetClientConnectionOptions(QuicTagVector{kQLVE});
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_GT(GetClientConnection()
-                ->GetStats()
-                .sent_legacy_version_encapsulated_packets,
-            0u);
+  SendSynchronousFooRequestAndCheckResponse();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_GT(
+      client_connection->GetStats().sent_legacy_version_encapsulated_packets,
+      0u);
 }
 
 TEST_P(EndToEndTest, LegacyVersionEncapsulationWithLoss) {
@@ -4367,13 +4738,15 @@
   SetQuicReloadableFlag(quic_dont_pad_chlo, true);
   SetQuicReloadableFlag(quic_dispatcher_legacy_version_encapsulation, true);
   client_config_.SetClientConnectionOptions(QuicTagVector{kQLVE});
+  // Disable blackhole detection as this test is testing loss recovery.
+  client_extra_copts_.push_back(kNBHD);
   ASSERT_TRUE(Initialize());
-  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
-  EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
-  EXPECT_GT(GetClientConnection()
-                ->GetStats()
-                .sent_legacy_version_encapsulated_packets,
-            0u);
+  SendSynchronousFooRequestAndCheckResponse();
+  QuicConnection* client_connection = GetClientConnection();
+  ASSERT_TRUE(client_connection);
+  EXPECT_GT(
+      client_connection->GetStats().sent_legacy_version_encapsulated_packets,
+      0u);
 }
 
 }  // namespace