github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/safemem/seq_test.go (about) 1 // Copyright 2018 The gVisor 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 safemem 16 17 import ( 18 "bytes" 19 "reflect" 20 "testing" 21 ) 22 23 func TestBlockSeqOfEmptyBlock(t *testing.T) { 24 bs := BlockSeqOf(Block{}) 25 if !bs.IsEmpty() { 26 t.Errorf("BlockSeqOf(Block{}).IsEmpty(): got false, wanted true; BlockSeq is %v", bs) 27 } 28 } 29 30 func TestBlockSeqOfNonemptyBlock(t *testing.T) { 31 b := BlockFromSafeSlice(make([]byte, 1)) 32 bs := BlockSeqOf(b) 33 if bs.IsEmpty() { 34 t.Fatalf("BlockSeqOf(non-empty Block).IsEmpty(): got true, wanted false; BlockSeq is %v", bs) 35 } 36 if head := bs.Head(); head != b { 37 t.Fatalf("BlockSeqOf(non-empty Block).Head(): got %v, wanted %v", head, b) 38 } 39 if tail := bs.Tail(); !tail.IsEmpty() { 40 t.Fatalf("BlockSeqOf(non-empty Block).Tail().IsEmpty(): got false, wanted true: tail is %v", tail) 41 } 42 } 43 44 type blockSeqTest struct { 45 desc string 46 47 pieces []string 48 haveOffset bool 49 offset uint64 50 haveLimit bool 51 limit uint64 52 53 want string 54 } 55 56 func (t blockSeqTest) NonEmptyByteSlices() [][]byte { 57 // t is a value, so we can mutate it freely. 58 slices := make([][]byte, 0, len(t.pieces)) 59 for _, str := range t.pieces { 60 if t.haveOffset { 61 strOff := t.offset 62 if strOff > uint64(len(str)) { 63 strOff = uint64(len(str)) 64 } 65 str = str[strOff:] 66 t.offset -= strOff 67 } 68 if t.haveLimit { 69 strLim := t.limit 70 if strLim > uint64(len(str)) { 71 strLim = uint64(len(str)) 72 } 73 str = str[:strLim] 74 t.limit -= strLim 75 } 76 if len(str) != 0 { 77 slices = append(slices, []byte(str)) 78 } 79 } 80 return slices 81 } 82 83 func (t blockSeqTest) BlockSeq() BlockSeq { 84 blocks := make([]Block, 0, len(t.pieces)) 85 for _, str := range t.pieces { 86 blocks = append(blocks, BlockFromSafeSlice([]byte(str))) 87 } 88 bs := BlockSeqFromSlice(blocks) 89 if t.haveOffset { 90 bs = bs.DropFirst64(t.offset) 91 } 92 if t.haveLimit { 93 bs = bs.TakeFirst64(t.limit) 94 } 95 return bs 96 } 97 98 var blockSeqTests = []blockSeqTest{ 99 { 100 desc: "Empty sequence", 101 }, 102 { 103 desc: "Sequence of length 1", 104 pieces: []string{"foobar"}, 105 want: "foobar", 106 }, 107 { 108 desc: "Sequence of length 2", 109 pieces: []string{"foo", "bar"}, 110 want: "foobar", 111 }, 112 { 113 desc: "Empty Blocks", 114 pieces: []string{"", "foo", "", "", "bar", ""}, 115 want: "foobar", 116 }, 117 { 118 desc: "Sequence with non-zero offset", 119 pieces: []string{"foo", "bar"}, 120 haveOffset: true, 121 offset: 2, 122 want: "obar", 123 }, 124 { 125 desc: "Sequence with non-maximal limit", 126 pieces: []string{"foo", "bar"}, 127 haveLimit: true, 128 limit: 5, 129 want: "fooba", 130 }, 131 { 132 desc: "Sequence with offset and limit", 133 pieces: []string{"foo", "bar"}, 134 haveOffset: true, 135 offset: 2, 136 haveLimit: true, 137 limit: 3, 138 want: "oba", 139 }, 140 } 141 142 func TestBlockSeqNumBytes(t *testing.T) { 143 for _, test := range blockSeqTests { 144 t.Run(test.desc, func(t *testing.T) { 145 if got, want := test.BlockSeq().NumBytes(), uint64(len(test.want)); got != want { 146 t.Errorf("NumBytes: got %d, wanted %d", got, want) 147 } 148 }) 149 } 150 } 151 152 func TestBlockSeqIterBlocks(t *testing.T) { 153 // Tests BlockSeq iteration using Head/Tail. 154 for _, test := range blockSeqTests { 155 t.Run(test.desc, func(t *testing.T) { 156 srcs := test.BlockSeq() 157 // "Note that a non-nil empty slice and a nil slice ... are not 158 // deeply equal." - reflect 159 slices := make([][]byte, 0, 0) 160 for !srcs.IsEmpty() { 161 src := srcs.Head() 162 slices = append(slices, src.ToSlice()) 163 nextSrcs := srcs.Tail() 164 if got, want := nextSrcs.NumBytes(), srcs.NumBytes()-uint64(src.Len()); got != want { 165 t.Fatalf("%v.Tail(): got %v (%d bytes), wanted %d bytes", srcs, nextSrcs, got, want) 166 } 167 srcs = nextSrcs 168 } 169 if wantSlices := test.NonEmptyByteSlices(); !reflect.DeepEqual(slices, wantSlices) { 170 t.Errorf("Accumulated slices: got %v, wanted %v", slices, wantSlices) 171 } 172 }) 173 } 174 } 175 176 func TestBlockSeqIterBytes(t *testing.T) { 177 // Tests BlockSeq iteration using Head/DropFirst. 178 for _, test := range blockSeqTests { 179 t.Run(test.desc, func(t *testing.T) { 180 srcs := test.BlockSeq() 181 var dst bytes.Buffer 182 for !srcs.IsEmpty() { 183 src := srcs.Head() 184 var b [1]byte 185 n, err := Copy(BlockFromSafeSlice(b[:]), src) 186 if n != 1 || err != nil { 187 t.Fatalf("Copy: got (%v, %v), wanted (1, nil)", n, err) 188 } 189 dst.WriteByte(b[0]) 190 nextSrcs := srcs.DropFirst(1) 191 if got, want := nextSrcs.NumBytes(), srcs.NumBytes()-1; got != want { 192 t.Fatalf("%v.DropFirst(1): got %v (%d bytes), wanted %d bytes", srcs, nextSrcs, got, want) 193 } 194 srcs = nextSrcs 195 } 196 if got := string(dst.Bytes()); got != test.want { 197 t.Errorf("Copied string: got %q, wanted %q", got, test.want) 198 } 199 }) 200 } 201 } 202 203 func TestBlockSeqDropBeyondLimit(t *testing.T) { 204 blocks := []Block{BlockFromSafeSlice([]byte("123")), BlockFromSafeSlice([]byte("4"))} 205 bs := BlockSeqFromSlice(blocks) 206 if got, want := bs.NumBytes(), uint64(4); got != want { 207 t.Errorf("%v.NumBytes(): got %d, wanted %d", bs, got, want) 208 } 209 bs = bs.TakeFirst(1) 210 if got, want := bs.NumBytes(), uint64(1); got != want { 211 t.Errorf("%v.NumBytes(): got %d, wanted %d", bs, got, want) 212 } 213 bs = bs.DropFirst(2) 214 if got, want := bs.NumBytes(), uint64(0); got != want { 215 t.Errorf("%v.NumBytes(): got %d, wanted %d", bs, got, want) 216 } 217 }