package wsconn import ( "io" "net/http" "net/http/httptest" "strings" "testing" "time" "github.com/gorilla/websocket" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // 基本煙測:確認 wsconn 能在真實 WebSocket 之上做雙向傳輸。 // // 不深度測試(邏輯與 POC 完全一致,POC 已驗證);此測試主要保證: // - package 可編譯 // - New / Read / Write / Close / SetReadDeadline 可實際運作 // - 符合 net.Conn 介面 func TestConn_ReadWrite(t *testing.T) { // 啟動一個 echo server:把收到的 bytes 原封寫回。 var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } done := make(chan struct{}) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ws, err := upgrader.Upgrade(w, r, nil) if err != nil { t.Errorf("upgrade failed: %v", err) return } defer ws.Close() defer close(done) conn := New(ws) // 讀一整塊 → 寫回 buf := make([]byte, 64) n, err := conn.Read(buf) if err != nil { t.Errorf("server read failed: %v", err) return } if _, err := conn.Write(buf[:n]); err != nil { t.Errorf("server write failed: %v", err) } })) defer server.Close() wsURL := "ws" + strings.TrimPrefix(server.URL, "http") + "/" dialer := websocket.DefaultDialer rawClient, _, err := dialer.Dial(wsURL, nil) require.NoError(t, err) defer rawClient.Close() client := New(rawClient) // 寫 → 讀回 payload := []byte("hello wsconn") _, err = client.Write(payload) require.NoError(t, err) buf := make([]byte, len(payload)) _, err = io.ReadFull(client, buf) require.NoError(t, err) assert.Equal(t, payload, buf) // 等 server goroutine 結束 select { case <-done: case <-time.After(2 * time.Second): t.Fatal("server goroutine 未在 2s 內完成") } } func TestConn_SetDeadline_ExpiredReadReturnsError(t *testing.T) { // 建一個永遠不送資料的 server,讓 client read deadline 觸發 timeout。 var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }} server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ws, err := upgrader.Upgrade(w, r, nil) if err != nil { return } defer ws.Close() // 故意 block — 等 client 斷開 _, _, _ = ws.NextReader() })) defer server.Close() wsURL := "ws" + strings.TrimPrefix(server.URL, "http") + "/" raw, _, err := websocket.DefaultDialer.Dial(wsURL, nil) require.NoError(t, err) defer raw.Close() c := New(raw) require.NoError(t, c.SetReadDeadline(time.Now().Add(50*time.Millisecond))) buf := make([]byte, 16) _, err = c.Read(buf) assert.Error(t, err, "過期 deadline 下 Read 應回 error") }