forked from hashicorp/go-connlimit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwrap_test.go
149 lines (121 loc) · 2.76 KB
/
wrap_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package connlimit
import (
"context"
"net"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestWrapClose(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
limit := 3
l, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
errCh := make(chan error, 1)
connCh := make(chan net.Conn, 1)
go func() {
defer l.Close()
lim := NewLimiter(Config{
MaxConnsPerClientIP: limit,
})
for {
conn, err := l.Accept()
if err != nil {
errCh <- err
return
}
free, err := lim.Accept(conn)
if err != nil {
errCh <- err
return
}
conn = Wrap(conn, free)
select {
case connCh <- conn:
case <-ctx.Done():
return
}
}
}()
// Max out connections
conns := make([]net.Conn, 0, limit)
for i := 0; i < limit; i++ {
conn, err := net.DialTimeout("tcp", l.Addr().String(), 2*time.Second)
require.NoError(t, err)
defer conn.Close()
select {
case c := <-connCh:
conns = append(conns, c)
defer c.Close()
case err := <-errCh:
t.Fatalf("error from server goroutine: %v", err)
}
}
// Close one and assert it was freed by creating a new connection
require.NoError(t, conns[0].Close())
conn, err := net.DialTimeout("tcp", l.Addr().String(), 2*time.Second)
require.NoError(t, err)
defer conn.Close()
select {
case c := <-connCh:
// Yay! Connected as expected!
c.Close()
case err := <-errCh:
// An error from the limiter here indicates a problem with the
// wrapper calling free()
t.Fatalf("error from server goroutine: %v", err)
}
}
// TestWrap_SubLimit asserts that already wrapped connections may be passed to
// a sub-limiter.
func TestWrap_SubLimit(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
l, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
errCh := make(chan error, 1)
connCh := make(chan net.Conn, 1)
go func() {
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
errCh <- err
return
}
select {
case connCh <- conn:
case <-ctx.Done():
return
}
}
}()
// Make a "real" conn
clientConn, err := net.DialTimeout("tcp", l.Addr().String(), 2*time.Second)
require.NoError(t, err)
defer clientConn.Close()
// Limit it
var serverConn net.Conn
select {
case serverConn = <-connCh:
case err = <-errCh:
t.Fatalf("error from listener: %v", err)
}
parent := NewLimiter(Config{
MaxConnsPerClientIP: 5,
})
child := NewLimiter(Config{
MaxConnsPerClientIP: 3,
})
freeParent, err := parent.Accept(serverConn)
require.NoError(t, err)
wrapParent := Wrap(serverConn, freeParent)
defer wrapParent.Close()
freeChild, err := child.Accept(wrapParent)
require.NoError(t, err)
// Success!
freeChild()
}