github.com/pion/dtls/v2@v2.2.12/fragment_buffer_test.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package dtls
     5  
     6  import (
     7  	"errors"
     8  	"reflect"
     9  	"testing"
    10  )
    11  
    12  func TestFragmentBuffer(t *testing.T) {
    13  	for _, test := range []struct {
    14  		Name     string
    15  		In       [][]byte
    16  		Expected [][]byte
    17  		Epoch    uint16
    18  	}{
    19  		{
    20  			Name: "Single Fragment",
    21  			In: [][]byte{
    22  				{0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00},
    23  			},
    24  			Expected: [][]byte{
    25  				{0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00},
    26  			},
    27  			Epoch: 0,
    28  		},
    29  		{
    30  			Name: "Single Fragment Epoch 3",
    31  			In: [][]byte{
    32  				{0x16, 0xfe, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00},
    33  			},
    34  			Expected: [][]byte{
    35  				{0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00},
    36  			},
    37  			Epoch: 3,
    38  		},
    39  		{
    40  			Name: "Multiple Fragments",
    41  			In: [][]byte{
    42  				{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04},
    43  				{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09},
    44  				{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E},
    45  			},
    46  			Expected: [][]byte{
    47  				{0x0b, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e},
    48  			},
    49  			Epoch: 0,
    50  		},
    51  		{
    52  			Name: "Multiple Unordered Fragments",
    53  			In: [][]byte{
    54  				{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04},
    55  				{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x05, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E},
    56  				{0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x81, 0x0b, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09},
    57  			},
    58  			Expected: [][]byte{
    59  				{0x0b, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e},
    60  			},
    61  			Epoch: 0,
    62  		},
    63  		{
    64  			Name: "Multiple Handshakes in Single Fragment",
    65  			In: [][]byte{
    66  				{
    67  					0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, /* record header */
    68  					0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01, /*handshake msg 1*/
    69  					0x03, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01, /*handshake msg 2*/
    70  					0x03, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01, /*handshake msg 3*/
    71  				},
    72  			},
    73  			Expected: [][]byte{
    74  				{0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01},
    75  				{0x03, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01},
    76  				{0x03, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x01, 0x01},
    77  			},
    78  			Epoch: 0,
    79  		},
    80  		// Assert that a zero length fragment doesn't cause the fragmentBuffer to enter an infinite loop
    81  		{
    82  			Name: "Zero Length Fragment",
    83  			In: [][]byte{
    84  				{
    85  					0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
    86  					0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    87  				},
    88  			},
    89  			Expected: [][]byte{
    90  				{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
    91  			},
    92  			Epoch: 0,
    93  		},
    94  	} {
    95  		fragmentBuffer := newFragmentBuffer()
    96  		for _, frag := range test.In {
    97  			status, err := fragmentBuffer.push(frag)
    98  			if err != nil {
    99  				t.Error(err)
   100  			} else if !status {
   101  				t.Errorf("fragmentBuffer didn't accept fragments for '%s'", test.Name)
   102  			}
   103  		}
   104  
   105  		for _, expected := range test.Expected {
   106  			out, epoch := fragmentBuffer.pop()
   107  			if !reflect.DeepEqual(out, expected) {
   108  				t.Errorf("fragmentBuffer '%s' push/pop: got % 02x, want % 02x", test.Name, out, expected)
   109  			}
   110  			if epoch != test.Epoch {
   111  				t.Errorf("fragmentBuffer returned wrong epoch: got %d, want %d", epoch, test.Epoch)
   112  			}
   113  		}
   114  
   115  		if frag, _ := fragmentBuffer.pop(); frag != nil {
   116  			t.Errorf("fragmentBuffer popped single buffer multiple times for '%s'", test.Name)
   117  		}
   118  	}
   119  }
   120  
   121  func TestFragmentBuffer_Overflow(t *testing.T) {
   122  	fragmentBuffer := newFragmentBuffer()
   123  
   124  	// Push a buffer that doesn't exceed size limits
   125  	if _, err := fragmentBuffer.push([]byte{0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x00}); err != nil {
   126  		t.Fatal(err)
   127  	}
   128  
   129  	// Allocate a buffer that exceeds cache size
   130  	largeBuffer := make([]byte, fragmentBufferMaxSize)
   131  	if _, err := fragmentBuffer.push(largeBuffer); !errors.Is(err, errFragmentBufferOverflow) {
   132  		t.Fatalf("Pushing a large buffer returned (%s) expected(%s)", err, errFragmentBufferOverflow)
   133  	}
   134  }