github.com/cloudwego/hertz@v0.9.3/pkg/common/utils/ioutil_test.go (about)

     1  /*
     2   * Copyright 2022 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package utils
    18  
    19  import (
    20  	"bytes"
    21  	"io"
    22  	"testing"
    23  
    24  	"github.com/cloudwego/hertz/pkg/common/test/mock"
    25  
    26  	"github.com/cloudwego/hertz/pkg/common/test/assert"
    27  	"github.com/cloudwego/hertz/pkg/network"
    28  )
    29  
    30  type writeReadTest interface {
    31  	Write(p []byte) (n int, err error)
    32  	Malloc(n int) (buf []byte, err error)
    33  	WriteBinary(b []byte) (n int, err error)
    34  	Flush() error
    35  }
    36  
    37  type readerTest interface {
    38  	ReadFrom(r io.Reader) (n int64, err error)
    39  	Malloc(n int) (buf []byte, err error)
    40  	WriteBinary(b []byte) (n int, err error)
    41  	Flush() error
    42  }
    43  
    44  type testWriter struct {
    45  	w io.Writer
    46  }
    47  
    48  func (t testWriter) Write(p []byte) (n int, err error) {
    49  	return
    50  }
    51  
    52  func (t testWriter) Malloc(n int) (buf []byte, err error) {
    53  	return
    54  }
    55  
    56  func (t testWriter) WriteBinary(b []byte) (n int, err error) {
    57  	return
    58  }
    59  
    60  func (t testWriter) Flush() error {
    61  	return nil
    62  }
    63  
    64  type testReader struct {
    65  	r io.ReaderFrom
    66  }
    67  
    68  func (t testReader) ReadFrom(r io.Reader) (n int64, err error) {
    69  	return
    70  }
    71  
    72  func (t testReader) Malloc(n int) (buf []byte, err error) {
    73  	return
    74  }
    75  
    76  func (t testReader) WriteBinary(b []byte) (n int, err error) {
    77  	return
    78  }
    79  
    80  func (t testReader) Flush() error {
    81  	return nil
    82  }
    83  
    84  func newTestWriter(w io.Writer) writeReadTest {
    85  	return &testWriter{
    86  		w: w,
    87  	}
    88  }
    89  
    90  func newTestReaderForm(r io.ReaderFrom) readerTest {
    91  	return &testReader{
    92  		r: r,
    93  	}
    94  }
    95  
    96  func TestIoutilCopyBuffer(t *testing.T) {
    97  	var writeBuffer bytes.Buffer
    98  	str := string("hertz is very good!!!")
    99  	src := bytes.NewBufferString(str)
   100  	dst := network.NewWriter(&writeBuffer)
   101  	var buf []byte
   102  	// src.Len() will change, when use src.read(p []byte)
   103  	srcLen := int64(src.Len())
   104  	written, err := CopyBuffer(dst, src, buf)
   105  
   106  	assert.DeepEqual(t, written, srcLen)
   107  	assert.DeepEqual(t, err, nil)
   108  	assert.DeepEqual(t, []byte(str), writeBuffer.Bytes())
   109  
   110  	// Test when no data is readable
   111  	writeBuffer.Reset()
   112  	emptySrc := bytes.NewBufferString("")
   113  	written, err = CopyBuffer(dst, emptySrc, buf)
   114  	assert.DeepEqual(t, written, int64(0))
   115  	assert.Nil(t, err)
   116  	assert.DeepEqual(t, []byte(""), writeBuffer.Bytes())
   117  
   118  	// Test a LimitedReader
   119  	writeBuffer.Reset()
   120  	limit := int64(5)
   121  	limitedSrc := io.LimitedReader{R: bytes.NewBufferString(str), N: limit}
   122  	written, err = CopyBuffer(dst, &limitedSrc, buf)
   123  	assert.DeepEqual(t, written, limit)
   124  	assert.Nil(t, err)
   125  	assert.DeepEqual(t, []byte(str[:limit]), writeBuffer.Bytes())
   126  }
   127  
   128  func TestIoutilCopyBufferWithIoWriter(t *testing.T) {
   129  	var writeBuffer bytes.Buffer
   130  	str := "hertz is very good!!!"
   131  	var buf []byte
   132  	src := bytes.NewBuffer([]byte(str))
   133  	ioWriter := newTestWriter(&writeBuffer)
   134  	// to show example about -----w, ok := dst.(io.Writer)-----
   135  	_, ok := ioWriter.(io.Writer)
   136  	assert.DeepEqual(t, true, ok)
   137  	written, err := CopyBuffer(ioWriter, src, buf)
   138  	assert.DeepEqual(t, written, int64(0))
   139  	assert.NotNil(t, err)
   140  	assert.DeepEqual(t, []byte(nil), writeBuffer.Bytes())
   141  }
   142  
   143  func TestIoutilCopyBufferWithIoReaderFrom(t *testing.T) {
   144  	var writeBuffer bytes.Buffer
   145  	str := "hertz is very good!!!"
   146  	var buf []byte
   147  	src := bytes.NewBufferString(str)
   148  	ioReaderFrom := newTestReaderForm(&writeBuffer)
   149  	// to show example about -----rf, ok := dst.(io.ReaderFrom)-----
   150  	_, ok := ioReaderFrom.(io.Writer)
   151  	assert.DeepEqual(t, false, ok)
   152  	_, ok = ioReaderFrom.(io.ReaderFrom)
   153  	assert.DeepEqual(t, true, ok)
   154  	written, err := CopyBuffer(ioReaderFrom, src, buf)
   155  	assert.DeepEqual(t, written, int64(0))
   156  	assert.Nil(t, err)
   157  	assert.DeepEqual(t, []byte(nil), writeBuffer.Bytes())
   158  }
   159  
   160  func TestIoutilCopyBufferWithPanic(t *testing.T) {
   161  	var writeBuffer bytes.Buffer
   162  	str := "hertz is very good!!!"
   163  	var buf []byte
   164  	defer func() {
   165  		if r := recover(); r != nil {
   166  			assert.DeepEqual(t, "empty buffer in io.CopyBuffer", r)
   167  		}
   168  	}()
   169  	src := bytes.NewBufferString(str)
   170  	dst := network.NewWriter(&writeBuffer)
   171  	buf = make([]byte, 0)
   172  	_, _ = CopyBuffer(dst, src, buf)
   173  }
   174  
   175  func TestIoutilCopyBufferWithNilBuffer(t *testing.T) {
   176  	var writeBuffer bytes.Buffer
   177  	str := string("hertz is very good!!!")
   178  	src := bytes.NewBufferString(str)
   179  	dst := network.NewWriter(&writeBuffer)
   180  	// src.Len() will change, when use src.read(p []byte)
   181  	srcLen := int64(src.Len())
   182  	written, err := CopyBuffer(dst, src, nil)
   183  
   184  	assert.DeepEqual(t, written, srcLen)
   185  	assert.Nil(t, err)
   186  	assert.DeepEqual(t, []byte(str), writeBuffer.Bytes())
   187  }
   188  
   189  func TestIoutilCopyBufferWithNilBufferAndIoLimitedReader(t *testing.T) {
   190  	var writeBuffer bytes.Buffer
   191  	str := "hertz is very good!!!"
   192  	src := bytes.NewBufferString(str)
   193  	reader := mock.NewLimitReader(src)
   194  	dst := network.NewWriter(&writeBuffer)
   195  	srcLen := int64(src.Len())
   196  	written, err := CopyBuffer(dst, &reader, nil)
   197  
   198  	assert.DeepEqual(t, written, srcLen)
   199  	assert.Nil(t, err)
   200  	assert.DeepEqual(t, []byte(str), writeBuffer.Bytes())
   201  
   202  	// test l.N < 1
   203  	writeBuffer.Reset()
   204  	str = ""
   205  	src = bytes.NewBufferString(str)
   206  	reader = mock.NewLimitReader(src)
   207  	dst = network.NewWriter(&writeBuffer)
   208  	srcLen = int64(src.Len())
   209  	written, err = CopyBuffer(dst, &reader, nil)
   210  
   211  	assert.DeepEqual(t, written, srcLen)
   212  	assert.Nil(t, err)
   213  	assert.DeepEqual(t, []byte(str), writeBuffer.Bytes())
   214  }
   215  
   216  func TestIoutilCopyZeroAlloc(t *testing.T) {
   217  	var writeBuffer bytes.Buffer
   218  	str := "hertz is very good!!!"
   219  	src := bytes.NewBufferString(str)
   220  	dst := network.NewWriter(&writeBuffer)
   221  	srcLen := int64(src.Len())
   222  	written, err := CopyZeroAlloc(dst, src)
   223  
   224  	assert.DeepEqual(t, written, srcLen)
   225  	assert.DeepEqual(t, err, nil)
   226  	assert.DeepEqual(t, []byte(str), writeBuffer.Bytes())
   227  
   228  	// Test when no data is readable
   229  	writeBuffer.Reset()
   230  	emptySrc := bytes.NewBufferString("")
   231  	written, err = CopyZeroAlloc(dst, emptySrc)
   232  	assert.DeepEqual(t, written, int64(0))
   233  	assert.Nil(t, err)
   234  	assert.DeepEqual(t, []byte(""), writeBuffer.Bytes())
   235  }
   236  
   237  func TestIoutilCopyBufferWithEmptyBuffer(t *testing.T) {
   238  	var writeBuffer bytes.Buffer
   239  	str := "hertz is very good!!!"
   240  	src := bytes.NewBufferString(str)
   241  	dst := network.NewWriter(&writeBuffer)
   242  	// Use a non-empty buffer of length 0
   243  	emptyBuf := make([]byte, 0)
   244  	func() {
   245  		defer func() {
   246  			if r := recover(); r != nil {
   247  				assert.DeepEqual(t, "empty buffer in io.CopyBuffer", r)
   248  			}
   249  		}()
   250  
   251  		written, err := CopyBuffer(dst, src, emptyBuf)
   252  		assert.Nil(t, err)
   253  		assert.DeepEqual(t, written, int64(len(str)))
   254  		assert.DeepEqual(t, []byte(str), writeBuffer.Bytes())
   255  	}()
   256  }
   257  
   258  func TestIoutilCopyBufferWithLimitedReader(t *testing.T) {
   259  	var writeBuffer bytes.Buffer
   260  	str := "hertz is very good!!!"
   261  	src := bytes.NewBufferString(str)
   262  	limit := int64(5)
   263  	limitedSrc := io.LimitedReader{R: src, N: limit}
   264  	dst := network.NewWriter(&writeBuffer)
   265  	var buf []byte
   266  
   267  	// Test LimitedReader status
   268  	written, err := CopyBuffer(dst, &limitedSrc, buf)
   269  	assert.Nil(t, err)
   270  	assert.DeepEqual(t, written, limit)
   271  	assert.DeepEqual(t, []byte(str[:limit]), writeBuffer.Bytes())
   272  }