sdk: simplify test using testify
Kim committed
Nov 18, 2025 at 11:04 UTC
0b356d2eba126533a4f5e75949c193ddef341330
6 files changed
+58
-92
go.mod
+3
@@ -7,6 +7,7 @@ require (
7
github.com/hashicorp/yamux v0.1.2
8
github.com/planetscale/vtprotobuf v0.6.0
9
github.com/rs/zerolog v1.34.0
10
+ github.com/stretchr/testify v1.9.0
11
github.com/valyala/bytebufferpool v1.0.0
12
golang.org/x/crypto v0.43.0
13
golang.org/x/net v0.46.0
@@ -15,8 +16,10 @@ require (
16
)
17
18
require (
19
+ github.com/davecgh/go-spew v1.1.1 // indirect
20
github.com/mattn/go-colorable v0.1.14 // indirect
21
github.com/mattn/go-isatty v0.0.20 // indirect
22
+ github.com/pmezard/go-difflib v1.0.0 // indirect
23
golang.org/x/sys v0.37.0 // indirect
24
golang.org/x/text v0.30.0 // indirect
25
)
go.sum
+6
@@ -1,4 +1,6 @@
1
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
2
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
5
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
6
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
@@ -16,9 +18,13 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
18
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
19
github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA=
20
github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
21
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
22
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
23
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
24
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
25
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
26
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
27
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
28
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
29
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
30
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
sdk/client.go
+1
-1
@@ -29,7 +29,7 @@ type Client struct {
29
waitGroup sync.WaitGroup // Track all listener workers
30
}
31
32
-func NewClient(opt ...Option) (*Client, error) {
32
+func NewClient(opt ...ClientOption) (*Client, error) {
33
log.Debug().Msg("[SDK] Creating new Client")
34
35
config := &ClientConfig{
sdk/client_e2e_test.go
+32
-71
@@ -14,6 +14,9 @@ import (
14
"github.com/gorilla/websocket"
15
"github.com/rs/zerolog"
16
"github.com/rs/zerolog/log"
17
+ "github.com/stretchr/testify/assert"
18
+ "github.com/stretchr/testify/require"
19
+
20
"gosuda.org/portal/portal"
21
"gosuda.org/portal/portal/core/cryptoops"
22
"gosuda.org/portal/portal/utils/wsstream"
@@ -33,9 +36,7 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
36
// 1. Create relay server credential
37
log.Info().Msg("[TEST] Step 1: Creating relay server credential")
38
relayServerCred, err := cryptoops.NewCredential()
36
- if err != nil {
37
- t.Fatalf("Failed to create relay server credential: %v", err)
38
- }
39
+ require.NoError(t, err, "Failed to create relay server credential")
40
log.Debug().Str("relay_id", relayServerCred.ID()).Msg("[TEST] Relay server credential created")
41
42
// 2. Start relay server
@@ -94,18 +95,14 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
95
appClient, err := NewClient(func(c *ClientConfig) {
96
c.BootstrapServers = []string{"ws://127.0.0.1:14017/relay"}
97
})
97
- if err != nil {
98
- t.Fatalf("Failed to create app SDK client: %v", err)
99
- }
98
+ require.NoError(t, err, "Failed to create app SDK client")
99
defer appClient.Close()
100
log.Info().Msg("[TEST] App SDK client created")
101
102
// 5. Register listener on app side
103
log.Info().Msg("[TEST] Step 5: Registering app listener")
104
appListener, err := appClient.Listen(appCred, "test-app", []string{"http/1.1"})
106
- if err != nil {
107
- t.Fatalf("Failed to create app listener: %v", err)
108
- }
105
+ require.NoError(t, err, "Failed to create app listener")
106
defer appListener.Close()
107
log.Info().Str("lease_id", appCred.ID()).Msg("[TEST] App listener registered")
108
@@ -143,9 +140,7 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
140
clientSDK, err := NewClient(func(c *ClientConfig) {
141
c.BootstrapServers = []string{"ws://127.0.0.1:14017/relay"}
142
})
146
- if err != nil {
147
- t.Fatalf("Failed to create client SDK: %v", err)
148
- }
143
+ require.NoError(t, err, "Failed to create client SDK")
144
defer clientSDK.Close()
145
log.Info().Msg("[TEST] Client SDK client created")
146
@@ -156,9 +151,7 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
151
// 10. Dial to app through relay
152
log.Info().Msg("[TEST] Step 10: Client dialing to app through relay")
153
conn, err := clientSDK.Dial(clientCred, appCred.ID(), "http/1.1")
159
- if err != nil {
160
- t.Fatalf("Failed to dial to app: %v", err)
161
- }
154
+ require.NoError(t, err, "Failed to dial to app")
155
defer conn.Close()
156
log.Info().
157
Str("local", conn.LocalAddr().String()).
@@ -170,22 +163,18 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
163
164
// Create HTTP request
165
req, err := http.NewRequest("GET", "http://test-app/", nil)
173
- if err != nil {
174
- t.Fatalf("Failed to create HTTP request: %v", err)
175
- }
166
+ require.NoError(t, err, "Failed to create HTTP request")
167
168
// Write HTTP request to connection
169
if err := req.Write(conn); err != nil {
179
- t.Fatalf("Failed to write HTTP request: %v", err)
170
+ require.NoError(t, err, "Failed to write HTTP request")
171
}
172
log.Debug().Msg("[TEST] HTTP request sent")
173
174
// Read HTTP response
175
log.Info().Msg("[TEST] Step 12: Reading HTTP response")
176
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
186
- if err != nil {
187
- t.Fatalf("Failed to read HTTP response: %v", err)
188
- }
177
+ require.NoError(t, err, "Failed to read HTTP response")
178
defer resp.Body.Close()
179
180
log.Debug().
@@ -195,30 +184,20 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
184
185
// Read response body
186
body, err := io.ReadAll(resp.Body)
198
- if err != nil {
199
- t.Fatalf("Failed to read response body: %v", err)
200
- }
187
+ require.NoError(t, err, "Failed to read response body")
188
189
responseStr := string(body)
190
log.Info().Str("body", responseStr).Msg("[TEST] Response body received")
191
192
// 12. Verify response
193
log.Info().Msg("[TEST] Step 13: Verifying response")
207
- if resp.StatusCode != 200 {
208
- t.Errorf("Expected status code 200, got %d", resp.StatusCode)
209
- }
210
-
211
- if len(body) == 0 {
212
- t.Error("Expected non-empty response body")
213
- }
194
+ require.Equal(t, http.StatusOK, resp.StatusCode, "Expected status code 200")
195
+ require.NotEmpty(t, body, "Expected non-empty response body")
196
197
// Check if response contains test message
198
bodyStr := string(body)
217
- if len(bodyStr) == 0 {
218
- t.Error("Response body is empty")
219
- } else {
220
- log.Info().Str("response", bodyStr).Msg("[TEST] Response verification successful")
221
- }
199
+ require.NotEmpty(t, bodyStr, "Response body is empty")
200
+ log.Info().Str("response", bodyStr).Msg("[TEST] Response verification successful")
201
202
log.Info().Msg("=== E2E Test Completed Successfully ===")
203
}
@@ -229,9 +208,7 @@ func TestE2E_MultipleConnections(t *testing.T) {
208
209
// Setup relay server
210
relayServerCred, err := cryptoops.NewCredential()
232
- if err != nil {
233
- t.Fatalf("Failed to create relay server credential: %v", err)
234
- }
211
+ require.NoError(t, err, "Failed to create relay server credential")
212
213
relayServer := portal.NewRelayServer(relayServerCred, []string{"ws://127.0.0.1:14018/relay"})
214
relayServer.Start()
@@ -271,15 +248,11 @@ func TestE2E_MultipleConnections(t *testing.T) {
248
appClient, err := NewClient(func(c *ClientConfig) {
249
c.BootstrapServers = []string{"ws://127.0.0.1:14018/relay"}
250
})
274
- if err != nil {
275
- t.Fatalf("Failed to create app SDK client: %v", err)
276
- }
251
+ require.NoError(t, err, "Failed to create app SDK client")
252
defer appClient.Close()
253
254
appListener, err := appClient.Listen(appCred, "multi-test-app", []string{"http/1.1"})
280
- if err != nil {
281
- t.Fatalf("Failed to create app listener: %v", err)
282
- }
255
+ require.NoError(t, err, "Failed to create app listener")
256
defer appListener.Close()
257
258
// Serve echo server
@@ -304,9 +277,7 @@ func TestE2E_MultipleConnections(t *testing.T) {
277
clientSDK, err := NewClient(func(c *ClientConfig) {
278
c.BootstrapServers = []string{"ws://127.0.0.1:14018/relay"}
279
})
307
- if err != nil {
308
- t.Fatalf("Failed to create client SDK: %v", err)
309
- }
280
+ require.NoError(t, err, "Failed to create client SDK")
281
defer clientSDK.Close()
282
283
time.Sleep(2 * time.Second)
@@ -321,8 +292,7 @@ func TestE2E_MultipleConnections(t *testing.T) {
292
log.Debug().Int("conn_num", i).Msg("[TEST] Starting connection")
293
294
conn, err := clientSDK.Dial(clientCred, appCred.ID(), "http/1.1")
324
- if err != nil {
325
- t.Errorf("Connection %d failed to dial: %v", i, err)
295
+ if !assert.NoError(t, err, "Connection %d failed to dial", i) {
296
return
297
}
298
defer conn.Close()
@@ -330,20 +300,19 @@ func TestE2E_MultipleConnections(t *testing.T) {
300
testData := fmt.Sprintf("test-message-%d", i)
301
302
// Write test data
333
- if _, err := conn.Write([]byte(testData)); err != nil {
334
- t.Errorf("Connection %d failed to write: %v", i, err)
303
+ _, err = conn.Write([]byte(testData))
304
+ if !assert.NoError(t, err, "Connection %d failed to write", i) {
305
return
306
}
307
308
// Read echoed data
309
buf := make([]byte, len(testData))
340
- if _, err := io.ReadFull(conn, buf); err != nil {
341
- t.Errorf("Connection %d failed to read: %v", i, err)
310
+ _, err = io.ReadFull(conn, buf)
311
+ if !assert.NoError(t, err, "Connection %d failed to read", i) {
312
return
313
}
314
345
- if string(buf) != testData {
346
- t.Errorf("Connection %d: expected %q, got %q", i, testData, string(buf))
315
+ if !assert.Equal(t, testData, string(buf), "Connection %d: unexpected echo data", i) {
316
return
317
}
318
@@ -376,13 +345,10 @@ func TestE2E_ConnectionTimeout(t *testing.T) {
345
346
select {
347
case err := <-done:
379
- if err == nil {
380
- t.Error("Expected error when connecting to non-existent relay")
381
- } else {
382
- log.Info().Err(err).Msg("[TEST] Got expected error")
383
- }
348
+ require.Error(t, err, "Expected error when connecting to non-existent relay")
349
+ log.Info().Err(err).Msg("[TEST] Got expected error")
350
case <-ctx.Done():
385
- t.Error("Connection attempt did not complete within timeout")
351
+ require.Fail(t, "Connection attempt did not complete within timeout")
352
}
353
354
// Try to dial to non-existent lease
@@ -423,9 +389,7 @@ func TestE2E_ConnectionTimeout(t *testing.T) {
389
clientSDK, err := NewClient(func(c *ClientConfig) {
390
c.BootstrapServers = []string{"ws://127.0.0.1:14019/relay"}
391
})
426
- if err != nil {
427
- t.Fatalf("Failed to create client SDK: %v", err)
428
- }
392
+ require.NoError(t, err, "Failed to create client SDK")
393
defer clientSDK.Close()
394
395
time.Sleep(1 * time.Second)
@@ -433,11 +397,8 @@ func TestE2E_ConnectionTimeout(t *testing.T) {
397
// Try to dial to non-existent lease
398
log.Info().Msg("[TEST] Attempting to dial non-existent lease")
399
_, err = clientSDK.Dial(clientCred, "non-existent-lease-id", "http/1.1")
436
- if err == nil {
437
- t.Error("Expected error when dialing non-existent lease")
438
- } else {
439
- log.Info().Err(err).Msg("[TEST] Got expected error for non-existent lease")
440
- }
400
+ require.Error(t, err, "Expected error when dialing non-existent lease")
401
+ log.Info().Err(err).Msg("[TEST] Got expected error for non-existent lease")
402
403
log.Info().Msg("=== Connection Timeout Test Completed ===")
404
}
sdk/types.go
+6
-6
@@ -33,33 +33,33 @@ type ClientConfig struct {
33
ReconnectInterval time.Duration // Interval between reconnection attempts (default: 5 seconds)
34
}
35
36
-type Option func(*ClientConfig)
36
+type ClientOption func(*ClientConfig)
37
38
-func WithBootstrapServers(servers []string) Option {
38
+func WithBootstrapServers(servers []string) ClientOption {
39
return func(c *ClientConfig) {
40
c.BootstrapServers = servers
41
}
42
}
43
44
-func WithDialer(dialer func(context.Context, string) (io.ReadWriteCloser, error)) Option {
44
+func WithDialer(dialer func(context.Context, string) (io.ReadWriteCloser, error)) ClientOption {
45
return func(c *ClientConfig) {
46
c.Dialer = dialer
47
}
48
}
49
50
-func WithHealthCheckInterval(interval time.Duration) Option {
50
+func WithHealthCheckInterval(interval time.Duration) ClientOption {
51
return func(c *ClientConfig) {
52
c.HealthCheckInterval = interval
53
}
54
}
55
56
-func WithReconnectMaxRetries(retries int) Option {
56
+func WithReconnectMaxRetries(retries int) ClientOption {
57
return func(c *ClientConfig) {
58
c.ReconnectMaxRetries = retries
59
}
60
}
61
62
-func WithReconnectInterval(interval time.Duration) Option {
62
+func WithReconnectInterval(interval time.Duration) ClientOption {
63
return func(c *ClientConfig) {
64
c.ReconnectInterval = interval
65
}
sdk/utils_test.go
+10
-14
@@ -1,6 +1,10 @@
1
package sdk
2
3
-import "testing"
3
+import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/assert"
7
+)
8
9
func TestIsURLSafeName(t *testing.T) {
10
tests := []struct {
@@ -26,7 +30,7 @@ func TestIsURLSafeName(t *testing.T) {
30
{"chinese", "中文服务", true},
31
{"arabic", "خدمة", true},
32
{"mixed languages", "Service-서비스-サービス", true},
29
- {"korean numbers", "서비스23", true},
33
+ {"korean numbers", "서비스3", true},
34
35
// Invalid names
36
{"with space", "my service", false},
@@ -64,9 +68,7 @@ func TestIsURLSafeName(t *testing.T) {
68
for _, tt := range tests {
69
t.Run(tt.name, func(t *testing.T) {
70
result := isURLSafeName(tt.input)
67
- if result != tt.expected {
68
- t.Errorf("isURLSafeName(%q) = %v, want %v", tt.input, result, tt.expected)
69
- }
71
+ assert.Equal(t, tt.expected, result, "isURLSafeName(%q)", tt.input)
72
})
73
}
74
}
@@ -144,17 +146,11 @@ func TestNormalizeBootstrapServer(t *testing.T) {
146
t.Run(tt.name, func(t *testing.T) {
147
got, err := normalizeBootstrapServer(tt.input)
148
if tt.shouldFail {
147
- if err == nil {
148
- t.Fatalf("normalizeBootstrapServer(%q) expected error, got nil", tt.input)
149
- }
149
+ assert.Error(t, err, "normalizeBootstrapServer(%q) expected error", tt.input)
150
return
151
}
152
- if err != nil {
153
- t.Fatalf("normalizeBootstrapServer(%q) unexpected error: %v", tt.input, err)
154
- }
155
- if got != tt.want {
156
- t.Fatalf("normalizeBootstrapServer(%q) = %q, want %q", tt.input, got, tt.want)
157
- }
152
+ assert.NoError(t, err, "normalizeBootstrapServer(%q) unexpected error", tt.input)
153
+ assert.Equal(t, tt.want, got, "normalizeBootstrapServer(%q)", tt.input)
154
})
155
}
156
}