github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/zerocopy/stream_test.go (about) 1 package zerocopy 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "errors" 7 "fmt" 8 "io" 9 "testing" 10 ) 11 12 var errExpectDirect = errors.New("buffered relay method is used") 13 14 type testReader struct { 15 r *bytes.Reader 16 } 17 18 func newTestReader(t *testing.T) (*testReader, []byte) { 19 b := make([]byte, 1024) 20 _, err := rand.Read(b) 21 if err != nil { 22 t.Fatal(err) 23 } 24 return &testReader{r: bytes.NewReader(b)}, append([]byte{}, b...) 25 } 26 27 func (r *testReader) ReaderInfo() ReaderInfo { 28 return ReaderInfo{} 29 } 30 31 func (r *testReader) ReadZeroCopy(b []byte, payloadBufStart, payloadBufLen int) (payloadLen int, err error) { 32 return r.r.Read(b[payloadBufStart : payloadBufStart+payloadBufLen]) 33 } 34 35 type testBigReader struct { 36 *testReader 37 } 38 39 func newTestBigReader(t *testing.T) (*testBigReader, []byte) { 40 r, b := newTestReader(t) 41 return &testBigReader{r}, b 42 } 43 44 func (r *testBigReader) ReaderInfo() ReaderInfo { 45 return ReaderInfo{MinPayloadBufferSizePerRead: 64} 46 } 47 48 func (r *testBigReader) ReadZeroCopy(b []byte, payloadBufStart, payloadBufLen int) (payloadLen int, err error) { 49 if len(b) < 64 { 50 return 0, fmt.Errorf("read buffer too small: %d", len(b)) 51 } 52 return r.testReader.ReadZeroCopy(b, payloadBufStart, payloadBufLen) 53 } 54 55 type testDirectReader struct { 56 *testReader 57 } 58 59 func newTestDirectReadCloser(t *testing.T) (*testDirectReader, []byte) { 60 r, b := newTestReader(t) 61 return &testDirectReader{r}, b 62 } 63 64 func (r *testDirectReader) DirectReader() io.Reader { 65 return r.r 66 } 67 68 func (r *testDirectReader) ReadZeroCopy(b []byte, payloadBufStart, payloadBufLen int) (payloadLen int, err error) { 69 return 0, errExpectDirect 70 } 71 72 type testWriter struct { 73 w bytes.Buffer 74 } 75 76 func (w *testWriter) WriterInfo() WriterInfo { 77 return WriterInfo{} 78 } 79 80 func (w *testWriter) WriteZeroCopy(b []byte, payloadStart, payloadLen int) (payloadWritten int, err error) { 81 return w.w.Write(b[payloadStart : payloadStart+payloadLen]) 82 } 83 84 func (w *testWriter) Bytes() []byte { 85 return w.w.Bytes() 86 } 87 88 type testSmallWriter struct { 89 testWriter 90 } 91 92 func (w *testSmallWriter) WriterInfo() WriterInfo { 93 return WriterInfo{MaxPayloadSizePerWrite: 32} 94 } 95 96 func (w *testSmallWriter) WriteZeroCopy(b []byte, payloadStart, payloadLen int) (payloadWritten int, err error) { 97 if len(b) > 32 { 98 return 0, fmt.Errorf("write buffer too big: %d", len(b)) 99 } 100 return w.testWriter.WriteZeroCopy(b, payloadStart, payloadLen) 101 } 102 103 type testDirectWriter struct { 104 testWriter 105 } 106 107 func (w *testDirectWriter) DirectWriter() io.Writer { 108 return &w.w 109 } 110 111 func (w *testDirectWriter) WriteZeroCopy(b []byte, payloadStart, payloadLen int) (payloadWritten int, err error) { 112 return 0, errExpectDirect 113 } 114 115 type getBytes interface { 116 Bytes() []byte 117 } 118 119 type testReadWriter interface { 120 ReadWriter 121 getBytes 122 } 123 124 type testWriterBytes interface { 125 Writer 126 getBytes 127 } 128 129 type testReadWriterImpl struct { 130 Reader 131 testWriterBytes 132 } 133 134 func (rw *testReadWriterImpl) FrontHeadroom() int { 135 return 0 136 } 137 138 func (rw *testReadWriterImpl) RearHeadroom() int { 139 return 0 140 } 141 142 func (rw *testReadWriterImpl) CloseRead() error { 143 return nil 144 } 145 146 func (rw *testReadWriterImpl) CloseWrite() error { 147 return nil 148 } 149 150 func (rw *testReadWriterImpl) Close() error { 151 return nil 152 } 153 154 func newTestTypicalReadWriter(t *testing.T) (*testReadWriterImpl, []byte) { 155 r, b := newTestReader(t) 156 return &testReadWriterImpl{ 157 Reader: r, 158 testWriterBytes: &testWriter{}, 159 }, b 160 } 161 162 func newTestBigReaderSmallWriter(t *testing.T) (*testReadWriterImpl, []byte) { 163 r, b := newTestBigReader(t) 164 return &testReadWriterImpl{ 165 Reader: r, 166 testWriterBytes: &testSmallWriter{}, 167 }, b 168 } 169 170 type testDirectReadWriter struct { 171 *testDirectReader 172 *testDirectWriter 173 } 174 175 func (rw *testDirectReadWriter) FrontHeadroom() int { 176 return 0 177 } 178 179 func (rw *testDirectReadWriter) RearHeadroom() int { 180 return 0 181 } 182 183 func (rw *testDirectReadWriter) CloseRead() error { 184 return nil 185 } 186 187 func (rw *testDirectReadWriter) CloseWrite() error { 188 return nil 189 } 190 191 func (rw *testDirectReadWriter) Close() error { 192 return nil 193 } 194 195 func (rw *testDirectReadWriter) Bytes() []byte { 196 return rw.w.Bytes() 197 } 198 199 func newTestDirectReadWriter(t *testing.T) (*testDirectReadWriter, []byte) { 200 r, b := newTestDirectReadCloser(t) 201 return &testDirectReadWriter{ 202 testDirectReader: r, 203 testDirectWriter: &testDirectWriter{}, 204 }, b 205 } 206 207 func testTwoWayRelay(t *testing.T, l, r testReadWriter, ldata, rdata []byte) { 208 nl2r, nr2l, err := TwoWayRelay(l, r) 209 if err != nil { 210 t.Error(err) 211 } 212 if nl2r != 1024 { 213 t.Errorf("Expected nl2r 1024, got %d", nl2r) 214 } 215 if nr2l != 1024 { 216 t.Errorf("Expected nr2l 1024, got %d", nr2l) 217 } 218 219 ldataAfter := l.Bytes() 220 rdataAfter := r.Bytes() 221 222 if !bytes.Equal(ldata, rdataAfter) { 223 t.Error("l2r copy changed data!") 224 } 225 if !bytes.Equal(rdata, ldataAfter) { 226 t.Error("r2l copy changed data!") 227 } 228 } 229 230 func TestTwoWayRelayBuffered(t *testing.T) { 231 l, ldata := newTestTypicalReadWriter(t) 232 r, rdata := newTestTypicalReadWriter(t) 233 testTwoWayRelay(t, l, r, ldata, rdata) 234 } 235 236 func TestTwoWayRelayFallback(t *testing.T) { 237 l, ldata := newTestBigReaderSmallWriter(t) 238 r, rdata := newTestBigReaderSmallWriter(t) 239 testTwoWayRelay(t, l, r, ldata, rdata) 240 } 241 242 func TestTwoWayRelayDirect(t *testing.T) { 243 l, ldata := newTestDirectReadWriter(t) 244 r, rdata := newTestDirectReadWriter(t) 245 testTwoWayRelay(t, l, r, ldata, rdata) 246 }