go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/data/chunkstream/view_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 "bytes" 19 "fmt" 20 "io" 21 "testing" 22 23 . "github.com/smartystreets/goconvey/convey" 24 ) 25 26 func TestView(t *testing.T) { 27 Convey(`An empty Buffer with generation 42`, t, func() { 28 b := Buffer{} 29 30 for _, chunks := range [][]*testChunk{ 31 []*testChunk(nil), 32 {tc()}, 33 {tc(0)}, 34 {tc(0, 0, 1)}, 35 {tc(0), tc(0), tc(0)}, 36 {tc(1, 2, 3, 0)}, 37 {tc(1, 2), tc(3, 0, 4, 0), tc(0, 5)}, 38 } { 39 Convey(fmt.Sprintf(`With Chunks %v`, chunks), func() { 40 aggregate := []byte{} 41 size := int64(0) 42 for _, c := range chunks { 43 aggregate = append(aggregate, c.Bytes()...) 44 size += int64(c.Len()) 45 b.Append(c) 46 } 47 48 // This is pretty stupid to do, but for testing it's a nice edge case 49 // to hammer. 50 Convey(`A View with limit 0`, func() { 51 br := b.ViewLimit(0) 52 53 So(br.Remaining(), ShouldEqual, 0) 54 So(br.Consumed(), ShouldEqual, 0) 55 56 Convey(`Read() returns EOF.`, func() { 57 buf := make([]byte, 16) 58 a, err := br.Read(buf) 59 So(err, ShouldEqual, io.EOF) 60 So(a, ShouldEqual, 0) 61 }) 62 63 Convey(`ReadByte() returns EOF.`, func() { 64 _, err := br.ReadByte() 65 So(err, ShouldEqual, io.EOF) 66 }) 67 68 Convey(`Skip() panics.`, func() { 69 So(func() { br.Skip(1) }, ShouldPanic) 70 }) 71 72 Convey(`Index() returns -1.`, func() { 73 So(br.Index([]byte{0}), ShouldEqual, -1) 74 }) 75 }) 76 77 Convey(`An unlimited View`, func() { 78 br := b.View() 79 So(br.Remaining(), ShouldEqual, b.Len()) 80 So(br.Consumed(), ShouldEqual, 0) 81 82 Convey(`Can Read() the full block of data.`, func() { 83 buf := make([]byte, len(aggregate)) 84 amt, err := br.Read(buf) 85 So(amt, ShouldEqual, len(aggregate)) 86 So(err, ShouldEqual, io.EOF) 87 So(buf[:amt], ShouldResemble, aggregate) 88 89 Convey(`Subsequent Read() will return io.EOF.`, func() { 90 amt, err := br.Read(buf) 91 So(amt, ShouldEqual, 0) 92 So(err, ShouldEqual, io.EOF) 93 }) 94 }) 95 96 Convey(`Can Read() the full block of data byte-by-byte.`, func() { 97 buf := make([]byte, 1) 98 for i, d := range aggregate { 99 amt, err := br.Read(buf) 100 if i == len(aggregate)-1 { 101 So(err, ShouldEqual, io.EOF) 102 } else { 103 So(err, ShouldBeNil) 104 } 105 106 So(amt, ShouldEqual, 1) 107 So(buf[0], ShouldEqual, d) 108 } 109 110 Convey(`Subsequent Read() will return io.EOF.`, func() { 111 amt, err := br.Read(buf) 112 So(amt, ShouldEqual, 0) 113 So(err, ShouldEqual, io.EOF) 114 }) 115 }) 116 117 Convey(`Can ReadByte() the full block of data.`, func() { 118 for _, d := range aggregate { 119 b, err := br.ReadByte() 120 So(err, ShouldBeNil) 121 So(b, ShouldEqual, d) 122 } 123 124 Convey(`Subsequent ReadByte() will return io.EOF.`, func() { 125 _, err := br.ReadByte() 126 So(err, ShouldEqual, io.EOF) 127 }) 128 }) 129 130 for _, needle := range [][]byte{ 131 {0}, 132 {0, 0}, 133 {0, 0, 0, 0}, 134 } { 135 expected := bytes.Index(aggregate, needle) 136 Convey(fmt.Sprintf(`Index() of %v returns %v.`, needle, expected), func() { 137 So(br.Index(needle), ShouldEqual, expected) 138 }) 139 } 140 }) 141 }) 142 } 143 144 Convey(`An unlimited View`, func() { 145 br := b.View() 146 147 Convey(`Has chunksRemaining() value of 0.`, func() { 148 So(br.chunkRemaining(), ShouldEqual, 0) 149 }) 150 }) 151 152 Convey(`With chunks [{0x01, 0x02, 0x00}, {0x00, 0x03}, {0x00}, {0x00, 0x00}, {0x04}]`, func() { 153 for _, c := range []Chunk{tc(1, 2, 0), tc(0, 3), tc(0), tc(0, 0), tc(4)} { 154 b.Append(c) 155 } 156 157 Convey(`An unlimited View`, func() { 158 br := b.View() 159 160 Convey(`Should have Remaining() value of 9.`, func() { 161 So(br.Remaining(), ShouldEqual, 9) 162 }) 163 164 Convey(`Can spawn a limited clone.`, func() { 165 buf := bytes.Buffer{} 166 _, err := buf.ReadFrom(br.CloneLimit(7)) 167 So(err, ShouldBeNil) 168 So(buf.Bytes(), ShouldResemble, []byte{0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00}) 169 }) 170 171 for _, s := range []struct { 172 needle []byte 173 index int64 174 }{ 175 {[]byte(nil), 0}, 176 {[]byte{0x01}, 0}, 177 {[]byte{0x01, 0x02}, 0}, 178 {[]byte{0x02, 0x00}, 1}, 179 {[]byte{0x00}, 2}, 180 {[]byte{0x00, 0x00}, 2}, 181 {[]byte{0x00, 0x00, 0x00}, 5}, 182 {[]byte{0x03, 0x00, 0x00}, 4}, 183 } { 184 Convey(fmt.Sprintf(`Has Index %v for needle %v`, s.index, s.needle), func() { 185 So(br.Index(s.needle), ShouldEqual, s.index) 186 }) 187 } 188 }) 189 190 Convey(`A View with a limit of 6`, func() { 191 br := b.ViewLimit(6) 192 193 Convey(`Should have Remaining() value of 6.`, func() { 194 So(br.Remaining(), ShouldEqual, 6) 195 }) 196 197 Convey(`Has index of -1 for needle [0x00, 0x04]`, func() { 198 So(br.Index([]byte{0x00, 0x04}), ShouldEqual, -1) 199 }) 200 }) 201 202 Convey(`A View with a limit of 20`, func() { 203 br := b.ViewLimit(20) 204 205 Convey(`Should have Remaining() value of 9.`, func() { 206 So(br.Remaining(), ShouldEqual, 9) 207 }) 208 }) 209 }) 210 211 Convey(`With chunks [{0x0F}..{0x00}]`, func() { 212 for i := 0x0F; i >= 0x00; i-- { 213 b.Append(tc(byte(i))) 214 } 215 br := b.View() 216 217 Convey(`Has index of -1 for needle [0x0f, 0x10]`, func() { 218 So(br.Index([]byte{0x0f, 0x10}), ShouldEqual, -1) 219 }) 220 221 for _, s := range []struct { 222 needle []byte 223 index int64 224 }{ 225 {[]byte{0x0F}, 0}, 226 {[]byte{0x04, 0x03, 0x02}, 11}, 227 {[]byte{0x01, 0x00}, 14}, 228 {[]byte{0x00}, 15}, 229 {[]byte{0x00, 0xFF}, -1}, 230 } { 231 Convey(fmt.Sprintf(`Has Index %v for needle %v`, s.index, s.needle), func() { 232 So(br.Index(s.needle), ShouldEqual, s.index) 233 }) 234 } 235 }) 236 }) 237 }