go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/iotools/chainreader_test.go (about)

     1  // Copyright 2015 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package iotools
    16  
    17  import (
    18  	"bytes"
    19  	"errors"
    20  	"io"
    21  	"testing"
    22  
    23  	. "github.com/smartystreets/goconvey/convey"
    24  )
    25  
    26  type infiniteReader struct{}
    27  
    28  func (r infiniteReader) Read(b []byte) (int, error) {
    29  	for idx := 0; idx < len(b); idx++ {
    30  		b[idx] = 0x55
    31  	}
    32  	return len(b), nil
    33  }
    34  
    35  type errorReader struct {
    36  	error
    37  }
    38  
    39  func (e *errorReader) Read([]byte) (int, error) {
    40  	return 0, e.error
    41  }
    42  
    43  func TestChainReader(t *testing.T) {
    44  	Convey(`An empty ChainReader`, t, func() {
    45  		cr := ChainReader{}
    46  
    47  		Convey(`Should successfully read into a zero-byte array.`, func() {
    48  			d := []byte{}
    49  			count, err := cr.Read(d)
    50  			So(count, ShouldEqual, 0)
    51  			So(err, ShouldBeNil)
    52  		})
    53  
    54  		Convey(`Should fail with io.EOF during ReadByte.`, func() {
    55  			b, err := cr.ReadByte()
    56  			So(b, ShouldEqual, 0)
    57  			So(err, ShouldEqual, io.EOF)
    58  		})
    59  
    60  		Convey(`Should have zero remaining bytes.`, func() {
    61  			So(cr.Remaining(), ShouldEqual, 0)
    62  		})
    63  	})
    64  
    65  	Convey(`A ChainReader with {{0x00, 0x01}, nil, nil, {0x02}, nil}`, t, func() {
    66  		cr := ChainReader{bytes.NewReader([]byte{0x00, 0x01}), nil, nil, bytes.NewReader([]byte{0x02}), nil}
    67  
    68  		Convey(`The ChainReader should have a Remaining count of 3.`, func() {
    69  			So(cr.Remaining(), ShouldEqual, 3)
    70  		})
    71  
    72  		Convey(`The ChainReader should read: []byte{0x00, 0x01, 0x02} for buffer size 3.`, func() {
    73  			data := make([]byte, 3)
    74  			count, err := cr.Read(data)
    75  			So(count, ShouldEqual, 3)
    76  			So(err, ShouldBeNil)
    77  			So(data, ShouldResemble, []byte{0x00, 0x01, 0x02})
    78  
    79  			So(cr.Remaining(), ShouldEqual, 0)
    80  		})
    81  
    82  		Convey(`The ChainReader should read: []byte{0x00, 0x01} for buffer size 2.`, func() {
    83  			data := make([]byte, 2)
    84  			count, err := cr.Read(data)
    85  			So(count, ShouldEqual, 2)
    86  			So(err, ShouldBeNil)
    87  			So(data, ShouldResemble, []byte{0x00, 0x01})
    88  
    89  			So(cr.Remaining(), ShouldEqual, 1)
    90  		})
    91  
    92  		Convey(`The ChainReader should read bytes: 0x00, 0x01, 0x02, EOF.`, func() {
    93  			b, err := cr.ReadByte()
    94  			So(b, ShouldEqual, 0x00)
    95  			So(err, ShouldBeNil)
    96  
    97  			b, err = cr.ReadByte()
    98  			So(b, ShouldEqual, 0x01)
    99  			So(err, ShouldBeNil)
   100  
   101  			b, err = cr.ReadByte()
   102  			So(b, ShouldEqual, 0x02)
   103  			So(err, ShouldBeNil)
   104  
   105  			b, err = cr.ReadByte()
   106  			So(b, ShouldEqual, 0x00)
   107  			So(err, ShouldEqual, io.EOF)
   108  
   109  			So(cr.Remaining(), ShouldEqual, 0)
   110  		})
   111  	})
   112  
   113  	Convey(`A ChainReader with an infinite io.Reader`, t, func() {
   114  		cr := ChainReader{&infiniteReader{}}
   115  
   116  		Convey(`Should return an error on RemainingErr()`, func() {
   117  			_, err := cr.RemainingErr()
   118  			So(err, ShouldNotBeNil)
   119  		})
   120  
   121  		Convey(`Should panic on Remaining()`, func() {
   122  			So(func() { cr.Remaining() }, ShouldPanic)
   123  		})
   124  
   125  		Convey(`Should fill a 1024-byte buffer`, func() {
   126  			data := make([]byte, 1024)
   127  			count, err := cr.Read(data)
   128  			So(count, ShouldEqual, 1024)
   129  			So(err, ShouldBeNil)
   130  			So(data, ShouldResemble, bytes.Repeat([]byte{0x55}, 1024))
   131  		})
   132  	})
   133  
   134  	Convey(`A ChainReader with {0x00, 0x01} and an error-returning io.Reader`, t, func() {
   135  		e := errors.New("TEST ERROR")
   136  		cr := ChainReader{bytes.NewReader([]byte{0x00, 0x01}), &errorReader{e}}
   137  
   138  		Convey(`Should fill a 3-byte buffer with the first two bytes and return an error.`, func() {
   139  			data := make([]byte, 3)
   140  			count, err := cr.Read(data)
   141  			So(count, ShouldEqual, 2)
   142  			So(err, ShouldEqual, e)
   143  			So(data[:2], ShouldResemble, []byte{0x00, 0x01})
   144  		})
   145  	})
   146  }