blob: 240eca1ea1e4c7e9ba0dafe73e446d07096ee916 [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()
48 r, err := http.Get("http://" + l.Addr().String())
49 if err != nil {
50 t.Logf("Get: %v", err)
51 atomic.AddInt32(&failed, 1)
52 return
53 }
54 defer r.Body.Close()
55 io.Copy(ioutil.Discard, r.Body)
56 }()
57 }
58 wg.Wait()
59
60 // We expect some Gets to fail as the kernel's accept queue is filled,
61 // but most should succeed.
62 if failed >= num/2 {
63 t.Errorf("too many Gets failed")
64 }
65}