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  }