Skip to content

Commit 3059f5e

Browse files
committed
refactoring server lifecycle test
1 parent 248137e commit 3059f5e

File tree

6 files changed

+459
-607
lines changed

6 files changed

+459
-607
lines changed
Lines changed: 37 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
package integration
22

33
import (
4-
"bytes"
54
"context"
65
"crypto/tls"
7-
"fmt"
8-
"io"
96
"net"
107
"net/http"
118
"testing"
@@ -16,8 +13,6 @@ import (
1613
"github.com/stretchr/testify/require"
1714
employeev1 "github.com/wundergraph/cosmo/router-tests/testdata/connectrpc/client/employee.v1"
1815
"github.com/wundergraph/cosmo/router-tests/testdata/connectrpc/client/employee.v1/employeev1connect"
19-
"github.com/wundergraph/cosmo/router/pkg/connectrpc"
20-
"go.uber.org/zap"
2116
"golang.org/x/net/http2"
2217
)
2318

@@ -26,49 +21,15 @@ import (
2621
func TestConnectRPC_ClientProtocols(t *testing.T) {
2722
t.Parallel()
2823

29-
// Create mock GraphQL server
30-
graphqlServer := newMockGraphQLServer(func(w http.ResponseWriter, r *http.Request) {
31-
w.Header().Set("Content-Type", "application/json")
32-
w.WriteHeader(http.StatusOK)
33-
w.Write([]byte(`{
34-
"data": {
35-
"employee": {
36-
"id": 1,
37-
"tag": "employee-1",
38-
"details": {
39-
"forename": "John",
40-
"surname": "Doe",
41-
"pets": [{"name": "Fluffy"}],
42-
"location": {"key": {"name": "San Francisco"}}
43-
}
44-
}
45-
}
46-
}`))
24+
// Use shared helper for employee GraphQL handler
25+
ts := NewTestConnectRPCServer(t, ConnectRPCServerOptions{
26+
GraphQLHandler: EmployeeGraphQLHandler(),
4727
})
48-
defer graphqlServer.Close()
49-
50-
// Start ConnectRPC server
51-
graphqlEndpoint := graphqlServer.URL + "/graphql"
52-
fmt.Printf("[Test] Mock GraphQL Server URL: %s\n", graphqlServer.URL)
53-
fmt.Printf("[Test] GraphQL Endpoint configured: %s\n", graphqlEndpoint)
5428

55-
server, err := connectrpc.NewServer(connectrpc.ServerConfig{
56-
ServicesDir: "testdata/connectrpc/services",
57-
GraphQLEndpoint: graphqlEndpoint,
58-
ListenAddr: "localhost:0",
59-
Logger: zap.NewNop(),
60-
})
29+
err := ts.Start()
6130
require.NoError(t, err)
6231

63-
err = server.Start()
64-
require.NoError(t, err)
65-
defer func() {
66-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
67-
defer cancel()
68-
server.Stop(ctx)
69-
}()
70-
71-
baseURL := "http://" + server.Addr().String()
32+
baseURL := "http://" + ts.Addr().String()
7233

7334
t.Run("Connect protocol", func(t *testing.T) {
7435
client := employeev1connect.NewEmployeeServiceClient(
@@ -151,34 +112,16 @@ func TestConnectRPC_ClientErrorHandling(t *testing.T) {
151112
t.Parallel()
152113

153114
t.Run("GraphQL error with no data returns CRITICAL", func(t *testing.T) {
154-
graphqlServer := newMockGraphQLServer(func(w http.ResponseWriter, r *http.Request) {
155-
w.Header().Set("Content-Type", "application/json")
156-
w.WriteHeader(http.StatusOK)
157-
w.Write([]byte(`{
158-
"errors": [{"message": "Employee not found"}]
159-
}`))
115+
ts := NewTestConnectRPCServer(t, ConnectRPCServerOptions{
116+
GraphQLHandler: ErrorGraphQLHandler("Employee not found"),
160117
})
161-
defer graphqlServer.Close()
162-
163-
server, err := connectrpc.NewServer(connectrpc.ServerConfig{
164-
ServicesDir: "testdata/connectrpc/services",
165-
GraphQLEndpoint: graphqlServer.URL + "/graphql",
166-
ListenAddr: "localhost:0",
167-
Logger: zap.NewNop(),
168-
})
169-
require.NoError(t, err)
170-
171-
err = server.Start()
118+
119+
err := ts.Start()
172120
require.NoError(t, err)
173-
defer func() {
174-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
175-
defer cancel()
176-
server.Stop(ctx)
177-
}()
178121

179122
client := employeev1connect.NewEmployeeServiceClient(
180123
http.DefaultClient,
181-
"http://"+server.Addr().String(),
124+
"http://"+ts.Addr().String(),
182125
)
183126

184127
req := connect.NewRequest(&employeev1.GetEmployeeByIdRequest{
@@ -196,7 +139,8 @@ func TestConnectRPC_ClientErrorHandling(t *testing.T) {
196139
})
197140

198141
t.Run("GraphQL error with partial data returns NON-CRITICAL", func(t *testing.T) {
199-
graphqlServer := newMockGraphQLServer(func(w http.ResponseWriter, r *http.Request) {
142+
// Custom handler for partial data with errors
143+
handler := func(w http.ResponseWriter, r *http.Request) {
200144
w.Header().Set("Content-Type", "application/json")
201145
w.WriteHeader(http.StatusOK)
202146
w.Write([]byte(`{
@@ -212,29 +156,19 @@ func TestConnectRPC_ClientErrorHandling(t *testing.T) {
212156
"errors": [{"message": "Could not fetch pets"}]
213157
}
214158
}`))
159+
}
160+
161+
ts := NewTestConnectRPCServer(t, ConnectRPCServerOptions{
162+
GraphQLHandler: handler,
215163
})
216-
defer graphqlServer.Close()
217-
218-
server, err := connectrpc.NewServer(connectrpc.ServerConfig{
219-
ServicesDir: "testdata/connectrpc/services",
220-
GraphQLEndpoint: graphqlServer.URL + "/graphql",
221-
ListenAddr: "localhost:0",
222-
Logger: zap.NewNop(),
223-
})
164+
165+
err := ts.Start()
224166
require.NoError(t, err)
225167

226-
err = server.Start()
227-
require.NoError(t, err)
228-
defer func() {
229-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
230-
defer cancel()
231-
server.Stop(ctx)
232-
}()
233-
234168
time.Sleep(100 * time.Millisecond)
235169
client := employeev1connect.NewEmployeeServiceClient(
236170
http.DefaultClient,
237-
"http://"+server.Addr().String(),
171+
"http://"+ts.Addr().String(),
238172
)
239173

240174
req := connect.NewRequest(&employeev1.GetEmployeeByIdRequest{
@@ -250,31 +184,16 @@ func TestConnectRPC_ClientErrorHandling(t *testing.T) {
250184
})
251185

252186
t.Run("HTTP 404 maps to CodeNotFound", func(t *testing.T) {
253-
graphqlServer := newMockGraphQLServer(func(w http.ResponseWriter, r *http.Request) {
254-
w.WriteHeader(http.StatusNotFound)
255-
w.Write([]byte("Not Found"))
256-
})
257-
defer graphqlServer.Close()
258-
259-
server, err := connectrpc.NewServer(connectrpc.ServerConfig{
260-
ServicesDir: "testdata/connectrpc/services",
261-
GraphQLEndpoint: graphqlServer.URL + "/graphql",
262-
ListenAddr: "localhost:0",
263-
Logger: zap.NewNop(),
187+
ts := NewTestConnectRPCServer(t, ConnectRPCServerOptions{
188+
GraphQLHandler: HTTPErrorHandler(http.StatusNotFound, "Not Found"),
264189
})
190+
191+
err := ts.Start()
265192
require.NoError(t, err)
266193

267-
err = server.Start()
268-
require.NoError(t, err)
269-
defer func() {
270-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
271-
defer cancel()
272-
server.Stop(ctx)
273-
}()
274-
275194
client := employeev1connect.NewEmployeeServiceClient(
276195
http.DefaultClient,
277-
"http://"+server.Addr().String(),
196+
"http://"+ts.Addr().String(),
278197
)
279198

280199
req := connect.NewRequest(&employeev1.GetEmployeeByIdRequest{
@@ -290,31 +209,16 @@ func TestConnectRPC_ClientErrorHandling(t *testing.T) {
290209
})
291210

292211
t.Run("HTTP 500 maps to CodeInternal", func(t *testing.T) {
293-
graphqlServer := newMockGraphQLServer(func(w http.ResponseWriter, r *http.Request) {
294-
w.WriteHeader(http.StatusInternalServerError)
295-
w.Write([]byte("Internal Server Error"))
296-
})
297-
defer graphqlServer.Close()
298-
299-
server, err := connectrpc.NewServer(connectrpc.ServerConfig{
300-
ServicesDir: "testdata/connectrpc/services",
301-
GraphQLEndpoint: graphqlServer.URL + "/graphql",
302-
ListenAddr: "localhost:0",
303-
Logger: zap.NewNop(),
212+
ts := NewTestConnectRPCServer(t, ConnectRPCServerOptions{
213+
GraphQLHandler: HTTPErrorHandler(http.StatusInternalServerError, "Internal Server Error"),
304214
})
215+
216+
err := ts.Start()
305217
require.NoError(t, err)
306218

307-
err = server.Start()
308-
require.NoError(t, err)
309-
defer func() {
310-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
311-
defer cancel()
312-
server.Stop(ctx)
313-
}()
314-
315219
client := employeev1connect.NewEmployeeServiceClient(
316220
http.DefaultClient,
317-
"http://"+server.Addr().String(),
221+
"http://"+ts.Addr().String(),
318222
)
319223

320224
req := connect.NewRequest(&employeev1.GetEmployeeByIdRequest{
@@ -335,7 +239,7 @@ func TestConnectRPC_ClientConcurrency(t *testing.T) {
335239
t.Parallel()
336240

337241
var requestCount int
338-
graphqlServer := newMockGraphQLServer(func(w http.ResponseWriter, r *http.Request) {
242+
handler := func(w http.ResponseWriter, r *http.Request) {
339243
requestCount++
340244
w.Header().Set("Content-Type", "application/json")
341245
w.WriteHeader(http.StatusOK)
@@ -351,28 +255,18 @@ func TestConnectRPC_ClientConcurrency(t *testing.T) {
351255
}
352256
}
353257
}`))
258+
}
259+
260+
ts := NewTestConnectRPCServer(t, ConnectRPCServerOptions{
261+
GraphQLHandler: handler,
354262
})
355-
defer graphqlServer.Close()
356-
357-
server, err := connectrpc.NewServer(connectrpc.ServerConfig{
358-
ServicesDir: "testdata/connectrpc/services",
359-
GraphQLEndpoint: graphqlServer.URL + "/graphql",
360-
ListenAddr: "localhost:0",
361-
Logger: zap.NewNop(),
362-
})
363-
require.NoError(t, err)
364-
365-
err = server.Start()
263+
264+
err := ts.Start()
366265
require.NoError(t, err)
367-
defer func() {
368-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
369-
defer cancel()
370-
server.Stop(ctx)
371-
}()
372266

373267
client := employeev1connect.NewEmployeeServiceClient(
374268
http.DefaultClient,
375-
"http://"+server.Addr().String(),
269+
"http://"+ts.Addr().String(),
376270
)
377271

378272
// Make 10 concurrent requests
@@ -396,62 +290,4 @@ func TestConnectRPC_ClientConcurrency(t *testing.T) {
396290
}
397291

398292
assert.Equal(t, numRequests, requestCount, "should have made all requests")
399-
}
400-
401-
// mockGraphQLServer is a simple mock HTTP server for testing
402-
type mockGraphQLServer struct {
403-
server *http.Server
404-
handler http.HandlerFunc
405-
URL string
406-
}
407-
408-
func newMockGraphQLServer(handler http.HandlerFunc) *mockGraphQLServer {
409-
m := &mockGraphQLServer{
410-
handler: handler,
411-
}
412-
413-
mux := http.NewServeMux()
414-
mux.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) {
415-
// Log the incoming request for debugging
416-
body, _ := io.ReadAll(r.Body)
417-
r.Body.Close()
418-
r.Body = io.NopCloser(bytes.NewBuffer(body))
419-
420-
fmt.Printf("[MockGraphQL] Request: %s %s\n", r.Method, r.URL.Path)
421-
fmt.Printf("[MockGraphQL] Headers: %v\n", r.Header)
422-
fmt.Printf("[MockGraphQL] Body: %s\n", string(body))
423-
424-
if m.handler != nil {
425-
m.handler(w, r)
426-
}
427-
428-
fmt.Printf("[MockGraphQL] Response sent\n\n")
429-
})
430-
431-
m.server = &http.Server{
432-
Handler: mux,
433-
Addr: "127.0.0.1:0",
434-
}
435-
436-
listener, err := net.Listen("tcp", m.server.Addr)
437-
if err != nil {
438-
panic(err)
439-
}
440-
441-
m.URL = "http://" + listener.Addr().String()
442-
443-
go m.server.Serve(listener)
444-
445-
// Give the server a moment to start
446-
time.Sleep(10 * time.Millisecond)
447-
448-
return m
449-
}
450-
451-
func (m *mockGraphQLServer) Close() {
452-
if m.server != nil {
453-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
454-
defer cancel()
455-
m.server.Shutdown(ctx)
456-
}
457293
}

0 commit comments

Comments
 (0)