github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/net/tcpsock_unix_test.go (about)

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