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 }