go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/data/chunkstream/buffer_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 chunkstream
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	. "github.com/smartystreets/goconvey/convey"
    22  )
    23  
    24  func TestBuffer(t *testing.T) {
    25  	Convey(`An empty Buffer instance`, t, func() {
    26  		b := Buffer{}
    27  
    28  		Convey(`Has a length of zero.`, func() {
    29  			So(b.Len(), ShouldEqual, 0)
    30  		})
    31  
    32  		Convey(`Has a FirstChunk of nil.`, func() {
    33  			So(b.FirstChunk(), ShouldEqual, nil)
    34  		})
    35  
    36  		Convey(`Will panic if more than zero bytes are consumed.`, func() {
    37  			So(func() { b.Consume(1) }, ShouldPanic)
    38  		})
    39  
    40  		Convey(`When Appending an empty chunk`, func() {
    41  			c := tc()
    42  			b.Append(c)
    43  
    44  			Convey(`Has a FirstChunk of nil.`, func() {
    45  				So(b.FirstChunk(), ShouldEqual, nil)
    46  			})
    47  
    48  			Convey(`The Chunk is released.`, func() {
    49  				So(c.released, ShouldBeTrue)
    50  			})
    51  		})
    52  
    53  		for _, chunks := range [][]*testChunk{
    54  			{},
    55  			{tc()},
    56  			{tc(0, 1, 2), tc(), tc(3, 4, 5)},
    57  		} {
    58  			Convey(fmt.Sprintf(`With chunks %v, can append.`, chunks), func() {
    59  				size := int64(0)
    60  				coalesced := []byte(nil)
    61  				for _, c := range chunks {
    62  					b.Append(c)
    63  					coalesced = append(coalesced, c.Bytes()...)
    64  					size += int64(c.Len())
    65  					So(b.Len(), ShouldEqual, size)
    66  				}
    67  				So(b.Bytes(), ShouldResemble, coalesced)
    68  
    69  				Convey(`Can consume chunk-at-a-time.`, func() {
    70  					for i, c := range chunks {
    71  						if c.Len() > 0 {
    72  							So(b.FirstChunk(), ShouldEqual, chunks[i])
    73  						}
    74  						So(b.Len(), ShouldEqual, size)
    75  						b.Consume(int64(c.Len()))
    76  						size -= int64(c.Len())
    77  					}
    78  					So(b.Len(), ShouldEqual, 0)
    79  
    80  					Convey(`All chunks are released.`, func() {
    81  						for _, c := range chunks {
    82  							So(c.released, ShouldBeTrue)
    83  						}
    84  					})
    85  				})
    86  
    87  				Convey(`Can consume byte-at-a-time.`, func() {
    88  					for i := int64(0); i < size; i++ {
    89  						So(b.Len(), ShouldEqual, (size - i))
    90  						So(b.Bytes(), ShouldResemble, coalesced[i:])
    91  						b.Consume(1)
    92  					}
    93  					So(b.Len(), ShouldEqual, 0)
    94  
    95  					Convey(`All chunks are released.`, func() {
    96  						for _, c := range chunks {
    97  							So(c.released, ShouldBeTrue)
    98  						}
    99  					})
   100  				})
   101  
   102  				Convey(`Can consume two bytes at a time.`, func() {
   103  					for i := int64(0); i < size; i += 2 {
   104  						// Final byte(s), make sure we don't over-consume.
   105  						if b.Len() < 2 {
   106  							i = b.Len()
   107  						}
   108  
   109  						So(b.Len(), ShouldEqual, (size - i))
   110  						So(b.Bytes(), ShouldResemble, coalesced[i:])
   111  						b.Consume(2)
   112  					}
   113  					So(b.Len(), ShouldEqual, 0)
   114  
   115  					Convey(`All chunks are released.`, func() {
   116  						for _, c := range chunks {
   117  							So(c.released, ShouldBeTrue)
   118  						}
   119  					})
   120  				})
   121  
   122  				Convey(`Can consume all at once.`, func() {
   123  					b.Consume(size)
   124  					So(b.Len(), ShouldEqual, 0)
   125  
   126  					Convey(`All chunks are released.`, func() {
   127  						for _, c := range chunks {
   128  							So(c.released, ShouldBeTrue)
   129  						}
   130  					})
   131  				})
   132  			})
   133  		}
   134  	})
   135  }