github.com/pion/webrtc/v3@v3.2.24/internal/mux/mux_test.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package mux 5 6 import ( 7 "io" 8 "net" 9 "testing" 10 "time" 11 12 "github.com/pion/logging" 13 "github.com/pion/transport/v2/packetio" 14 "github.com/pion/transport/v2/test" 15 "github.com/stretchr/testify/require" 16 ) 17 18 const testPipeBufferSize = 8192 19 20 func TestNoEndpoints(t *testing.T) { 21 // In memory pipe 22 ca, cb := net.Pipe() 23 require.NoError(t, cb.Close()) 24 25 m := NewMux(Config{ 26 Conn: ca, 27 BufferSize: testPipeBufferSize, 28 LoggerFactory: logging.NewDefaultLoggerFactory(), 29 }) 30 require.NoError(t, m.dispatch(make([]byte, 1))) 31 require.NoError(t, m.Close()) 32 require.NoError(t, ca.Close()) 33 } 34 35 type muxErrorConnReadResult struct { 36 err error 37 data []byte 38 } 39 40 // muxErrorConn 41 type muxErrorConn struct { 42 net.Conn 43 readResults []muxErrorConnReadResult 44 } 45 46 func (m *muxErrorConn) Read(b []byte) (n int, err error) { 47 err = m.readResults[0].err 48 copy(b, m.readResults[0].data) 49 n = len(m.readResults[0].data) 50 51 m.readResults = m.readResults[1:] 52 return 53 } 54 55 /* 56 Don't end the mux readLoop for packetio.ErrTimeout or io.ErrShortBuffer, assert the following 57 58 - io.ErrShortBuffer and packetio.ErrTimeout don't end the read loop 59 60 - io.EOF ends the loop 61 62 pion/webrtc#1720 63 */ 64 func TestNonFatalRead(t *testing.T) { 65 // Limit runtime in case of deadlocks 66 lim := test.TimeOut(time.Second * 20) 67 defer lim.Stop() 68 69 expectedData := []byte("expectedData") 70 71 // In memory pipe 72 ca, cb := net.Pipe() 73 require.NoError(t, cb.Close()) 74 75 conn := &muxErrorConn{ca, []muxErrorConnReadResult{ 76 // Non-fatal timeout error 77 {packetio.ErrTimeout, nil}, 78 {nil, expectedData}, 79 {io.ErrShortBuffer, nil}, 80 {nil, expectedData}, 81 {io.EOF, nil}, 82 }} 83 84 m := NewMux(Config{ 85 Conn: conn, 86 BufferSize: testPipeBufferSize, 87 LoggerFactory: logging.NewDefaultLoggerFactory(), 88 }) 89 90 e := m.NewEndpoint(MatchAll) 91 92 buff := make([]byte, testPipeBufferSize) 93 n, err := e.Read(buff) 94 require.NoError(t, err) 95 require.Equal(t, buff[:n], expectedData) 96 97 n, err = e.Read(buff) 98 require.NoError(t, err) 99 require.Equal(t, buff[:n], expectedData) 100 101 <-m.closedCh 102 require.NoError(t, m.Close()) 103 require.NoError(t, ca.Close()) 104 } 105 106 // If a endpoint returns packetio.ErrFull it is a non-fatal error and shouldn't cause 107 // the mux to be destroyed 108 // pion/webrtc#2180 109 func TestNonFatalDispatch(t *testing.T) { 110 in, out := net.Pipe() 111 112 m := NewMux(Config{ 113 Conn: out, 114 LoggerFactory: logging.NewDefaultLoggerFactory(), 115 BufferSize: 1500, 116 }) 117 118 e := m.NewEndpoint(MatchSRTP) 119 e.buffer.SetLimitSize(1) 120 121 for i := 0; i <= 25; i++ { 122 srtpPacket := []byte{128, 1, 2, 3, 4} 123 _, err := in.Write(srtpPacket) 124 require.NoError(t, err) 125 } 126 127 require.NoError(t, m.Close()) 128 require.NoError(t, in.Close()) 129 require.NoError(t, out.Close()) 130 } 131 132 func BenchmarkDispatch(b *testing.B) { 133 m := &Mux{ 134 endpoints: make(map[*Endpoint]MatchFunc), 135 log: logging.NewDefaultLoggerFactory().NewLogger("mux"), 136 } 137 138 e := m.NewEndpoint(MatchSRTP) 139 m.NewEndpoint(MatchSRTCP) 140 141 buf := []byte{128, 1, 2, 3, 4} 142 buf2 := make([]byte, 1200) 143 144 b.StartTimer() 145 146 for i := 0; i < b.N; i++ { 147 err := m.dispatch(buf) 148 if err != nil { 149 b.Errorf("dispatch: %v", err) 150 } 151 _, err = e.buffer.Read(buf2) 152 if err != nil { 153 b.Errorf("read: %v", err) 154 } 155 } 156 }