This is an automated email from the ASF dual-hosted git repository.

Alanxtl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new e1bd4e817 fix(triple): guard httpSrv/http3Srv access with atomic 
pointers (#3639)
e1bd4e817 is described below

commit e1bd4e817942e38824e03e4ebf8c79dffa81b98b
Author: Li Zining <[email protected]>
AuthorDate: Tue Aug 11 20:32:32 2026 +0800

    fix(triple): guard httpSrv/http3Srv access with atomic pointers (#3639)
    
    * fix(triple): guard httpSrv/http3Srv access with atomic pointers
    
    Server starts the HTTP/2 and HTTP/3 listeners in background goroutines
    (startHttp2/startHttp3/startHttp2AndHttp3 write s.httpSrv and s.http3Srv
    on the start path) while Stop and GracefulStop read and close them on a
    different goroutine, with no synchronization in between. Under -race this
    reports a data race on both fields every time TestCfgAPI_Export runs.
    
    Store the two servers in uatomic.Pointer fields: every write goes through
    Store and every read through Load, and Stop/GracefulStop load once into a
    local snapshot before checking nil and closing.
    
    Signed-off-by: lizining <[email protected]>
    
    * test(triple): verify triple server start and stop behavior
    
    Add 13 tests that start the real HTTP/2, HTTP/3 and dual-protocol
    servers on random ports, stop or gracefully stop them, and assert the
    httpSrv/http3Srv uatomic.Pointer fields across start and stop. Also
    cover stopping before start, repeated start/stop for every protocol,
    and the missing-TLS / unsupported-protocol error paths. These tests
    fail on the previous unsynchronized fields under -race.
    
    Signed-off-by: lizining <[email protected]>
    
    * test(triple): adapt nil assertions to uatomic.Pointer fields
    
    The fields became uatomic.Pointer in the race fix, which is never nil 
itself; load the pointer before the nil assertion.
    
    Signed-off-by: lizining <[email protected]>
    
    ---------
    
    Signed-off-by: lizining <[email protected]>
---
 protocol/triple/triple_protocol/server.go          |  53 ++--
 .../triple_protocol/server_lifecycle_test.go       | 344 +++++++++++++++++++++
 protocol/triple/triple_protocol/server_test.go     |   6 +-
 3 files changed, 375 insertions(+), 28 deletions(-)

diff --git a/protocol/triple/triple_protocol/server.go 
b/protocol/triple/triple_protocol/server.go
index ea88764a4..409b4e485 100644
--- a/protocol/triple/triple_protocol/server.go
+++ b/protocol/triple/triple_protocol/server.go
@@ -31,6 +31,8 @@ import (
 
        "github.com/quic-go/quic-go/http3"
 
+       uatomic "go.uber.org/atomic"
+
        "golang.org/x/net/http2"
        "golang.org/x/net/http2/h2c"
 
@@ -48,8 +50,8 @@ type Server struct {
        addr               string
        mux                *methodRouteMux
        handlers           map[string]*Handler
-       httpSrv            *http.Server
-       http3Srv           *http3.Server
+       httpSrv            uatomic.Pointer[http.Server]
+       http3Srv           uatomic.Pointer[http3.Server]
        tripleConfig       *global.TripleConfig // Configuration for the triple 
protocol
        openapiIntegration *openapi.OpenAPIIntegration
 }
@@ -196,20 +198,21 @@ func (s *Server) Run(callProtocol string, tlsConf 
*tls.Config) error {
 }
 
 func (s *Server) startHttp2(tlsConf *tls.Config) error {
-       s.httpSrv = &http.Server{
+       s.httpSrv.Store(&http.Server{
                Addr:      s.addr,
                Handler:   h2c.NewHandler(s.mux, &http2.Server{}),
                TLSConfig: tlsConf,
-       }
+       })
 
        logger.Debugf("[Triple][Server] triple HTTP/2 Server starting on %v", 
s.addr)
 
-       var err error
+       srv := s.httpSrv.Load()
 
+       var err error
        if tlsConf != nil {
-               err = s.httpSrv.ListenAndServeTLS("", "")
+               err = srv.ListenAndServeTLS("", "")
        } else {
-               err = s.httpSrv.ListenAndServe()
+               err = srv.ListenAndServe()
        }
 
        return err
@@ -230,7 +233,7 @@ func (s *Server) startHttp3(tlsConf *tls.Config) error {
                return err
        }
 
-       s.http3Srv = &http3.Server{
+       s.http3Srv.Store(&http3.Server{
                Addr:    s.addr,
                Handler: s.mux,
                // Adapt and enhance a generic tls.Config object into a 
configuration
@@ -238,11 +241,11 @@ func (s *Server) startHttp3(tlsConf *tls.Config) error {
                // ref: 
https://quic-go.net/docs/http3/server/#setting-up-a-http3server
                TLSConfig:  http3.ConfigureTLSConfig(tlsConf),
                QUICConfig: quicConfig,
-       }
+       })
 
        logger.Debugf("[Triple][Server] triple HTTP/3 Server starting on %v", 
s.addr)
 
-       return s.http3Srv.ListenAndServe()
+       return s.http3Srv.Load().ListenAndServe()
 }
 
 func (s *Server) startHttp2AndHttp3(tlsConf *tls.Config) error {
@@ -262,26 +265,26 @@ func (s *Server) startHttp2AndHttp3(tlsConf *tls.Config) 
error {
        }
 
        // Start HTTP/3 server first to get its configuration
-       s.http3Srv = &http3.Server{
+       s.http3Srv.Store(&http3.Server{
                Addr:       s.addr,
                Handler:    s.mux,
                TLSConfig:  http3.ConfigureTLSConfig(tlsConf),
                QUICConfig: quicConfig,
-       }
+       })
 
        // Create Alt-Svc handler wrapper for HTTP/2 server
        var negotiation bool
        if s.tripleConfig != nil && s.tripleConfig.Http3 != nil {
                negotiation = s.tripleConfig.Http3.Negotiation
        }
-       altSvcHandler := NewAltSvcHandler(s.mux, s.http3Srv, negotiation)
+       altSvcHandler := NewAltSvcHandler(s.mux, s.http3Srv.Load(), negotiation)
 
        // Start HTTP/2 server with Alt-Svc handler wrapper
-       s.httpSrv = &http.Server{
+       s.httpSrv.Store(&http.Server{
                Addr:      s.addr,
                Handler:   h2c.NewHandler(altSvcHandler, &http2.Server{}),
                TLSConfig: tlsConf,
-       }
+       })
 
        logger.Debugf("[Triple][Server] triple HTTP/2 and HTTP/3 Server 
starting on %v", s.addr)
 
@@ -290,7 +293,7 @@ func (s *Server) startHttp2AndHttp3(tlsConf *tls.Config) 
error {
 
        // Start HTTP/2 server in a goroutine
        eg.Go(func() error {
-               if err := s.httpSrv.ListenAndServeTLS("", ""); err != nil && 
err != http.ErrServerClosed {
+               if err := s.httpSrv.Load().ListenAndServeTLS("", ""); err != 
nil && err != http.ErrServerClosed {
                        return fmt.Errorf("HTTP/2 server error: %w", err)
                }
                return nil
@@ -298,7 +301,7 @@ func (s *Server) startHttp2AndHttp3(tlsConf *tls.Config) 
error {
 
        // Start HTTP/3 server in a goroutine
        eg.Go(func() error {
-               if err := s.http3Srv.ListenAndServe(); err != nil && err != 
http.ErrServerClosed {
+               if err := s.http3Srv.Load().ListenAndServe(); err != nil && err 
!= http.ErrServerClosed {
                        return fmt.Errorf("HTTP/3 server error: %w", err)
                }
                return nil
@@ -313,9 +316,9 @@ func (s *Server) Stop() error {
        eg, _ := errgroup.WithContext(context.Background())
 
        // stop HTTP server
-       if s.httpSrv != nil {
+       if srv := s.httpSrv.Load(); srv != nil {
                eg.Go(func() error {
-                       if err := s.httpSrv.Close(); err != nil {
+                       if err := srv.Close(); err != nil {
                                return fmt.Errorf("http server close failed: 
%w", err)
                        }
                        return nil
@@ -323,9 +326,9 @@ func (s *Server) Stop() error {
        }
 
        // stop HTTP/3 server
-       if s.http3Srv != nil {
+       if srv3 := s.http3Srv.Load(); srv3 != nil {
                eg.Go(func() error {
-                       if err := s.http3Srv.Close(); err != nil {
+                       if err := srv3.Close(); err != nil {
                                return fmt.Errorf("http3 server close failed: 
%w", err)
                        }
                        return nil
@@ -341,9 +344,9 @@ func (s *Server) GracefulStop(ctx context.Context) error {
        eg, ctx := errgroup.WithContext(ctx)
 
        // shutdown HTTP server
-       if s.httpSrv != nil {
+       if srv := s.httpSrv.Load(); srv != nil {
                eg.Go(func() error {
-                       if err := s.httpSrv.Shutdown(ctx); err != nil {
+                       if err := srv.Shutdown(ctx); err != nil {
                                return fmt.Errorf("http server shutdown failed: 
%w", err)
                        }
                        return nil
@@ -351,9 +354,9 @@ func (s *Server) GracefulStop(ctx context.Context) error {
        }
 
        // shutdown HTTP/3 server
-       if s.http3Srv != nil {
+       if srv3 := s.http3Srv.Load(); srv3 != nil {
                eg.Go(func() error {
-                       if err := s.http3Srv.Shutdown(ctx); err != nil {
+                       if err := srv3.Shutdown(ctx); err != nil {
                                return fmt.Errorf("http3 server shutdown 
failed: %w", err)
                        }
                        return nil
diff --git a/protocol/triple/triple_protocol/server_lifecycle_test.go 
b/protocol/triple/triple_protocol/server_lifecycle_test.go
new file mode 100644
index 000000000..2e6c39d4d
--- /dev/null
+++ b/protocol/triple/triple_protocol/server_lifecycle_test.go
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple_protocol
+
+import (
+       "context"
+       "crypto/ecdsa"
+       "crypto/elliptic"
+       "crypto/rand"
+       "crypto/tls"
+       "crypto/x509"
+       "crypto/x509/pkix"
+       "errors"
+       "math/big"
+       "net"
+       "net/http"
+       "syscall"
+       "testing"
+       "time"
+)
+
+import (
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+       "dubbo.apache.org/dubbo-go/v3/global"
+)
+
+// newTestTLSConfig generates an in-memory self-signed certificate for the
+// server-side TLS configuration. HTTP/3 requires TLS, so it is used by all
+// HTTP/3 related tests.
+func newTestTLSConfig(t *testing.T) *tls.Config {
+       t.Helper()
+
+       priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+       require.NoError(t, err)
+
+       template := &x509.Certificate{
+               SerialNumber: big.NewInt(1),
+               Subject: pkix.Name{
+                       CommonName: "localhost",
+               },
+               NotBefore:             time.Now().Add(-24 * time.Hour),
+               NotAfter:              time.Now().Add(24 * time.Hour),
+               KeyUsage:              x509.KeyUsageDigitalSignature | 
x509.KeyUsageKeyEncipherment,
+               ExtKeyUsage:           
[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+               DNSNames:              []string{"localhost"},
+               IPAddresses:           []net.IP{net.ParseIP("127.0.0.1")},
+               BasicConstraintsValid: true,
+       }
+
+       der, err := x509.CreateCertificate(rand.Reader, template, template, 
&priv.PublicKey, priv)
+       require.NoError(t, err)
+
+       return &tls.Config{
+               Certificates: []tls.Certificate{
+                       {Certificate: [][]byte{der}, PrivateKey: priv},
+               },
+       }
+}
+
+// getFreeAddr returns a free TCP address on loopback for the test server.
+func getFreeAddr(t *testing.T) string {
+       t.Helper()
+
+       l, err := net.Listen("tcp", "127.0.0.1:0")
+       require.NoError(t, err)
+       addr := l.Addr().String()
+       require.NoError(t, l.Close())
+
+       return addr
+}
+
+// runServer starts the server in a goroutine and returns the channel that
+// receives the error returned by Run. ListenAndServe is blocking, so the
+// server must always be started this way in tests.
+func runServer(srv *Server, protocol string, tlsConf *tls.Config) chan error {
+       errCh := make(chan error, 1)
+       go func() {
+               errCh <- srv.Run(protocol, tlsConf)
+       }()
+       return errCh
+}
+
+// isAddrInUse reports whether the error is a port conflict, i.e. the error
+// chain unwraps to syscall.EADDRINUSE.
+func isAddrInUse(err error) bool {
+       return errors.Is(err, syscall.EADDRINUSE)
+}
+
+// startTestServer creates a server on a free port and starts it in a
+// goroutine. It retries with a fresh port when binding fails.
+func startTestServer(t *testing.T, protocol string, cfg *global.TripleConfig, 
tlsConf *tls.Config) (*Server, chan error) {
+       t.Helper()
+
+       for range 3 {
+               srv := NewServer(getFreeAddr(t), cfg)
+               errCh := runServer(srv, protocol, tlsConf)
+               select {
+               case err := <-errCh:
+                       if isAddrInUse(err) {
+                               continue
+                       }
+                       require.FailNow(t, "server failed to start", err)
+               case <-time.After(100 * time.Millisecond):
+               }
+               return srv, errCh
+       }
+       require.FailNow(t, "failed to find a free port after 3 attempts")
+       return nil, nil
+}
+
+// waitForTCPReady polls the address until a TCP connection can be established.
+func waitForTCPReady(t *testing.T, addr string, timeout time.Duration) {
+       t.Helper()
+
+       require.Eventually(t, func() bool {
+               conn, err := net.DialTimeout("tcp", addr, 200*time.Millisecond)
+               if err != nil {
+                       return false
+               }
+               _ = conn.Close()
+               return true
+       }, timeout, 20*time.Millisecond)
+}
+
+// waitForHTTP3Stored waits until the HTTP/3 server has been stored, which
+// means the startup path has passed the Store call. QUIC listens on UDP,
+// so the TCP readiness probe does not apply here.
+func waitForHTTP3Stored(t *testing.T, srv *Server) {
+       t.Helper()
+
+       require.Eventually(t, func() bool {
+               return srv.http3Srv.Load() != nil
+       }, 3*time.Second, 20*time.Millisecond)
+}
+
+// waitForServerExit waits for Run to return. The test fails if the server
+// does not exit within the timeout.
+func waitForServerExit(t *testing.T, errCh chan error, timeout time.Duration) 
error {
+       t.Helper()
+
+       select {
+       case err := <-errCh:
+               return err
+       case <-time.After(timeout):
+               require.FailNow(t, "server did not exit within", timeout)
+               return nil
+       }
+}
+
+func TestServer_HTTP2_StartAndStop(t *testing.T) {
+       srv, errCh := startTestServer(t, constant.CallHTTP2, nil, nil)
+       waitForTCPReady(t, srv.addr, 3*time.Second)
+
+       require.NotNil(t, srv.httpSrv.Load())
+       require.Nil(t, srv.http3Srv.Load())
+
+       require.NoError(t, srv.Stop())
+       require.ErrorIs(t, waitForServerExit(t, errCh, 5*time.Second), 
http.ErrServerClosed)
+}
+
+func TestServer_HTTP2_StartAndStopWithTLS(t *testing.T) {
+       srv, errCh := startTestServer(t, constant.CallHTTP2, nil, 
newTestTLSConfig(t))
+       waitForTCPReady(t, srv.addr, 3*time.Second)
+
+       require.NotNil(t, srv.httpSrv.Load())
+       require.Nil(t, srv.http3Srv.Load())
+
+       require.NoError(t, srv.Stop())
+       require.ErrorIs(t, waitForServerExit(t, errCh, 5*time.Second), 
http.ErrServerClosed)
+}
+
+func TestServer_HTTP3_StartAndStop(t *testing.T) {
+       cfg := &global.TripleConfig{
+               Http3: &global.Http3Config{Enable: true},
+       }
+       srv, errCh := startTestServer(t, constant.CallHTTP3, cfg, 
newTestTLSConfig(t))
+       waitForHTTP3Stored(t, srv)
+
+       require.NotNil(t, srv.http3Srv.Load())
+       require.Nil(t, srv.httpSrv.Load())
+
+       require.NoError(t, srv.Stop())
+       require.ErrorIs(t, waitForServerExit(t, errCh, 5*time.Second), 
http.ErrServerClosed)
+}
+
+func TestServer_HTTP2AndHTTP3_StartAndStop(t *testing.T) {
+       cfg := &global.TripleConfig{
+               Http3: &global.Http3Config{Enable: true},
+       }
+       srv, errCh := startTestServer(t, constant.CallHTTP2AndHTTP3, cfg, 
newTestTLSConfig(t))
+       waitForTCPReady(t, srv.addr, 3*time.Second)
+       waitForHTTP3Stored(t, srv)
+
+       require.NotNil(t, srv.httpSrv.Load())
+       require.NotNil(t, srv.http3Srv.Load())
+
+       require.NoError(t, srv.Stop())
+       // startHttp2AndHttp3 swallows http.ErrServerClosed inside the errgroup,
+       // so Run returns nil after the servers are closed.
+       require.NoError(t, waitForServerExit(t, errCh, 5*time.Second))
+}
+
+func TestServer_HTTP2_StartAndGracefulStop(t *testing.T) {
+       srv, errCh := startTestServer(t, constant.CallHTTP2, nil, nil)
+       waitForTCPReady(t, srv.addr, 3*time.Second)
+
+       require.NotNil(t, srv.httpSrv.Load())
+       require.Nil(t, srv.http3Srv.Load())
+
+       graceCtx, cancel := context.WithTimeout(context.Background(), 
constant.DefaultGracefulShutdownTimeout)
+       defer cancel()
+       require.NoError(t, srv.GracefulStop(graceCtx))
+       require.ErrorIs(t, waitForServerExit(t, errCh, 5*time.Second), 
http.ErrServerClosed)
+}
+
+func TestServer_HTTP3_StartAndGracefulStop(t *testing.T) {
+       cfg := &global.TripleConfig{
+               Http3: &global.Http3Config{Enable: true},
+       }
+       srv, errCh := startTestServer(t, constant.CallHTTP3, cfg, 
newTestTLSConfig(t))
+       waitForHTTP3Stored(t, srv)
+
+       require.NotNil(t, srv.http3Srv.Load())
+       require.Nil(t, srv.httpSrv.Load())
+
+       graceCtx, cancel := context.WithTimeout(context.Background(), 
constant.DefaultGracefulShutdownTimeout)
+       defer cancel()
+       require.NoError(t, srv.GracefulStop(graceCtx))
+       require.ErrorIs(t, waitForServerExit(t, errCh, 5*time.Second), 
http.ErrServerClosed)
+}
+
+func TestServer_HTTP2AndHTTP3_StartAndGracefulStop(t *testing.T) {
+       cfg := &global.TripleConfig{
+               Http3: &global.Http3Config{Enable: true},
+       }
+       srv, errCh := startTestServer(t, constant.CallHTTP2AndHTTP3, cfg, 
newTestTLSConfig(t))
+       waitForTCPReady(t, srv.addr, 3*time.Second)
+       waitForHTTP3Stored(t, srv)
+
+       require.NotNil(t, srv.httpSrv.Load())
+       require.NotNil(t, srv.http3Srv.Load())
+
+       graceCtx, cancel := context.WithTimeout(context.Background(), 
constant.DefaultGracefulShutdownTimeout)
+       defer cancel()
+       require.NoError(t, srv.GracefulStop(graceCtx))
+       // startHttp2AndHttp3 swallows http.ErrServerClosed inside the errgroup,
+       // so Run returns nil after the servers are closed.
+       require.NoError(t, waitForServerExit(t, errCh, 5*time.Second))
+}
+
+func TestServer_StopBeforeStart(t *testing.T) {
+       srv := NewServer(getFreeAddr(t), nil)
+       require.NoError(t, srv.Stop())
+}
+
+func TestServer_GracefulStopBeforeStart(t *testing.T) {
+       srv := NewServer(getFreeAddr(t), nil)
+       graceCtx, cancel := context.WithTimeout(context.Background(), 
constant.DefaultGracefulShutdownTimeout)
+       defer cancel()
+       require.NoError(t, srv.GracefulStop(graceCtx))
+}
+
+func TestServer_Run_HTTP3WithoutTLS(t *testing.T) {
+       srv := NewServer(getFreeAddr(t), nil)
+       err := srv.Run(constant.CallHTTP3, nil)
+       require.Error(t, err)
+       assert.Contains(t, err.Error(), "must have TLS config")
+}
+
+func TestServer_Run_HTTP2AndHTTP3WithoutTLS(t *testing.T) {
+       srv := NewServer(getFreeAddr(t), nil)
+       err := srv.Run(constant.CallHTTP2AndHTTP3, nil)
+       require.Error(t, err)
+       assert.Contains(t, err.Error(), "must have TLS config")
+}
+
+func TestServer_RunUnsupportedProtocol(t *testing.T) {
+       srv := NewServer(getFreeAddr(t), nil)
+       err := srv.Run("tcp", nil)
+       require.Error(t, err)
+       assert.Contains(t, err.Error(), "unsupported protocol")
+}
+
+// TestServer_RepeatedStartStop runs several Start/Stop cycles across all
+// protocols. Each iteration creates a fresh Server, because an http.Server
+// cannot be restarted after Close.
+func TestServer_RepeatedStartStop(t *testing.T) {
+       tlsConf := newTestTLSConfig(t)
+
+       protocols := []struct {
+               protocol string
+               tlsConf  *tls.Config
+       }{
+               {protocol: constant.CallHTTP2},
+               {protocol: constant.CallHTTP3, tlsConf: tlsConf},
+               {protocol: constant.CallHTTP2AndHTTP3, tlsConf: tlsConf},
+       }
+
+       for range 3 {
+               for _, tc := range protocols {
+                       cfg := &global.TripleConfig{}
+                       if tc.protocol == constant.CallHTTP3 || tc.protocol == 
constant.CallHTTP2AndHTTP3 {
+                               cfg.Http3 = &global.Http3Config{Enable: true}
+                       }
+                       srv, errCh := startTestServer(t, tc.protocol, cfg, 
tc.tlsConf)
+                       switch tc.protocol {
+                       case constant.CallHTTP2AndHTTP3:
+                               waitForTCPReady(t, srv.addr, 3*time.Second)
+                               waitForHTTP3Stored(t, srv)
+                       case constant.CallHTTP3:
+                               waitForHTTP3Stored(t, srv)
+                       default:
+                               waitForTCPReady(t, srv.addr, 3*time.Second)
+                       }
+
+                       require.NoError(t, srv.Stop())
+                       if tc.protocol == constant.CallHTTP2AndHTTP3 {
+                               require.NoError(t, waitForServerExit(t, errCh, 
5*time.Second))
+                       } else {
+                               require.ErrorIs(t, waitForServerExit(t, errCh, 
5*time.Second), http.ErrServerClosed)
+                       }
+               }
+       }
+}
diff --git a/protocol/triple/triple_protocol/server_test.go 
b/protocol/triple/triple_protocol/server_test.go
index 84d87ae45..f002682b0 100644
--- a/protocol/triple/triple_protocol/server_test.go
+++ b/protocol/triple/triple_protocol/server_test.go
@@ -159,7 +159,7 @@ func TestServer_HTTP3PathsUseQUICConfigHelper(t *testing.T) 
{
                err := srv.startHttp3(&tls.Config{})
                require.Error(t, err)
                require.ErrorContains(t, err, "keep-alive-period")
-               assert.Nil(t, srv.http3Srv)
+               assert.Nil(t, srv.http3Srv.Load())
        })
 
        t.Run("start_http2_and_http3_returns_parse_error", func(t *testing.T) {
@@ -172,8 +172,8 @@ func TestServer_HTTP3PathsUseQUICConfigHelper(t *testing.T) 
{
                err := srv.startHttp2AndHttp3(&tls.Config{})
                require.Error(t, err)
                require.ErrorContains(t, err, "max-idle-timeout")
-               assert.Nil(t, srv.http3Srv)
-               assert.Nil(t, srv.httpSrv)
+               assert.Nil(t, srv.http3Srv.Load())
+               assert.Nil(t, srv.httpSrv.Load())
        })
 }
 

Reply via email to