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 }