Source file src/net/tcpsock_unix_test.go

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build !plan9 && !windows
     6  
     7  package net
     8  
     9  import (
    10  	"context"
    11  	"math/rand"
    12  	"runtime"
    13  	"sync"
    14  	"syscall"
    15  	"testing"
    16  	"time"
    17  )
    18  
    19  // See golang.org/issue/14548.
    20  func TestTCPSpuriousConnSetupCompletion(t *testing.T) {
    21  	if testing.Short() {
    22  		t.Skip("skipping in short mode")
    23  	}
    24  
    25  	ln := newLocalListener(t, "tcp")
    26  	var wg sync.WaitGroup
    27  	wg.Add(1)
    28  	go func(ln Listener) {
    29  		defer wg.Done()
    30  		for {
    31  			c, err := ln.Accept()
    32  			if err != nil {
    33  				return
    34  			}
    35  			wg.Add(1)
    36  			go func(c Conn) {
    37  				var b [1]byte
    38  				c.Read(b[:])
    39  				c.Close()
    40  				wg.Done()
    41  			}(c)
    42  		}
    43  	}(ln)
    44  
    45  	attempts := int(1e4) // larger is better
    46  	wg.Add(attempts)
    47  	throttle := make(chan struct{}, runtime.GOMAXPROCS(-1)*2)
    48  	for i := 0; i < attempts; i++ {
    49  		throttle <- struct{}{}
    50  		go func(i int) {
    51  			defer func() {
    52  				<-throttle
    53  				wg.Done()
    54  			}()
    55  			d := Dialer{Timeout: 50 * time.Millisecond}
    56  			c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
    57  			if err != nil {
    58  				if perr := parseDialError(err); perr != nil {
    59  					t.Errorf("#%d: %v (original error: %v)", i, perr, err)
    60  				}
    61  				return
    62  			}
    63  			var b [1]byte
    64  			if _, err := c.Write(b[:]); err != nil {
    65  				if perr := parseWriteError(err); perr != nil {
    66  					t.Errorf("#%d: %v", i, err)
    67  				}
    68  				if samePlatformError(err, syscall.ENOTCONN) {
    69  					t.Errorf("#%d: %v", i, err)
    70  				}
    71  			}
    72  			c.Close()
    73  		}(i)
    74  	}
    75  
    76  	ln.Close()
    77  	wg.Wait()
    78  }
    79  
    80  // Issue 19289.
    81  // Test that a canceled Dial does not cause a subsequent Dial to succeed.
    82  func TestTCPSpuriousConnSetupCompletionWithCancel(t *testing.T) {
    83  	mustHaveExternalNetwork(t)
    84  
    85  	defer dnsWaitGroup.Wait()
    86  	t.Parallel()
    87  	const tries = 10000
    88  	var wg sync.WaitGroup
    89  	wg.Add(tries * 2)
    90  	sem := make(chan bool, 5)
    91  	for i := 0; i < tries; i++ {
    92  		sem <- true
    93  		ctx, cancel := context.WithCancel(context.Background())
    94  		go func() {
    95  			defer wg.Done()
    96  			time.Sleep(time.Duration(rand.Int63n(int64(5 * time.Millisecond))))
    97  			cancel()
    98  		}()
    99  		go func(i int) {
   100  			defer wg.Done()
   101  			var dialer Dialer
   102  			// Try to connect to a real host on a port
   103  			// that it is not listening on.
   104  			_, err := dialer.DialContext(ctx, "tcp", "golang.org:3")
   105  			if err == nil {
   106  				t.Errorf("Dial to unbound port succeeded on attempt %d", i)
   107  			}
   108  			<-sem
   109  		}(i)
   110  	}
   111  	wg.Wait()
   112  }
   113  

View as plain text