@@ -16,6 +16,7 @@ import (
1616 "golang.org/x/xerrors"
1717
1818 "nhooyr.io/websocket"
19+ "nhooyr.io/websocket/internal/test/cmp"
1920 "nhooyr.io/websocket/internal/test/wstest"
2021 "nhooyr.io/websocket/internal/test/xrand"
2122 "nhooyr.io/websocket/internal/xsync"
@@ -31,9 +32,6 @@ func TestConn(t *testing.T) {
3132 t .Run ("" , func (t * testing.T ) {
3233 t .Parallel ()
3334
34- ctx , cancel := context .WithTimeout (context .Background (), time .Second * 10 )
35- defer cancel ()
36-
3735 copts := & websocket.CompressionOptions {
3836 Mode : websocket .CompressionMode (xrand .Int (int (websocket .CompressionDisabled ) + 1 )),
3937 Threshold : xrand .Int (9999 ),
@@ -47,11 +45,14 @@ func TestConn(t *testing.T) {
4745 if err != nil {
4846 t .Fatal (err )
4947 }
50- defer c1 .Close (websocket .StatusInternalError , "" )
5148 defer c2 .Close (websocket .StatusInternalError , "" )
49+ defer c1 .Close (websocket .StatusInternalError , "" )
50+
51+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 10 )
52+ defer cancel ()
5253
5354 echoLoopErr := xsync .Go (func () error {
54- err := wstest .EchoLoop (ctx , c1 )
55+ err := wstest .EchoLoop (ctx , c2 )
5556 return assertCloseStatus (websocket .StatusNormalClosure , err )
5657 })
5758 defer func () {
@@ -62,19 +63,143 @@ func TestConn(t *testing.T) {
6263 }()
6364 defer cancel ()
6465
65- c2 .SetReadLimit (131072 )
66+ c1 .SetReadLimit (131072 )
6667
6768 for i := 0 ; i < 5 ; i ++ {
68- err := wstest .Echo (ctx , c2 , 131072 )
69+ err := wstest .Echo (ctx , c1 , 131072 )
6970 if err != nil {
7071 t .Fatal (err )
7172 }
7273 }
7374
74- c2 .Close (websocket .StatusNormalClosure , "" )
75+ err = c1 .Close (websocket .StatusNormalClosure , "" )
76+ if err != nil {
77+ t .Fatalf ("unexpected error: %v" , err )
78+ }
7579 })
7680 }
7781 })
82+
83+ t .Run ("badClose" , func (t * testing.T ) {
84+ t .Parallel ()
85+
86+ c1 , c2 , err := wstest .Pipe (nil , nil )
87+ if err != nil {
88+ t .Fatal (err )
89+ }
90+ defer c1 .Close (websocket .StatusInternalError , "" )
91+ defer c2 .Close (websocket .StatusInternalError , "" )
92+
93+ err = c1 .Close (- 1 , "" )
94+ if ! cmp .ErrorContains (err , "failed to marshal close frame: status code StatusCode(-1) cannot be set" ) {
95+ t .Fatalf ("unexpected error: %v" , err )
96+ }
97+ })
98+
99+ t .Run ("ping" , func (t * testing.T ) {
100+ t .Parallel ()
101+
102+ c1 , c2 , err := wstest .Pipe (nil , nil )
103+ if err != nil {
104+ t .Fatal (err )
105+ }
106+ defer c1 .Close (websocket .StatusInternalError , "" )
107+ defer c2 .Close (websocket .StatusInternalError , "" )
108+
109+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 15 )
110+ defer cancel ()
111+
112+ c2 .CloseRead (ctx )
113+ c1 .CloseRead (ctx )
114+
115+ for i := 0 ; i < 10 ; i ++ {
116+ err = c1 .Ping (ctx )
117+ if err != nil {
118+ t .Fatal (err )
119+ }
120+ }
121+
122+ err = c1 .Close (websocket .StatusNormalClosure , "" )
123+ if err != nil {
124+ t .Fatalf ("unexpected error: %v" , err )
125+ }
126+ })
127+
128+ t .Run ("badPing" , func (t * testing.T ) {
129+ t .Parallel ()
130+
131+ c1 , c2 , err := wstest .Pipe (nil , nil )
132+ if err != nil {
133+ t .Fatal (err )
134+ }
135+ defer c1 .Close (websocket .StatusInternalError , "" )
136+ defer c2 .Close (websocket .StatusInternalError , "" )
137+
138+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 5 )
139+ defer cancel ()
140+
141+ c2 .CloseRead (ctx )
142+
143+ err = c1 .Ping (ctx )
144+ if ! cmp .ErrorContains (err , "failed to wait for pong" ) {
145+ t .Fatalf ("unexpected error: %v" , err )
146+ }
147+ })
148+
149+ t .Run ("concurrentWrite" , func (t * testing.T ) {
150+ t .Parallel ()
151+
152+ c1 , c2 , err := wstest .Pipe (nil , nil )
153+ if err != nil {
154+ t .Fatal (err )
155+ }
156+ defer c2 .Close (websocket .StatusInternalError , "" )
157+ defer c1 .Close (websocket .StatusInternalError , "" )
158+
159+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 10 )
160+ defer cancel ()
161+
162+ discardLoopErr := xsync .Go (func () error {
163+ for {
164+ _ , _ , err := c2 .Read (ctx )
165+ if websocket .CloseStatus (err ) == websocket .StatusNormalClosure {
166+ return nil
167+ }
168+ if err != nil {
169+ return err
170+ }
171+ }
172+ })
173+ defer func () {
174+ err := <- discardLoopErr
175+ if err != nil {
176+ t .Errorf ("discard loop error: %v" , err )
177+ }
178+ }()
179+ defer cancel ()
180+
181+ msg := xrand .Bytes (xrand .Int (9999 ))
182+ const count = 100
183+ errs := make (chan error , count )
184+
185+ for i := 0 ; i < count ; i ++ {
186+ go func () {
187+ errs <- c1 .Write (ctx , websocket .MessageBinary , msg )
188+ }()
189+ }
190+
191+ for i := 0 ; i < count ; i ++ {
192+ err := <- errs
193+ if err != nil {
194+ t .Fatal (err )
195+ }
196+ }
197+
198+ err = c1 .Close (websocket .StatusNormalClosure , "" )
199+ if err != nil {
200+ t .Fatalf ("unexpected error: %v" , err )
201+ }
202+ })
78203}
79204
80205func TestWasm (t * testing.T ) {
0 commit comments