@@ -332,3 +332,95 @@ third:
332
332
}
333
333
return fmt .Errorf ("unexpected type on 3rd nested level: %T" , nestedErr )
334
334
}
335
+
336
+ // parseCloseError parses nestedErr and reports whether it is a valid
337
+ // error value from Close functions.
338
+ // It returns nil when nestedErr is valid.
339
+ func parseCloseError (nestedErr error ) error {
340
+ if nestedErr == nil {
341
+ return nil
342
+ }
343
+
344
+ switch err := nestedErr .(type ) {
345
+ case * OpError :
346
+ if err := err .isValid (); err != nil {
347
+ return err
348
+ }
349
+ nestedErr = err .Err
350
+ goto second
351
+ }
352
+ return fmt .Errorf ("unexpected type on 1st nested level: %T" , nestedErr )
353
+
354
+ second:
355
+ if isPlatformError (nestedErr ) {
356
+ return nil
357
+ }
358
+ switch err := nestedErr .(type ) {
359
+ case * os.SyscallError :
360
+ nestedErr = err .Err
361
+ goto third
362
+ case * os.PathError : // for Plan 9
363
+ nestedErr = err .Err
364
+ goto third
365
+ }
366
+ switch nestedErr {
367
+ case errClosing :
368
+ return nil
369
+ }
370
+ return fmt .Errorf ("unexpected type on 2nd nested level: %T" , nestedErr )
371
+
372
+ third:
373
+ if isPlatformError (nestedErr ) {
374
+ return nil
375
+ }
376
+ return fmt .Errorf ("unexpected type on 3rd nested level: %T" , nestedErr )
377
+ }
378
+
379
+ func TestCloseError (t * testing.T ) {
380
+ ln , err := newLocalListener ("tcp" )
381
+ if err != nil {
382
+ t .Fatal (err )
383
+ }
384
+ defer ln .Close ()
385
+ c , err := Dial (ln .Addr ().Network (), ln .Addr ().String ())
386
+ if err != nil {
387
+ t .Fatal (err )
388
+ }
389
+ defer c .Close ()
390
+
391
+ for i := 0 ; i < 3 ; i ++ {
392
+ err = c .(* TCPConn ).CloseRead ()
393
+ if perr := parseCloseError (err ); perr != nil {
394
+ t .Errorf ("#%d: %v" , i , perr )
395
+ }
396
+ }
397
+ for i := 0 ; i < 3 ; i ++ {
398
+ err = c .(* TCPConn ).CloseWrite ()
399
+ if perr := parseCloseError (err ); perr != nil {
400
+ t .Errorf ("#%d: %v" , i , perr )
401
+ }
402
+ }
403
+ for i := 0 ; i < 3 ; i ++ {
404
+ err = c .Close ()
405
+ if perr := parseCloseError (err ); perr != nil {
406
+ t .Errorf ("#%d: %v" , i , perr )
407
+ }
408
+ err = ln .Close ()
409
+ if perr := parseCloseError (err ); perr != nil {
410
+ t .Errorf ("#%d: %v" , i , perr )
411
+ }
412
+ }
413
+
414
+ pc , err := ListenPacket ("udp" , "127.0.0.1:0" )
415
+ if err != nil {
416
+ t .Fatal (err )
417
+ }
418
+ defer pc .Close ()
419
+
420
+ for i := 0 ; i < 3 ; i ++ {
421
+ err = pc .Close ()
422
+ if perr := parseCloseError (err ); perr != nil {
423
+ t .Errorf ("#%d: %v" , i , perr )
424
+ }
425
+ }
426
+ }
0 commit comments