@@ -169,6 +169,67 @@ func TestFallbackClient_SPDYSecondarySucceeds(t *testing.T) {
169
169
}
170
170
}
171
171
172
+ func TestFallbackClient_PrimaryAndSecondaryFail (t * testing.T ) {
173
+ // Create fake WebSocket server. Copy received STDIN data back onto STDOUT stream.
174
+ websocketServer := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
175
+ conns , err := webSocketServerStreams (req , w , streamOptionsFromRequest (req ))
176
+ if err != nil {
177
+ w .WriteHeader (http .StatusForbidden )
178
+ return
179
+ }
180
+ defer conns .conn .Close ()
181
+ // Loopback the STDIN stream onto the STDOUT stream.
182
+ _ , err = io .Copy (conns .stdoutStream , conns .stdinStream )
183
+ require .NoError (t , err )
184
+ }))
185
+ defer websocketServer .Close ()
186
+
187
+ // Now create the fallback client (executor), and point it to the "websocketServer".
188
+ // Must add STDIN and STDOUT query params for the client request.
189
+ websocketServer .URL = websocketServer .URL + "?" + "stdin=true" + "&" + "stdout=true"
190
+ websocketLocation , err := url .Parse (websocketServer .URL )
191
+ require .NoError (t , err )
192
+ websocketExecutor , err := NewWebSocketExecutor (& rest.Config {Host : websocketLocation .Host }, "GET" , websocketServer .URL )
193
+ require .NoError (t , err )
194
+ spdyExecutor , err := NewSPDYExecutor (& rest.Config {Host : websocketLocation .Host }, "POST" , websocketLocation )
195
+ require .NoError (t , err )
196
+ // Always fallback to spdyExecutor, but spdyExecutor fails against websocket server.
197
+ exec , err := NewFallbackExecutor (websocketExecutor , spdyExecutor , func (error ) bool { return true })
198
+ require .NoError (t , err )
199
+ // Update the websocket executor to request remote command v4, which is unsupported.
200
+ fallbackExec , ok := exec .(* FallbackExecutor )
201
+ assert .True (t , ok , "error casting executor as FallbackExecutor" )
202
+ websocketExec , ok := fallbackExec .primary .(* wsStreamExecutor )
203
+ assert .True (t , ok , "error casting executor as websocket executor" )
204
+ // Set the attempted subprotocol version to V4; websocket server only accepts V5.
205
+ websocketExec .protocols = []string {remotecommand .StreamProtocolV4Name }
206
+
207
+ // Generate random data, and set it up to stream on STDIN. The data will be
208
+ // returned on the STDOUT buffer.
209
+ randomSize := 1024 * 1024
210
+ randomData := make ([]byte , randomSize )
211
+ if _ , err := rand .Read (randomData ); err != nil {
212
+ t .Errorf ("unexpected error reading random data: %v" , err )
213
+ }
214
+ var stdout bytes.Buffer
215
+ options := & StreamOptions {
216
+ Stdin : bytes .NewReader (randomData ),
217
+ Stdout : & stdout ,
218
+ }
219
+ errorChan := make (chan error )
220
+ go func () {
221
+ errorChan <- exec .StreamWithContext (context .Background (), * options )
222
+ }()
223
+
224
+ select {
225
+ case <- time .After (wait .ForeverTestTimeout ):
226
+ t .Fatalf ("expect stream to be closed after connection is closed." )
227
+ case err := <- errorChan :
228
+ // Ensure secondary executor returned an error.
229
+ require .Error (t , err )
230
+ }
231
+ }
232
+
172
233
// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
173
234
//
174
235
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
@@ -340,64 +401,3 @@ func TestFallbackClient_WebSocketHTTPSProxyCausesSPDYFallback(t *testing.T) {
340
401
t .Errorf ("expected %d proxy call, got %d" , e , a )
341
402
}
342
403
}
343
-
344
- func TestFallbackClient_PrimaryAndSecondaryFail (t * testing.T ) {
345
- // Create fake WebSocket server. Copy received STDIN data back onto STDOUT stream.
346
- websocketServer := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
347
- conns , err := webSocketServerStreams (req , w , streamOptionsFromRequest (req ))
348
- if err != nil {
349
- w .WriteHeader (http .StatusForbidden )
350
- return
351
- }
352
- defer conns .conn .Close ()
353
- // Loopback the STDIN stream onto the STDOUT stream.
354
- _ , err = io .Copy (conns .stdoutStream , conns .stdinStream )
355
- require .NoError (t , err )
356
- }))
357
- defer websocketServer .Close ()
358
-
359
- // Now create the fallback client (executor), and point it to the "websocketServer".
360
- // Must add STDIN and STDOUT query params for the client request.
361
- websocketServer .URL = websocketServer .URL + "?" + "stdin=true" + "&" + "stdout=true"
362
- websocketLocation , err := url .Parse (websocketServer .URL )
363
- require .NoError (t , err )
364
- websocketExecutor , err := NewWebSocketExecutor (& rest.Config {Host : websocketLocation .Host }, "GET" , websocketServer .URL )
365
- require .NoError (t , err )
366
- spdyExecutor , err := NewSPDYExecutor (& rest.Config {Host : websocketLocation .Host }, "POST" , websocketLocation )
367
- require .NoError (t , err )
368
- // Always fallback to spdyExecutor, but spdyExecutor fails against websocket server.
369
- exec , err := NewFallbackExecutor (websocketExecutor , spdyExecutor , func (error ) bool { return true })
370
- require .NoError (t , err )
371
- // Update the websocket executor to request remote command v4, which is unsupported.
372
- fallbackExec , ok := exec .(* FallbackExecutor )
373
- assert .True (t , ok , "error casting executor as FallbackExecutor" )
374
- websocketExec , ok := fallbackExec .primary .(* wsStreamExecutor )
375
- assert .True (t , ok , "error casting executor as websocket executor" )
376
- // Set the attempted subprotocol version to V4; websocket server only accepts V5.
377
- websocketExec .protocols = []string {remotecommand .StreamProtocolV4Name }
378
-
379
- // Generate random data, and set it up to stream on STDIN. The data will be
380
- // returned on the STDOUT buffer.
381
- randomSize := 1024 * 1024
382
- randomData := make ([]byte , randomSize )
383
- if _ , err := rand .Read (randomData ); err != nil {
384
- t .Errorf ("unexpected error reading random data: %v" , err )
385
- }
386
- var stdout bytes.Buffer
387
- options := & StreamOptions {
388
- Stdin : bytes .NewReader (randomData ),
389
- Stdout : & stdout ,
390
- }
391
- errorChan := make (chan error )
392
- go func () {
393
- errorChan <- exec .StreamWithContext (context .Background (), * options )
394
- }()
395
-
396
- select {
397
- case <- time .After (wait .ForeverTestTimeout ):
398
- t .Fatalf ("expect stream to be closed after connection is closed." )
399
- case err := <- errorChan :
400
- // Ensure secondary executor returned an error.
401
- require .Error (t , err )
402
- }
403
- }
0 commit comments