blob: a4345b1d346717022887f8a97ad494ba45c2a7e4 [file] [log] [blame]
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +10001// Copyright 2013 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
5package netutil
6
7import (
8 "fmt"
9 "io"
10 "io/ioutil"
11 "net"
12 "net/http"
13 "sync"
14 "sync/atomic"
15 "testing"
16 "time"
17)
18
19func TestLimitListener(t *testing.T) {
20 const (
21 max = 5
22 num = 200
23 )
24
25 l, err := net.Listen("tcp", "127.0.0.1:0")
26 if err != nil {
27 t.Fatalf("Listen: %v", err)
28 }
29 defer l.Close()
30 l = LimitListener(l, max)
31
32 var open int32
33 go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
34 if n := atomic.AddInt32(&open, 1); n > max {
35 t.Errorf("%d open connections, want <= %d", n, max)
36 }
37 defer atomic.AddInt32(&open, -1)
38 time.Sleep(10 * time.Millisecond)
39 fmt.Fprint(w, "some body")
40 }))
41
42 var wg sync.WaitGroup
43 var failed int32
44 for i := 0; i < num; i++ {
45 wg.Add(1)
46 go func() {
47 defer wg.Done()
Mikio Harac5088f42014-03-20 04:05:24 +090048 c := http.Client{Timeout: 3 * time.Second}
49 r, err := c.Get("http://" + l.Addr().String())
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100050 if err != nil {
51 t.Logf("Get: %v", err)
52 atomic.AddInt32(&failed, 1)
53 return
54 }
55 defer r.Body.Close()
56 io.Copy(ioutil.Discard, r.Body)
57 }()
58 }
59 wg.Wait()
60
61 // We expect some Gets to fail as the kernel's accept queue is filled,
62 // but most should succeed.
63 if failed >= num/2 {
Mikio Harac5088f42014-03-20 04:05:24 +090064 t.Errorf("too many Gets failed: %v", failed)
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100065 }
66}