gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/stack/packet_buffer_test.go (about) 1 // Copyright 2020 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 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package stack 15 16 import ( 17 "bytes" 18 "fmt" 19 "testing" 20 21 "gvisor.dev/gvisor/pkg/buffer" 22 ) 23 24 func TestPacketHeaderPush(t *testing.T) { 25 for _, test := range []struct { 26 name string 27 reserved int 28 link []byte 29 network []byte 30 transport []byte 31 data []byte 32 }{ 33 { 34 name: "construct empty packet", 35 }, 36 { 37 name: "construct link header only packet", 38 reserved: 60, 39 link: makeView(10), 40 }, 41 { 42 name: "construct link and network header only packet", 43 reserved: 60, 44 link: makeView(10), 45 network: makeView(20), 46 }, 47 { 48 name: "construct header only packet", 49 reserved: 60, 50 link: makeView(10), 51 network: makeView(20), 52 transport: makeView(30), 53 }, 54 { 55 name: "construct data only packet", 56 data: makeView(40), 57 }, 58 { 59 name: "construct L3 packet", 60 reserved: 60, 61 network: makeView(20), 62 transport: makeView(30), 63 data: makeView(40), 64 }, 65 { 66 name: "construct L2 packet", 67 reserved: 60, 68 link: makeView(10), 69 network: makeView(20), 70 transport: makeView(30), 71 data: makeView(40), 72 }, 73 } { 74 t.Run(test.name, func(t *testing.T) { 75 pk := NewPacketBuffer(PacketBufferOptions{ 76 ReserveHeaderBytes: test.reserved, 77 // Make a copy of data to make sure our truth data won't be taint by 78 // PacketBuffer. 79 Payload: buffer.MakeWithData(test.data), 80 }) 81 82 allHdrSize := len(test.link) + len(test.network) + len(test.transport) 83 84 // Check the initial values for packet. 85 checkInitialPacketBuffer(t, pk, PacketBufferOptions{ 86 ReserveHeaderBytes: test.reserved, 87 Payload: buffer.MakeWithData(test.data), 88 }) 89 90 // Push headers. 91 if v := test.transport; len(v) > 0 { 92 copy(pk.TransportHeader().Push(len(v)), v) 93 } 94 if v := test.network; len(v) > 0 { 95 copy(pk.NetworkHeader().Push(len(v)), v) 96 } 97 if v := test.link; len(v) > 0 { 98 copy(pk.LinkHeader().Push(len(v)), v) 99 } 100 101 // Check the after values for packet. 102 if got, want := pk.ReservedHeaderBytes(), test.reserved; got != want { 103 t.Errorf("After pk.ReservedHeaderBytes() = %d, want %d", got, want) 104 } 105 if got, want := pk.AvailableHeaderBytes(), test.reserved-allHdrSize; got != want { 106 t.Errorf("After pk.AvailableHeaderBytes() = %d, want %d", got, want) 107 } 108 if got, want := pk.HeaderSize(), allHdrSize; got != want { 109 t.Errorf("After pk.HeaderSize() = %d, want %d", got, want) 110 } 111 if got, want := pk.Size(), allHdrSize+len(test.data); got != want { 112 t.Errorf("After pk.Size() = %d, want %d", got, want) 113 } 114 // Check the after state. 115 checkPacketContents(t, "After ", pk, packetContents{ 116 link: test.link, 117 network: test.network, 118 transport: test.transport, 119 data: test.data, 120 }) 121 }) 122 } 123 } 124 125 func TestPacketHeaderConsume(t *testing.T) { 126 for _, test := range []struct { 127 name string 128 data []byte 129 link int 130 network int 131 transport int 132 }{ 133 { 134 name: "parse L2 packet", 135 data: concatViews(makeView(10), makeView(20), makeView(30), makeView(40)), 136 link: 10, 137 network: 20, 138 transport: 30, 139 }, 140 { 141 name: "parse L3 packet", 142 data: concatViews(makeView(20), makeView(30), makeView(40)), 143 network: 20, 144 transport: 30, 145 }, 146 } { 147 t.Run(test.name, func(t *testing.T) { 148 pk := NewPacketBuffer(PacketBufferOptions{ 149 // Make a copy of data to make sure our truth data won't be taint by 150 // PacketBuffer. 151 Payload: buffer.MakeWithData(test.data), 152 }) 153 154 // Check the initial values for packet. 155 checkInitialPacketBuffer(t, pk, PacketBufferOptions{ 156 Payload: buffer.MakeWithData(test.data), 157 }) 158 159 // Consume headers. 160 if size := test.link; size > 0 { 161 if _, ok := pk.LinkHeader().Consume(size); !ok { 162 t.Fatalf("pk.LinkHeader().Consume() = false, want true") 163 } 164 } 165 if size := test.network; size > 0 { 166 if _, ok := pk.NetworkHeader().Consume(size); !ok { 167 t.Fatalf("pk.NetworkHeader().Consume() = false, want true") 168 } 169 } 170 if size := test.transport; size > 0 { 171 if _, ok := pk.TransportHeader().Consume(size); !ok { 172 t.Fatalf("pk.TransportHeader().Consume() = false, want true") 173 } 174 } 175 176 allHdrSize := test.link + test.network + test.transport 177 178 // Check the after values for packet. 179 if got, want := pk.ReservedHeaderBytes(), 0; got != want { 180 t.Errorf("After pk.ReservedHeaderBytes() = %d, want %d", got, want) 181 } 182 if got, want := pk.AvailableHeaderBytes(), 0; got != want { 183 t.Errorf("After pk.AvailableHeaderBytes() = %d, want %d", got, want) 184 } 185 if got, want := pk.HeaderSize(), allHdrSize; got != want { 186 t.Errorf("After pk.HeaderSize() = %d, want %d", got, want) 187 } 188 if got, want := pk.Size(), len(test.data); got != want { 189 t.Errorf("After pk.Size() = %d, want %d", got, want) 190 } 191 // Check the after state of pk. 192 checkPacketContents(t, "After ", pk, packetContents{ 193 link: test.data[:test.link], 194 network: test.data[test.link:][:test.network], 195 transport: test.data[test.link+test.network:][:test.transport], 196 data: test.data[allHdrSize:], 197 }) 198 }) 199 } 200 } 201 202 func TestPacketHeaderConsumeDataTooShort(t *testing.T) { 203 data := makeView(10) 204 205 pk := NewPacketBuffer(PacketBufferOptions{ 206 // Make a copy of data to make sure our truth data won't be taint by 207 // PacketBuffer. 208 Payload: buffer.MakeWithData(data), 209 }) 210 211 // Consume should fail if pkt.Data is too short. 212 if _, ok := pk.LinkHeader().Consume(11); ok { 213 t.Fatalf("pk.LinkHeader().Consume() = _, true; want _, false") 214 } 215 if _, ok := pk.NetworkHeader().Consume(11); ok { 216 t.Fatalf("pk.NetworkHeader().Consume() = _, true; want _, false") 217 } 218 if _, ok := pk.TransportHeader().Consume(11); ok { 219 t.Fatalf("pk.TransportHeader().Consume() = _, true; want _, false") 220 } 221 222 // Check packet should look the same as initial packet. 223 checkInitialPacketBuffer(t, pk, PacketBufferOptions{ 224 Payload: buffer.MakeWithData(data), 225 }) 226 } 227 228 // This is a very obscure use-case seen in the code that verifies packets 229 // before sending them out. It tries to parse the headers to verify. 230 // PacketHeader was initially not designed to mix Push() and Consume(), but it 231 // works and it's been relied upon. Include a test here. 232 func TestPacketHeaderPushConsumeMixed(t *testing.T) { 233 link := makeView(10) 234 network := makeView(20) 235 data := makeView(30) 236 237 initData := append([]byte(nil), network...) 238 initData = append(initData, data...) 239 pk := NewPacketBuffer(PacketBufferOptions{ 240 ReserveHeaderBytes: len(link), 241 Payload: buffer.MakeWithData(initData), 242 }) 243 244 // 1. Consume network header 245 gotNetwork, ok := pk.NetworkHeader().Consume(len(network)) 246 if !ok { 247 t.Fatalf("pk.NetworkHeader().Consume(%d) = _, false; want _, true", len(network)) 248 } 249 checkViewEqual(t, "gotNetwork", gotNetwork, network) 250 251 // 2. Push link header 252 copy(pk.LinkHeader().Push(len(link)), link) 253 254 checkPacketContents(t, "" /* prefix */, pk, packetContents{ 255 link: link, 256 network: network, 257 data: data, 258 }) 259 } 260 261 func TestPacketHeaderPushConsumeMixedTooLong(t *testing.T) { 262 link := makeView(10) 263 network := makeView(20) 264 data := makeView(30) 265 266 initData := concatViews(network, data) 267 pk := NewPacketBuffer(PacketBufferOptions{ 268 ReserveHeaderBytes: len(link), 269 Payload: buffer.MakeWithData(initData), 270 }) 271 272 // 1. Push link header 273 copy(pk.LinkHeader().Push(len(link)), link) 274 275 checkPacketContents(t, "" /* prefix */, pk, packetContents{ 276 link: link, 277 data: initData, 278 }) 279 280 // 2. Consume network header, with a number of bytes too large. 281 gotNetwork, ok := pk.NetworkHeader().Consume(len(initData) + 1) 282 if ok { 283 t.Fatalf("pk.NetworkHeader().Consume(%d) = %q, true; want _, false", len(initData)+1, gotNetwork) 284 } 285 286 checkPacketContents(t, "" /* prefix */, pk, packetContents{ 287 link: link, 288 data: initData, 289 }) 290 } 291 292 func TestPacketHeaderPushCalledAtMostOnce(t *testing.T) { 293 const headerSize = 10 294 295 pk := NewPacketBuffer(PacketBufferOptions{ 296 ReserveHeaderBytes: headerSize * int(numHeaderType), 297 }) 298 299 for _, h := range []PacketHeader{ 300 pk.TransportHeader(), 301 pk.NetworkHeader(), 302 pk.LinkHeader(), 303 } { 304 t.Run("PushedTwice/"+h.typ.String(), func(t *testing.T) { 305 h.Push(headerSize) 306 307 defer func() { recover() }() 308 h.Push(headerSize) 309 t.Fatal("Second push should have panicked") 310 }) 311 } 312 } 313 314 func TestPacketHeaderConsumeCalledAtMostOnce(t *testing.T) { 315 const headerSize = 10 316 317 pk := NewPacketBuffer(PacketBufferOptions{ 318 Payload: buffer.MakeWithData(make([]byte, headerSize*int(numHeaderType))), 319 }) 320 321 for _, h := range []PacketHeader{ 322 pk.LinkHeader(), 323 pk.NetworkHeader(), 324 pk.TransportHeader(), 325 } { 326 t.Run("ConsumedTwice/"+h.typ.String(), func(t *testing.T) { 327 if _, ok := h.Consume(headerSize); !ok { 328 t.Fatal("First consume should succeed") 329 } 330 331 defer func() { recover() }() 332 h.Consume(headerSize) 333 t.Fatal("Second consume should have panicked") 334 }) 335 } 336 } 337 338 func TestReserveHeadersAllowsPush(t *testing.T) { 339 link1 := makeView(10) 340 pk := NewPacketBuffer(PacketBufferOptions{}) 341 pk.ReserveHeaderBytes(len(link1)) 342 343 copy(pk.LinkHeader().Push(len(link1)), link1) 344 checkPacketContents(t, "" /* prefix */, pk, packetContents{ 345 link: link1, 346 }) 347 } 348 349 func TestPacketHeaderPushThenConsumePanics(t *testing.T) { 350 const headerSize = 10 351 352 pk := NewPacketBuffer(PacketBufferOptions{ 353 ReserveHeaderBytes: headerSize * int(numHeaderType), 354 }) 355 356 for _, h := range []PacketHeader{ 357 pk.TransportHeader(), 358 pk.NetworkHeader(), 359 pk.LinkHeader(), 360 } { 361 t.Run(h.typ.String(), func(t *testing.T) { 362 h.Push(headerSize) 363 364 defer func() { recover() }() 365 h.Consume(headerSize) 366 t.Fatal("Consume should have panicked") 367 }) 368 } 369 } 370 371 func TestPacketHeaderConsumeThenPushPanics(t *testing.T) { 372 const headerSize = 10 373 374 pk := NewPacketBuffer(PacketBufferOptions{ 375 Payload: buffer.MakeWithData(make([]byte, headerSize*int(numHeaderType))), 376 }) 377 378 for _, h := range []PacketHeader{ 379 pk.LinkHeader(), 380 pk.NetworkHeader(), 381 pk.TransportHeader(), 382 } { 383 t.Run(h.typ.String(), func(t *testing.T) { 384 h.Consume(headerSize) 385 386 defer func() { recover() }() 387 h.Push(headerSize) 388 t.Fatal("Push should have panicked") 389 }) 390 } 391 } 392 393 func TestPacketBufferData(t *testing.T) { 394 for _, tc := range []struct { 395 name string 396 makePkt func(*testing.T) *PacketBuffer 397 data string 398 }{ 399 { 400 name: "inbound packet", 401 makePkt: func(*testing.T) *PacketBuffer { 402 pkt := NewPacketBuffer(PacketBufferOptions{ 403 Payload: buf("aabbbbccccccDATA"), 404 }) 405 pkt.LinkHeader().Consume(2) 406 pkt.NetworkHeader().Consume(4) 407 pkt.TransportHeader().Consume(6) 408 return pkt 409 }, 410 data: "DATA", 411 }, 412 { 413 name: "outbound packet", 414 makePkt: func(*testing.T) *PacketBuffer { 415 pkt := NewPacketBuffer(PacketBufferOptions{ 416 ReserveHeaderBytes: 12, 417 Payload: buf("DATA"), 418 }) 419 copy(pkt.TransportHeader().Push(6), []byte("cccccc")) 420 copy(pkt.NetworkHeader().Push(4), []byte("bbbb")) 421 copy(pkt.LinkHeader().Push(2), []byte("aa")) 422 return pkt 423 }, 424 data: "DATA", 425 }, 426 } { 427 t.Run(tc.name, func(t *testing.T) { 428 // PullUp 429 t.Run("PullUp", func(t *testing.T) { 430 for _, n := range []int{1, len(tc.data)} { 431 t.Run(fmt.Sprintf("%dbytes", n), func(t *testing.T) { 432 pkt := tc.makePkt(t) 433 v, ok := pkt.Data().PullUp(n) 434 wantV := []byte(tc.data)[:n] 435 if !ok || !bytes.Equal(v, wantV) { 436 t.Errorf("pkt.Data().PullUp(%d) = %q, %t; want %q, true", n, v, ok, wantV) 437 } 438 }) 439 } 440 }) 441 442 t.Run("PullUpOutOfBounds", func(t *testing.T) { 443 n := len(tc.data) + 1 444 pkt := tc.makePkt(t) 445 v, ok := pkt.Data().PullUp(n) 446 if ok || v != nil { 447 t.Errorf("pkt.Data().PullUp(%d) = %q, %t; want nil, false", n, v, ok) 448 } 449 }) 450 451 // Consume. 452 t.Run("Consume", func(t *testing.T) { 453 for _, n := range []int{1, len(tc.data)} { 454 t.Run(fmt.Sprintf("%dbytes", n), func(t *testing.T) { 455 pkt := tc.makePkt(t) 456 v, ok := pkt.Data().Consume(n) 457 if !ok { 458 t.Fatalf("Consume failed") 459 } 460 if want := []byte(tc.data)[:n]; !bytes.Equal(v, want) { 461 t.Fatalf("pkt.Data().Consume(n) = 0x%x, want 0x%x", v, want) 462 } 463 464 checkData(t, pkt, []byte(tc.data)[n:]) 465 }) 466 } 467 }) 468 469 // CapLength 470 t.Run("CapLength", func(t *testing.T) { 471 for _, n := range []int{0, 1, len(tc.data)} { 472 t.Run("%dbytes", func(t *testing.T) { 473 pkt := tc.makePkt(t) 474 pkt.Data().CapLength(n) 475 476 want := []byte(tc.data) 477 if n < len(want) { 478 want = want[:n] 479 } 480 checkData(t, pkt, want) 481 }) 482 } 483 }) 484 485 // Views 486 t.Run("Views", func(t *testing.T) { 487 pkt := tc.makePkt(t) 488 checkData(t, pkt, []byte(tc.data)) 489 }) 490 491 // AppendView 492 t.Run("AppendView", func(t *testing.T) { 493 s := "APPEND" 494 495 pkt := tc.makePkt(t) 496 pkt.Data().AppendView(buffer.NewViewWithData([]byte(s))) 497 498 checkData(t, pkt, []byte(tc.data+s)) 499 }) 500 501 t.Run("Merge", func(t *testing.T) { 502 pkt1 := tc.makePkt(t) 503 pkt2 := tc.makePkt(t) 504 pkt1.Data().Merge(pkt2.Data()) 505 506 checkData(t, pkt1, []byte(tc.data+tc.data)) 507 if pkt2.buf.Size() != 0 { 508 t.Errorf("pkt.buf.Size() = %v, want %v", 0, pkt2.buf.Size()) 509 } 510 }) 511 512 t.Run("TrimFront", func(t *testing.T) { 513 for _, n := range []int{0, 1, 2, 7, 10, 14, 20} { 514 t.Run(fmt.Sprintf("%dbytes", n), func(t *testing.T) { 515 pkt := tc.makePkt(t) 516 pkt.Data().TrimFront(n) 517 518 want := "" 519 if n < len(tc.data) { 520 want = tc.data[n:] 521 } 522 checkData(t, pkt, []byte(want)) 523 }) 524 } 525 }) 526 527 // ReadFromBuffer 528 for _, n := range []int{0, 1, 2, 7, 10, 14, 20} { 529 t.Run(fmt.Sprintf("ReadFrom%d", n), func(t *testing.T) { 530 s := "TO READ" 531 s += s 532 srcBuf := buffer.MakeWithData([]byte(s)) 533 534 pkt := tc.makePkt(t) 535 pkt.Data().ReadFrom(&srcBuf, n) 536 537 if n < len(s) { 538 s = s[:n] 539 } 540 checkData(t, pkt, []byte(tc.data+s)) 541 }) 542 } 543 }) 544 } 545 } 546 547 func TestPacketBufferId(t *testing.T) { 548 pk := NewPacketBuffer(PacketBufferOptions{ 549 ReserveHeaderBytes: 12, 550 }) 551 552 id := pk.ID() 553 // The ID should be stable 554 if idAgain := pk.ID(); idAgain != id { 555 t.Errorf("pk.ID() = %d, want %d", idAgain, id) 556 } 557 558 // Shallow copies have the same ID. 559 pkShallowCopy := pk 560 if shallowCopyID := pkShallowCopy.ID(); shallowCopyID != id { 561 t.Errorf("pkShallowCopy.ID() = %d, want %d", shallowCopyID, id) 562 } 563 564 // Clones have different IDs. 565 pkClone := pk.Clone() 566 if cloneID := pkClone.ID(); cloneID == id { 567 t.Errorf("pkClone.ID() = %d = pk.ID(), but pk = %#v, pkClone = %#v", cloneID, pk, pkClone) 568 } 569 570 pk2 := NewPacketBuffer(PacketBufferOptions{ReserveHeaderBytes: 12}) 571 if id2 := pk2.ID(); id2 == id { 572 t.Errorf("pk2.ID() = %d = pk.ID(), but pk = %#v, pk2 = %#v", id2, pk, pk2) 573 } 574 } 575 576 type packetContents struct { 577 link []byte 578 network []byte 579 transport []byte 580 data []byte 581 } 582 583 func checkPacketContents(t *testing.T, prefix string, pk *PacketBuffer, want packetContents) { 584 t.Helper() 585 // Headers. 586 checkPacketHeader(t, prefix+"pk.LinkHeader", pk.LinkHeader(), want.link) 587 checkPacketHeader(t, prefix+"pk.NetworkHeader", pk.NetworkHeader(), want.network) 588 checkPacketHeader(t, prefix+"pk.TransportHeader", pk.TransportHeader(), want.transport) 589 // Data. 590 checkData(t, pk, want.data) 591 // Whole packet. 592 checkViewEqual(t, prefix+"pk.AsSlices()", 593 concatViews(pk.AsSlices()...), 594 concatViews(want.link, want.network, want.transport, want.data)) 595 // PayloadSince. 596 link := PayloadSince(pk.LinkHeader()) 597 checkViewEqual(t, prefix+"PayloadSince(LinkHeader)", 598 link.AsSlice(), 599 concatViews(want.link, want.network, want.transport, want.data)) 600 net := PayloadSince(pk.NetworkHeader()) 601 checkViewEqual(t, prefix+"PayloadSince(NetworkHeader)", 602 net.AsSlice(), 603 concatViews(want.network, want.transport, want.data)) 604 trans := PayloadSince(pk.TransportHeader()) 605 checkViewEqual(t, prefix+"PayloadSince(TransportHeader)", 606 trans.AsSlice(), 607 concatViews(want.transport, want.data)) 608 // BufferSince. 609 linkBuf := BufferSince(pk.LinkHeader()) 610 checkViewEqual(t, prefix+"PayloadSince(LinkHeader)", 611 linkBuf.Flatten(), 612 concatViews(want.link, want.network, want.transport, want.data)) 613 netBuf := BufferSince(pk.NetworkHeader()) 614 checkViewEqual(t, prefix+"PayloadSince(NetworkHeader)", 615 netBuf.Flatten(), 616 concatViews(want.network, want.transport, want.data)) 617 transBuf := BufferSince(pk.TransportHeader()) 618 checkViewEqual(t, prefix+"PayloadSince(TransportHeader)", 619 transBuf.Flatten(), 620 concatViews(want.transport, want.data)) 621 } 622 623 func checkInitialPacketBuffer(t *testing.T, pk *PacketBuffer, opts PacketBufferOptions) { 624 t.Helper() 625 reserved := opts.ReserveHeaderBytes 626 if got, want := pk.ReservedHeaderBytes(), reserved; got != want { 627 t.Errorf("Initial pk.ReservedHeaderBytes() = %d, want %d", got, want) 628 } 629 if got, want := pk.AvailableHeaderBytes(), reserved; got != want { 630 t.Errorf("Initial pk.AvailableHeaderBytes() = %d, want %d", got, want) 631 } 632 if got, want := pk.HeaderSize(), 0; got != want { 633 t.Errorf("Initial pk.HeaderSize() = %d, want %d", got, want) 634 } 635 data := opts.Payload.Flatten() 636 if got, want := pk.Size(), len(data); got != want { 637 t.Errorf("Initial pk.Size() = %d, want %d", got, want) 638 } 639 checkPacketContents(t, "Initial ", pk, packetContents{ 640 data: data, 641 }) 642 } 643 644 func checkPacketHeader(t *testing.T, name string, h PacketHeader, want []byte) { 645 t.Helper() 646 checkViewEqual(t, name+".Slice()", h.Slice(), want) 647 } 648 649 func checkViewEqual(t *testing.T, what string, got, want []byte) { 650 t.Helper() 651 if !bytes.Equal(got, want) { 652 t.Errorf("%s = %x, want %x", what, got, want) 653 } 654 } 655 656 func checkData(t *testing.T, pkt *PacketBuffer, want []byte) { 657 t.Helper() 658 if got := pkt.Data().AsRange().ToSlice(); !bytes.Equal(got, want) { 659 t.Errorf("pkt.Data().Slices() = 0x%x, want 0x%x", got, want) 660 } 661 if got := pkt.Data().Size(); got != len(want) { 662 t.Errorf("pkt.Data().Size() = %d, want %d", got, len(want)) 663 } 664 665 t.Run("AsRange", func(t *testing.T) { 666 // Full range 667 checkRange(t, pkt.Data().AsRange(), want) 668 669 // SubRange 670 for _, off := range []int{0, 1, len(want), len(want) + 1} { 671 t.Run(fmt.Sprintf("SubRange%d", off), func(t *testing.T) { 672 // Empty when off is greater than the size of range. 673 var sub []byte 674 if off < len(want) { 675 sub = want[off:] 676 } 677 checkRange(t, pkt.Data().AsRange().SubRange(off), sub) 678 }) 679 } 680 681 // Capped 682 for _, n := range []int{0, 1, len(want), len(want) + 1} { 683 t.Run(fmt.Sprintf("Capped%d", n), func(t *testing.T) { 684 sub := want 685 if n < len(sub) { 686 sub = sub[:n] 687 } 688 checkRange(t, pkt.Data().AsRange().Capped(n), sub) 689 }) 690 } 691 }) 692 } 693 694 func checkRange(t *testing.T, r Range, data []byte) { 695 if got, want := r.Size(), len(data); got != want { 696 t.Errorf("r.Size() = %d, want %d", got, want) 697 } 698 if got := r.ToSlice(); !bytes.Equal(got, data) { 699 t.Errorf("r.AsSlice() = %x, want %x", got, data) 700 } 701 } 702 703 func buf(pieces ...string) buffer.Buffer { 704 b := buffer.Buffer{} 705 for _, p := range pieces { 706 b.Append(buffer.NewViewWithData([]byte(p))) 707 } 708 return b 709 } 710 711 func makeView(size int) []byte { 712 b := byte(size) 713 return bytes.Repeat([]byte{b}, size) 714 } 715 716 func concatViews(views ...[]byte) []byte { 717 var all []byte 718 for _, v := range views { 719 all = append(all, v...) 720 } 721 return all 722 }