Prevent infinite loops in QUIC e2e test

In some failure cases, our e2e test could get itself into an infinite loop, causing it to wait 5 minutes for the overall test timeout. That makes debugging incredibly painful. This CL tweaks our code to fail earlier allowing us to avoid more timeouts.

Test-only change

PiperOrigin-RevId: 319314922
Change-Id: Ibe90e26500db95201818c6a40c5b819d3c44cae8
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 02e1c66..0888a0e 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -1239,7 +1239,7 @@
 
   while (kNumRequests > client_->num_responses()) {
     client_->ClearPerRequestState();
-    WaitForFooResponseAndCheckIt();
+    ASSERT_TRUE(WaitForFooResponseAndCheckIt());
   }
 }
 
@@ -2171,7 +2171,8 @@
 
   // WaitForEvents waits 50ms and returns true if there are outstanding
   // requests.
-  while (client_->client()->WaitForEvents() == true) {
+  while (client_->client()->WaitForEvents()) {
+    ASSERT_TRUE(client_->connected());
   }
 }
 
@@ -2196,7 +2197,8 @@
 
   // WaitForEvents waits 50ms and returns true if there are outstanding
   // requests.
-  while (client_->client()->WaitForEvents() == true) {
+  while (client_->client()->WaitForEvents()) {
+    ASSERT_TRUE(client_->connected());
   }
   // It should be completely fine to RST a stream before any data has been
   // received for that stream.
@@ -2509,6 +2511,7 @@
     // is sent in the first packet on the control stream.
     while (!QuicSpdySessionPeer::GetReceiveControlStream(client_session)) {
       client_->client()->WaitForEvents();
+      ASSERT_TRUE(client_->connected());
     }
   }
 
@@ -2516,6 +2519,7 @@
   // (and the ack received by the client).
   while (client_session->HasUnackedStreamData()) {
     client_->client()->WaitForEvents();
+    ASSERT_TRUE(client_->connected());
   }
 
   server_thread_->Pause();
@@ -2675,21 +2679,22 @@
     while (true) {
       // Waits for up to 50 ms.
       client_->client()->WaitForEvents();
+      ASSERT_TRUE(client_->connected());
       QuicSpdyClientSession* client_session = GetClientSession();
       if (client_session == nullptr) {
         ADD_FAILURE() << "Missing client session";
-        break;
+        return;
       }
       QpackEncoder* qpack_encoder = client_session->qpack_encoder();
       if (qpack_encoder == nullptr) {
         ADD_FAILURE() << "Missing QPACK encoder";
-        break;
+        return;
       }
       QpackHeaderTable* header_table =
           QpackEncoderPeer::header_table(qpack_encoder);
       if (header_table == nullptr) {
         ADD_FAILURE() << "Missing header table";
-        break;
+        return;
       }
       if (QpackHeaderTablePeer::dynamic_table_capacity(header_table) > 0) {
         break;
@@ -2749,6 +2754,7 @@
   while (ack_listener->total_bytes_acked() < expected_bytes_acked) {
     // Waits for up to 50 ms.
     client_->client()->WaitForEvents();
+    ASSERT_TRUE(client_->connected());
   }
   EXPECT_EQ(ack_listener->total_bytes_acked(), expected_bytes_acked)
       << " header_size " << header_size << " request length "
@@ -3584,6 +3590,7 @@
     // Because of priority, the first response arrived should be to original
     // request.
     client_->WaitForResponse();
+    ASSERT_TRUE(client_->connected());
   }
 
   // Check server session to see if it has max number of outgoing streams opened
diff --git a/quic/test_tools/quic_test_client.cc b/quic/test_tools/quic_test_client.cc
index f876532..c25bd8e 100644
--- a/quic/test_tools/quic_test_client.cc
+++ b/quic/test_tools/quic_test_client.cc
@@ -636,7 +636,10 @@
 }
 
 void QuicTestClient::Connect() {
-  DCHECK(!connected());
+  if (connected()) {
+    QUIC_BUG << "Cannot connect already-connected client";
+    return;
+  }
   if (!connect_attempted_) {
     client_->Initialize();
   }
diff --git a/quic/test_tools/quic_test_client.h b/quic/test_tools/quic_test_client.h
index 41e30b1..a7c9d6a 100644
--- a/quic/test_tools/quic_test_client.h
+++ b/quic/test_tools/quic_test_client.h
@@ -332,7 +332,9 @@
  protected:
   QuicTestClient();
   QuicTestClient(const QuicTestClient&) = delete;
+  QuicTestClient(const QuicTestClient&&) = delete;
   QuicTestClient& operator=(const QuicTestClient&) = delete;
+  QuicTestClient& operator=(const QuicTestClient&&) = delete;
 
  private:
   class TestClientDataToResend : public QuicClient::QuicDataToResend {
diff --git a/quic/tools/quic_client_base.cc b/quic/tools/quic_client_base.cc
index 82b549f..efd668f 100644
--- a/quic/tools/quic_client_base.cc
+++ b/quic/tools/quic_client_base.cc
@@ -89,6 +89,10 @@
     }
     num_attempts++;
   }
+  if (session() == nullptr) {
+    QUIC_BUG << "Missing session after Connect";
+    return false;
+  }
   return session()->connection()->connected();
 }
 
@@ -165,7 +169,10 @@
 }
 
 bool QuicClientBase::WaitForEvents() {
-  DCHECK(connected());
+  if (!connected()) {
+    QUIC_BUG << "Cannot call WaitForEvents on non-connected client";
+    return false;
+  }
 
   network_helper_->RunEventLoop();
 
@@ -228,7 +235,10 @@
 }
 
 void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
-  DCHECK(connected());
+  if (!connected()) {
+    QUIC_BUG << "Cannot WaitForStreamToClose on non-connected client";
+    return;
+  }
 
   while (connected() && !session_->IsClosedStream(id)) {
     WaitForEvents();
@@ -236,7 +246,10 @@
 }
 
 bool QuicClientBase::WaitForOneRttKeysAvailable() {
-  DCHECK(connected());
+  if (!connected()) {
+    QUIC_BUG << "Cannot WaitForOneRttKeysAvailable on non-connected client";
+    return false;
+  }
 
   while (connected() && !session_->OneRttKeysAvailable()) {
     WaitForEvents();