-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathserver_test.go
173 lines (153 loc) · 4.42 KB
/
server_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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package kitty
import (
"bytes"
"context"
"encoding/json"
"errors"
"net/http"
"reflect"
"testing"
"time"
"github.com/go-kit/kit/endpoint"
)
func TestServer(t *testing.T) {
shutdownCalled := false
ctx, cancel := context.WithCancel(context.TODO())
exitError := make(chan error)
tr := NewHTTPTransport(DefaultConfig).
Endpoint("POST", "/foo", testEP, Decoder(goodDecoder)).
Endpoint("GET", "/decoding_error", testEP, Decoder(badDecoder))
srv := NewServer(tr).Shutdown(func() {
shutdownCalled = true
})
go func() {
exitError <- srv.Run(ctx)
}()
start := time.Now()
for {
resp, err := http.Get("http://localhost:8080/alivez")
if err == nil && resp.StatusCode == http.StatusOK {
break
}
if time.Since(start) > 500*time.Millisecond {
t.Fatal("server did not start within 500msec or liveness returned an error")
}
time.Sleep(50 * time.Millisecond)
}
{
resp, err := http.Get("http://localhost:8080/readyz")
if err != nil || resp.StatusCode != http.StatusOK {
t.Error("readyness returned an error")
}
}
{
resp, err := http.Post("http://localhost:8080/foo", "application/json", bytes.NewBufferString(`{"foo":"bar"}`))
if err != nil {
t.Errorf("http.Get returned an error : %s", err)
} else {
if resp.StatusCode != 200 {
t.Errorf("receive a %d status instead of 200", resp.StatusCode)
}
resData := testStruct{}
err := json.NewDecoder(resp.Body).Decode(&resData)
resp.Body.Close()
if err != nil {
t.Errorf("json.Decode returned an error : %s", err)
} else if !reflect.DeepEqual(resData, testStruct{Foo: "bar"}) {
t.Errorf("http.Get returned invalid data : %+v", resData)
}
}
}
{
resp, err := http.Post("http://localhost:8080/foo", "application/json", bytes.NewBufferString(`{"status":404}`))
if err != nil {
t.Errorf("http.Get returned an error : %s", err)
} else {
if resp.StatusCode != 404 {
t.Errorf("receive a %d status instead of 404", resp.StatusCode)
}
}
}
{
resp, err := http.Get("http://localhost:8080/decoding_error")
if err != nil {
t.Errorf("http.Get returned an error : %s", err)
} else {
resp.Body.Close()
if resp.StatusCode != http.StatusBadRequest {
t.Errorf("A decoding error should return a BadRequest status, not %d", resp.StatusCode)
}
}
}
cancel()
select {
case <-time.After(time.Second):
t.Error("Server.Run has not stopped after 1sec")
case err := <-exitError:
if err != nil && err != context.Canceled {
t.Errorf("Server.Run returned an error : %s", err)
}
}
if !shutdownCalled {
t.Error("Shutdown functions are not called")
}
}
type testStruct struct {
Foo string `json:"foo"`
Status int `json:"status"`
err error
}
func testEP(_ context.Context, req interface{}) (interface{}, error) {
if r, ok := req.(*testStruct); ok && r.Status != 0 {
return nil, httpError(r.Status)
}
return req, nil
}
func goodDecoder(_ context.Context, r *http.Request) (interface{}, error) {
request := &testStruct{}
err := json.NewDecoder(r.Body).Decode(request)
return request, err
}
func badDecoder(_ context.Context, _ *http.Request) (interface{}, error) {
return nil, errors.New("decoding error")
}
type failingTransport struct {
Transport
}
func (*failingTransport) RegisterEndpoints(m endpoint.Middleware) error { return nil }
func (*failingTransport) Start(ctx context.Context) error { return errors.New("unable to start") }
func (*failingTransport) Shutdown(ctx context.Context) error { return nil }
type workingTransport struct {
running chan struct{}
Transport
}
func (*workingTransport) RegisterEndpoints(m endpoint.Middleware) error { return nil }
func (t *workingTransport) Start(ctx context.Context) error {
defer func() { close(t.running) }()
<-ctx.Done()
return nil
}
func (*workingTransport) Shutdown(ctx context.Context) error { return nil }
func TestStartError(t *testing.T) {
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
defer cancel()
exitError := make(chan error)
wt := &workingTransport{running: make(chan struct{})}
srv := NewServer(&failingTransport{}, wt)
go func() {
exitError <- srv.Run(ctx)
}()
select {
case <-ctx.Done():
t.Error("Server.Run has not stopped after 5sec")
case err := <-exitError:
if err == nil || err.Error() != "unable to start" {
t.Errorf("Server.Run returned an invalid error : %v", err)
}
}
select {
case <-ctx.Done():
t.Error("Alternate transport has not stopped after 5sec")
case <-wt.running:
}
}