gfe-relnote: Add a quic::test::ServerThread::WaitUntil method and use it in quic end_to_end_test. Test only.

This is another attempt to deflake BadPacketHeaderFlags.

PiperOrigin-RevId: 293642314
Change-Id: I1809b8b56c50df7ef2de60d73ac30e9a4e8b35df
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 97623a7..2f9149c 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -2756,15 +2756,13 @@
       &packet[0], sizeof(packet),
       client_->client()->network_helper()->GetLatestClientAddress().host(),
       server_address_, nullptr);
-  // Give the server time to process the packet.
-  QuicSleep(QuicTime::Delta::FromSeconds(1));
-  // Pause the server so we can access the server's internals without races.
-  server_thread_->Pause();
-  QuicDispatcher* dispatcher =
-      QuicServerPeer::GetDispatcher(server_thread_->server());
-  EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
-              IsError(QUIC_INVALID_PACKET_HEADER));
-  server_thread_->Resume();
+  EXPECT_TRUE(server_thread_->WaitUntil(
+      [&] {
+        return QuicDispatcherPeer::GetAndClearLastError(
+                   QuicServerPeer::GetDispatcher(server_thread_->server())) ==
+               QUIC_INVALID_PACKET_HEADER;
+      },
+      QuicTime::Delta::FromSeconds(5)));
 
   // The connection should not be terminated.
   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -2807,15 +2805,14 @@
       &packet[0], sizeof(packet),
       client_->client()->network_helper()->GetLatestClientAddress().host(),
       server_address_, nullptr);
-  // Give the server time to process the packet.
-  QuicSleep(QuicTime::Delta::FromSeconds(1));
-  // Pause the server so we can access the server's internals without races.
-  server_thread_->Pause();
-  QuicDispatcher* dispatcher =
-      QuicServerPeer::GetDispatcher(server_thread_->server());
-  EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
-              IsError(QUIC_INVALID_PACKET_HEADER));
-  server_thread_->Resume();
+
+  EXPECT_TRUE(server_thread_->WaitUntil(
+      [&] {
+        return QuicDispatcherPeer::GetAndClearLastError(
+                   QuicServerPeer::GetDispatcher(server_thread_->server())) ==
+               QUIC_INVALID_PACKET_HEADER;
+      },
+      QuicTime::Delta::FromSeconds(5)));
 
   // The connection should not be terminated.
   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
diff --git a/quic/test_tools/server_thread.cc b/quic/test_tools/server_thread.cc
index da412dd..fa7e822 100644
--- a/quic/test_tools/server_thread.cc
+++ b/quic/test_tools/server_thread.cc
@@ -15,6 +15,7 @@
 ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address)
     : QuicThread("server_thread"),
       server_(server),
+      clock_(server->epoll_server()),
       address_(address),
       port_(0),
       initialized_(false) {}
@@ -68,6 +69,24 @@
   confirmed_.WaitForNotification();
 }
 
+bool ServerThread::WaitUntil(std::function<bool()> termination_predicate,
+                             QuicTime::Delta timeout) {
+  const QuicTime deadline = clock_.Now() + timeout;
+  while (clock_.Now() < deadline) {
+    QuicNotification done_checking;
+    bool should_terminate = false;
+    Schedule([&] {
+      should_terminate = termination_predicate();
+      done_checking.Notify();
+    });
+    done_checking.WaitForNotification();
+    if (should_terminate) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void ServerThread::Pause() {
   DCHECK(!pause_.HasBeenNotified());
   pause_.Notify();
diff --git a/quic/test_tools/server_thread.h b/quic/test_tools/server_thread.h
index d430297..eb47496 100644
--- a/quic/test_tools/server_thread.h
+++ b/quic/test_tools/server_thread.h
@@ -39,6 +39,13 @@
   // Waits for the handshake to be confirmed for the first session created.
   void WaitForCryptoHandshakeConfirmed();
 
+  // Wait until |termination_predicate| returns true in server thread, or
+  // reached |timeout|. Must be called from an external thread.
+  // Return whether the function returned after |termination_predicate| become
+  // true.
+  bool WaitUntil(std::function<bool()> termination_predicate,
+                 QuicTime::Delta timeout);
+
   // Pauses execution of the server until Resume() is called.  May only be
   // called once.
   void Pause();
@@ -71,6 +78,7 @@
   QuicNotification quit_;    // Notified when the server should quit.
 
   std::unique_ptr<QuicServer> server_;
+  QuicEpollClock clock_;
   QuicSocketAddress address_;
   mutable QuicMutex port_lock_;
   int port_ QUIC_GUARDED_BY(port_lock_);
diff --git a/quic/tools/quic_server.h b/quic/tools/quic_server.h
index 1fb17f6..6059ea0 100644
--- a/quic/tools/quic_server.h
+++ b/quic/tools/quic_server.h
@@ -91,6 +91,8 @@
 
   int port() { return port_; }
 
+  QuicEpollServer* epoll_server() { return &epoll_server_; }
+
  protected:
   virtual QuicPacketWriter* CreateWriter(int fd);
 
@@ -98,7 +100,6 @@
 
   const QuicConfig& config() const { return config_; }
   const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; }
-  QuicEpollServer* epoll_server() { return &epoll_server_; }
 
   QuicDispatcher* dispatcher() { return dispatcher_.get(); }