1
16
17 package grpc
18
19 import (
20 "context"
21 "fmt"
22 "net"
23 "net/http"
24 "net/http/httptest"
25 "strconv"
26 "strings"
27 "testing"
28 "time"
29
30 "github.com/stretchr/testify/assert"
31 "google.golang.org/grpc"
32 grpchealth "google.golang.org/grpc/health/grpc_health_v1"
33
34 "k8s.io/kubernetes/pkg/probe"
35 )
36
37 func TestNew(t *testing.T) {
38 t.Run("Should: implement Probe interface", func(t *testing.T) {
39 s := New()
40 assert.Implements(t, (*Prober)(nil), s)
41 })
42 }
43
44 type successServerMock struct {
45 }
46
47 func (s successServerMock) Check(context.Context, *grpchealth.HealthCheckRequest) (*grpchealth.HealthCheckResponse, error) {
48 return &grpchealth.HealthCheckResponse{
49 Status: grpchealth.HealthCheckResponse_SERVING,
50 }, nil
51 }
52
53 func (s successServerMock) Watch(_ *grpchealth.HealthCheckRequest, stream grpchealth.Health_WatchServer) error {
54 return stream.Send(&grpchealth.HealthCheckResponse{
55 Status: grpchealth.HealthCheckResponse_SERVING,
56 })
57 }
58
59 type errorTimeoutServerMock struct {
60 }
61
62 func (e errorTimeoutServerMock) Check(context.Context, *grpchealth.HealthCheckRequest) (*grpchealth.HealthCheckResponse, error) {
63 time.Sleep(time.Second * 4)
64 return &grpchealth.HealthCheckResponse{
65 Status: grpchealth.HealthCheckResponse_SERVING,
66 }, nil
67 }
68
69 func (e errorTimeoutServerMock) Watch(_ *grpchealth.HealthCheckRequest, stream grpchealth.Health_WatchServer) error {
70 time.Sleep(time.Second * 4)
71 return stream.Send(&grpchealth.HealthCheckResponse{
72 Status: grpchealth.HealthCheckResponse_SERVING,
73 })
74 }
75
76 type errorNotServeServerMock struct {
77 }
78
79 func (e errorNotServeServerMock) Check(context.Context, *grpchealth.HealthCheckRequest) (*grpchealth.HealthCheckResponse, error) {
80 return &grpchealth.HealthCheckResponse{
81 Status: grpchealth.HealthCheckResponse_NOT_SERVING,
82 }, nil
83 }
84
85 func (e errorNotServeServerMock) Watch(_ *grpchealth.HealthCheckRequest, stream grpchealth.Health_WatchServer) error {
86 return stream.Send(&grpchealth.HealthCheckResponse{
87 Status: grpchealth.HealthCheckResponse_NOT_SERVING,
88 })
89 }
90
91 func TestGrpcProber_Probe(t *testing.T) {
92 t.Run("Should: failed but return nil error because cant find host", func(t *testing.T) {
93 s := New()
94 p, o, err := s.Probe("", "", 32, time.Second)
95 assert.Equal(t, probe.Failure, p)
96 assert.Equal(t, nil, err)
97 assert.Equal(t, "timeout: failed to connect service \":32\" within 1s: context deadline exceeded", o)
98 })
99 t.Run("Should: return nil error because connection closed", func(t *testing.T) {
100 s := New()
101 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
102 fmt.Fprint(w, "res")
103 }))
104 u := strings.Split(server.URL, ":")
105 assert.Equal(t, 3, len(u))
106
107 port, err := strconv.Atoi(u[2])
108 assert.Equal(t, nil, err)
109
110
111 time.Sleep(2 * time.Second)
112 p, _, err := s.Probe("127.0.0.1", "", port, time.Second)
113 assert.Equal(t, probe.Failure, p)
114 assert.Equal(t, nil, err)
115 })
116 t.Run("Should: return nil error because server response not served", func(t *testing.T) {
117 s := New()
118 lis, _ := net.Listen("tcp", ":0")
119 port := lis.Addr().(*net.TCPAddr).Port
120 grpcServer := grpc.NewServer()
121 defer grpcServer.Stop()
122 grpchealth.RegisterHealthServer(grpcServer, &errorNotServeServerMock{})
123 go func() {
124 _ = grpcServer.Serve(lis)
125 }()
126
127 time.Sleep(2 * time.Second)
128 p, o, err := s.Probe("0.0.0.0", "", port, time.Second)
129 assert.Equal(t, probe.Failure, p)
130 assert.Equal(t, nil, err)
131 assert.Equal(t, "service unhealthy (responded with \"NOT_SERVING\")", o)
132 })
133 t.Run("Should: return nil-error because server not response in time", func(t *testing.T) {
134 s := New()
135 lis, _ := net.Listen("tcp", ":0")
136 port := lis.Addr().(*net.TCPAddr).Port
137
138 grpcServer := grpc.NewServer()
139 defer grpcServer.Stop()
140 grpchealth.RegisterHealthServer(grpcServer, &errorTimeoutServerMock{})
141 go func() {
142 _ = grpcServer.Serve(lis)
143 }()
144
145 time.Sleep(2 * time.Second)
146 p, o, err := s.Probe("0.0.0.0", "", port, time.Second*2)
147 assert.Equal(t, probe.Failure, p)
148 assert.Equal(t, nil, err)
149 assert.Equal(t, "timeout: health rpc did not complete within 2s", o)
150
151 })
152 t.Run("Should: not return error because check was success", func(t *testing.T) {
153 s := New()
154 lis, _ := net.Listen("tcp", ":0")
155 port := lis.Addr().(*net.TCPAddr).Port
156
157 grpcServer := grpc.NewServer()
158 defer grpcServer.Stop()
159 grpchealth.RegisterHealthServer(grpcServer, &successServerMock{})
160 go func() {
161 _ = grpcServer.Serve(lis)
162 }()
163
164 time.Sleep(2 * time.Second)
165 p, _, err := s.Probe("0.0.0.0", "", port, time.Second*2)
166 assert.Equal(t, probe.Success, p)
167 assert.Equal(t, nil, err)
168 })
169 t.Run("Should: not return error because check was success, when listen port is 0", func(t *testing.T) {
170 s := New()
171 lis, _ := net.Listen("tcp", ":0")
172 port := lis.Addr().(*net.TCPAddr).Port
173
174 grpcServer := grpc.NewServer()
175 defer grpcServer.Stop()
176 grpchealth.RegisterHealthServer(grpcServer, &successServerMock{})
177 go func() {
178 _ = grpcServer.Serve(lis)
179 }()
180
181 time.Sleep(2 * time.Second)
182 p, _, err := s.Probe("0.0.0.0", "", port, time.Second*2)
183 assert.Equal(t, probe.Success, p)
184 assert.Equal(t, nil, err)
185 })
186 }
187
View as plain text