Home | History | Annotate | Download | only in net
      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 }
    117