github.com/ezoic/ws@v1.0.4-0.20220713205711-5c1d69e074c5/wsutil/handler_test.go (about) 1 package wsutil 2 3 import ( 4 "bytes" 5 "runtime" 6 "testing" 7 8 "github.com/ezoic/ws" 9 ) 10 11 func TestControlHandler(t *testing.T) { 12 for _, test := range []struct { 13 name string 14 state ws.State 15 in ws.Frame 16 out ws.Frame 17 noOut bool 18 err error 19 }{ 20 { 21 name: "ping", 22 in: ws.NewPingFrame(nil), 23 out: ws.NewPongFrame(nil), 24 }, 25 { 26 name: "ping", 27 in: ws.NewPingFrame([]byte("catch the ball")), 28 out: ws.NewPongFrame([]byte("catch the ball")), 29 }, 30 { 31 name: "ping", 32 state: ws.StateServerSide, 33 in: ws.MaskFrame(ws.NewPingFrame([]byte("catch the ball"))), 34 out: ws.NewPongFrame([]byte("catch the ball")), 35 }, 36 { 37 name: "pong", 38 in: ws.NewPongFrame(nil), 39 noOut: true, 40 }, 41 { 42 name: "pong", 43 in: ws.NewPongFrame([]byte("catched")), 44 noOut: true, 45 }, 46 { 47 name: "close", 48 in: ws.NewCloseFrame(nil), 49 out: ws.NewCloseFrame(nil), 50 err: ClosedError{ 51 Code: ws.StatusNoStatusRcvd, 52 }, 53 }, 54 { 55 name: "close", 56 in: ws.NewCloseFrame(ws.NewCloseFrameBody( 57 ws.StatusGoingAway, "goodbye!", 58 )), 59 out: ws.NewCloseFrame(ws.NewCloseFrameBody( 60 ws.StatusGoingAway, "", 61 )), 62 err: ClosedError{ 63 Code: ws.StatusGoingAway, 64 Reason: "goodbye!", 65 }, 66 }, 67 { 68 name: "close", 69 state: ws.StateServerSide, 70 in: ws.MaskFrame(ws.NewCloseFrame(ws.NewCloseFrameBody( 71 ws.StatusGoingAway, "goodbye!", 72 ))), 73 out: ws.NewCloseFrame(ws.NewCloseFrameBody( 74 ws.StatusGoingAway, "", 75 )), 76 err: ClosedError{ 77 Code: ws.StatusGoingAway, 78 Reason: "goodbye!", 79 }, 80 }, 81 { 82 name: "close", 83 in: ws.NewCloseFrame(ws.NewCloseFrameBody( 84 ws.StatusNormalClosure, string([]byte{0, 200}), 85 )), 86 out: ws.NewCloseFrame(ws.NewCloseFrameBody( 87 ws.StatusProtocolError, ws.ErrProtocolInvalidUTF8.Error(), 88 )), 89 err: ws.ErrProtocolInvalidUTF8, 90 }, 91 } { 92 t.Run(test.name, func(t *testing.T) { 93 defer func() { 94 if err := recover(); err != nil { 95 stack := make([]byte, 4096) 96 n := runtime.Stack(stack, true) 97 t.Fatalf( 98 "panic recovered: %v\n%s", 99 err, stack[:n], 100 ) 101 } 102 }() 103 var ( 104 out = bytes.NewBuffer(nil) 105 in = bytes.NewReader(test.in.Payload) 106 ) 107 c := ControlHandler{ 108 Src: in, 109 Dst: out, 110 State: test.state, 111 } 112 113 err := c.Handle(test.in.Header) 114 if err != test.err { 115 t.Errorf("unexpected error: %v; want %v", err, test.err) 116 } 117 118 if in.Len() != 0 { 119 t.Errorf("handler did not drained the input") 120 } 121 122 act := out.Bytes() 123 switch { 124 case len(act) == 0 && test.noOut: 125 return 126 case len(act) == 0 && !test.noOut: 127 t.Errorf("unexpected silence") 128 case len(act) > 0 && test.noOut: 129 t.Errorf("unexpected sent frame") 130 default: 131 exp := ws.MustCompileFrame(test.out) 132 if !bytes.Equal(act, exp) { 133 fa := ws.MustReadFrame(bytes.NewReader(act)) 134 fe := ws.MustReadFrame(bytes.NewReader(exp)) 135 t.Errorf( 136 "unexpected sent frame:\n\tact: %+v\n\texp: %+v\nbytes:\n\tact: %v\n\texp: %v", 137 fa, fe, act, exp, 138 ) 139 } 140 } 141 }) 142 } 143 }