Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ws-manager-mk2/grpcpool/pool_test.go
2496 views
1
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License-AGPL.txt in the project root for license information.
4
5
package grpcpool_test
6
7
import (
8
"fmt"
9
"net"
10
"testing"
11
"time"
12
13
"google.golang.org/grpc"
14
"google.golang.org/grpc/connectivity"
15
16
"github.com/gitpod-io/gitpod/ws-manager-mk2/grpcpool"
17
)
18
19
// go tests does execute tests concurrently (each test a goroutine)
20
// To avoid clashes, we
21
var lastPort = 22000
22
23
var falseConnectionValidationFunc = func(hostIP string) (valid bool) { return false }
24
25
func getTestAddr() string {
26
// No need to lock() as we do not execute in _parallel_ but _concurrently_
27
port := lastPort + 1
28
lastPort = port
29
return fmt.Sprintf("localhost:%d", port)
30
}
31
32
func getFactory(address string) func(host string) (*grpc.ClientConn, error) {
33
return func(host string) (*grpc.ClientConn, error) {
34
return grpc.Dial(address, grpc.WithInsecure())
35
}
36
}
37
38
func startServer(address string, stop chan struct{}) error {
39
server := grpc.NewServer()
40
41
go func() {
42
lis, err := net.Listen("tcp", address)
43
if err != nil {
44
panic(err)
45
}
46
err = server.Serve(lis)
47
if err != nil && err != grpc.ErrServerStopped {
48
panic(err)
49
}
50
}()
51
go func() {
52
<-stop
53
server.Stop()
54
stop <- struct{}{}
55
}()
56
return nil
57
}
58
59
func stopServer(stop chan struct{}) {
60
stop <- struct{}{}
61
select {
62
case <-stop:
63
return
64
case <-time.After(4 * time.Second):
65
panic("stopServer took too long!")
66
}
67
}
68
69
func TestFirstGet(t *testing.T) {
70
address := getTestAddr()
71
stopTest := make(chan struct{}, 1)
72
err := startServer(address, stopTest)
73
if err != nil {
74
t.Skipf("cannot start server: %v", err)
75
return
76
}
77
defer stopServer(stopTest)
78
79
pool := grpcpool.New(getFactory(address), falseConnectionValidationFunc)
80
81
conn, err := pool.Get("foo")
82
if err != nil {
83
t.Errorf("Get returned error when it shouldn't have: %v", err)
84
return
85
}
86
if conn == nil {
87
t.Errorf("Get returned conn == nil")
88
}
89
90
connB, err := pool.Get("foo")
91
if err != nil {
92
t.Errorf("Get returned error when it shouldn't have: %v", err)
93
return
94
}
95
if connB == nil {
96
t.Errorf("Get returned conn == nil")
97
}
98
if connB != conn {
99
t.Errorf("Get did not return the same connection")
100
}
101
}
102
103
func TestGetShutDown(t *testing.T) {
104
address := getTestAddr()
105
stopTest := make(chan struct{}, 1)
106
err := startServer(address, stopTest)
107
if err != nil {
108
t.Skipf("cannot start server: %v", err)
109
return
110
}
111
defer stopServer(stopTest)
112
113
pool := grpcpool.New(getFactory(address), falseConnectionValidationFunc)
114
115
conn, err := pool.Get("foo")
116
if err != nil {
117
t.Errorf("Get returned error when it shouldn't have: %v", err)
118
return
119
}
120
if conn == nil {
121
t.Errorf("Get returned conn == nil")
122
}
123
124
conn.Close()
125
connB, err := pool.Get("foo")
126
if err != nil {
127
t.Errorf("Get returned error when it shouldn't have: %v", err)
128
return
129
}
130
if connB == nil {
131
t.Errorf("Get returned conn == nil")
132
}
133
if connB == conn {
134
t.Errorf("Get returned the same connection although it was closed")
135
}
136
}
137
138
func TestClosed(t *testing.T) {
139
address := getTestAddr()
140
stopTest := make(chan struct{}, 1)
141
err := startServer(address, stopTest)
142
if err != nil {
143
t.Skipf("cannot start server: %v", err)
144
return
145
}
146
defer stopServer(stopTest)
147
148
pool := grpcpool.New(getFactory(address), falseConnectionValidationFunc)
149
150
conn, err := pool.Get("foo")
151
if conn == nil || err != nil {
152
t.Errorf("Get returned an error or no connection: %v", err)
153
return
154
}
155
156
err = pool.Close()
157
if err != nil {
158
t.Errorf("Close returned an error: %v", err)
159
}
160
161
if conn.GetState() != connectivity.Shutdown {
162
t.Errorf("Close did not close connections in the pool")
163
}
164
165
conn, err = pool.Get("foo")
166
if err != grpcpool.ErrPoolClosed {
167
t.Errorf("Get did not return ErrPoolClosed even though pool was closed")
168
}
169
if conn != nil {
170
t.Errorf("Get returned a connection even though pool was closed")
171
}
172
}
173
174
func TestValidateConnections(t *testing.T) {
175
address := getTestAddr()
176
stopTest := make(chan struct{}, 1)
177
err := startServer(address, stopTest)
178
if err != nil {
179
t.Skipf("cannot start server: %v", err)
180
return
181
}
182
defer stopServer(stopTest)
183
184
checkFn := func(checkAddress string) bool {
185
if address != checkAddress {
186
t.Errorf("check address is invalid, expected %v, but returned %v", address, checkAddress)
187
return false
188
}
189
190
return true
191
}
192
193
pool := grpcpool.New(getFactory(address), checkFn)
194
195
conn, err := pool.Get(address)
196
if err != nil {
197
t.Errorf("Get returned error when it shouldn't have: %v", err)
198
return
199
}
200
if conn == nil {
201
t.Errorf("Get returned conn == nil")
202
}
203
204
pool.ValidateConnections()
205
}
206
207