]> Cypherpunks repositories - gostls13.git/commitdiff
net: unskip and attempt to deflake TestAcceptTimeout
authorBryan C. Mills <bcmills@google.com>
Mon, 11 Dec 2023 21:45:04 +0000 (16:45 -0500)
committerGopher Robot <gobot@golang.org>
Tue, 23 Jan 2024 17:46:06 +0000 (17:46 +0000)
This test has been unconditionally skipped for over five years.
It may be that whatever was causing it to flake has been fixed.
And if it hasn't been fixed, it isn't providing any value.
Let's unskip it for the Go 1.23 development cycle and see what happens.

Let's also use a separate listener for each test case, so that a
leaked Dial goroutine from one case won't interfere with the other.

Fixes #17948 (maybe).

Change-Id: I239f22ca5d5a44388b9aa0ed4d81e451c6342617
Reviewed-on: https://go-review.googlesource.com/c/go/+/548940
Commit-Queue: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/net/timeout_test.go

index ca86f31ef2f98231be6bf967fe8f94ec71e24369..3a903f8f73479188504b303bdd23bb771948ec98 100644 (file)
@@ -7,7 +7,6 @@ package net
 import (
        "errors"
        "fmt"
-       "internal/testenv"
        "io"
        "os"
        "runtime"
@@ -166,19 +165,7 @@ func TestDialTimeoutMaxDuration(t *testing.T) {
        }
 }
 
-var acceptTimeoutTests = []struct {
-       timeout time.Duration
-       xerrs   [2]error // expected errors in transition
-}{
-       // Tests that accept deadlines in the past work, even if
-       // there's incoming connections available.
-       {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}},
-
-       {50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
-}
-
 func TestAcceptTimeout(t *testing.T) {
-       testenv.SkipFlaky(t, 17948)
        t.Parallel()
 
        switch runtime.GOOS {
@@ -186,49 +173,62 @@ func TestAcceptTimeout(t *testing.T) {
                t.Skipf("not supported on %s", runtime.GOOS)
        }
 
-       ln := newLocalListener(t, "tcp")
-       defer ln.Close()
+       timeouts := []time.Duration{
+               -5 * time.Second,
+               10 * time.Millisecond,
+       }
 
-       var wg sync.WaitGroup
-       for i, tt := range acceptTimeoutTests {
-               if tt.timeout < 0 {
-                       wg.Add(1)
-                       go func() {
-                               defer wg.Done()
-                               d := Dialer{Timeout: 100 * time.Millisecond}
-                               c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
-                               if err != nil {
-                                       t.Error(err)
-                                       return
-                               }
-                               c.Close()
-                       }()
-               }
+       for _, timeout := range timeouts {
+               timeout := timeout
+               t.Run(fmt.Sprintf("%v", timeout), func(t *testing.T) {
+                       t.Parallel()
 
-               if err := ln.(*TCPListener).SetDeadline(time.Now().Add(tt.timeout)); err != nil {
-                       t.Fatalf("$%d: %v", i, err)
-               }
-               for j, xerr := range tt.xerrs {
-                       for {
-                               c, err := ln.Accept()
-                               if xerr != nil {
-                                       if perr := parseAcceptError(err); perr != nil {
-                                               t.Errorf("#%d/%d: %v", i, j, perr)
-                                       }
-                                       if !isDeadlineExceeded(err) {
-                                               t.Fatalf("#%d/%d: %v", i, j, err)
+                       ln := newLocalListener(t, "tcp")
+                       defer ln.Close()
+
+                       if timeout >= 0 {
+                               // Don't dial the listener at all, so that Accept will hang.
+                       } else {
+                               // A deadline in the past should cause Accept to fail even if there are
+                               // incoming connections available. Try to make one available before the
+                               // call to Accept happens. (It's ok if the timing doesn't always work
+                               // out that way, though: the test should pass regardless.)
+                               dialDone := make(chan struct{})
+                               t.Cleanup(func() { <-dialDone })
+
+                               go func() {
+                                       defer close(dialDone)
+                                       d := Dialer{}
+                                       c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
+                                       if err != nil {
+                                               t.Error(err)
+                                               return
                                        }
-                               }
-                               if err == nil {
                                        c.Close()
-                                       time.Sleep(10 * time.Millisecond)
-                                       continue
-                               }
-                               break
+                               }()
+
+                               time.Sleep(10 * time.Millisecond)
                        }
-               }
+
+                       if err := ln.(*TCPListener).SetDeadline(time.Now().Add(timeout)); err != nil {
+                               t.Fatal(err)
+                       }
+                       t.Logf("ln.SetDeadline(time.Now().Add(%v))", timeout)
+
+                       c, err := ln.Accept()
+                       if err == nil {
+                               c.Close()
+                       }
+                       t.Logf("ln.Accept: %v", err)
+
+                       if perr := parseAcceptError(err); perr != nil {
+                               t.Error(perr)
+                       }
+                       if !isDeadlineExceeded(err) {
+                               t.Error("wanted deadline exceeded")
+                       }
+               })
        }
-       wg.Wait()
 }
 
 func TestAcceptTimeoutMustReturn(t *testing.T) {