Source file src/net/http/internal/http3/qpack_test.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http3
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  )
    11  
    12  func TestPrefixedInt(t *testing.T) {
    13  	st1, st2 := newStreamPair(t)
    14  	for _, test := range []struct {
    15  		value     int64
    16  		prefixLen uint8
    17  		encoded   []byte
    18  	}{
    19  		// https://www.rfc-editor.org/rfc/rfc7541#appendix-C.1.1
    20  		{
    21  			value:     10,
    22  			prefixLen: 5,
    23  			encoded: []byte{
    24  				0b_0000_1010,
    25  			},
    26  		},
    27  		// https://www.rfc-editor.org/rfc/rfc7541#appendix-C.1.2
    28  		{
    29  			value:     1337,
    30  			prefixLen: 5,
    31  			encoded: []byte{
    32  				0b0001_1111,
    33  				0b1001_1010,
    34  				0b0000_1010,
    35  			},
    36  		},
    37  		// https://www.rfc-editor.org/rfc/rfc7541#appendix-C.1.3
    38  		{
    39  			value:     42,
    40  			prefixLen: 8,
    41  			encoded: []byte{
    42  				0b0010_1010,
    43  			},
    44  		},
    45  	} {
    46  		highBitMask := ^((byte(1) << test.prefixLen) - 1)
    47  		for _, highBits := range []byte{
    48  			0, highBitMask, 0b1010_1010 & highBitMask,
    49  		} {
    50  			gotEnc := appendPrefixedInt(nil, highBits, test.prefixLen, test.value)
    51  			wantEnc := append([]byte{}, test.encoded...)
    52  			wantEnc[0] |= highBits
    53  			if !bytes.Equal(gotEnc, wantEnc) {
    54  				t.Errorf("appendPrefixedInt(nil, 0b%08b, %v, %v) = {%x}, want {%x}",
    55  					highBits, test.prefixLen, test.value, gotEnc, wantEnc)
    56  			}
    57  
    58  			st1.Write(gotEnc)
    59  			if err := st1.Flush(); err != nil {
    60  				t.Fatal(err)
    61  			}
    62  			gotFirstByte, v, err := st2.readPrefixedInt(test.prefixLen)
    63  			if err != nil || gotFirstByte&highBitMask != highBits || v != test.value {
    64  				t.Errorf("st.readPrefixedInt(%v) = 0b%08b, %v, %v; want 0b%08b, %v, nil", test.prefixLen, gotFirstByte, v, err, highBits, test.value)
    65  			}
    66  		}
    67  	}
    68  }
    69  
    70  func TestPrefixedString(t *testing.T) {
    71  	st1, st2 := newStreamPair(t)
    72  	for _, test := range []struct {
    73  		value     string
    74  		prefixLen uint8
    75  		encoded   []byte
    76  	}{
    77  		// https://www.rfc-editor.org/rfc/rfc7541#appendix-C.6.1
    78  		{
    79  			value:     "302",
    80  			prefixLen: 7,
    81  			encoded: []byte{
    82  				0x82, // H bit + length 2
    83  				0x64, 0x02,
    84  			},
    85  		},
    86  		{
    87  			value:     "private",
    88  			prefixLen: 5,
    89  			encoded: []byte{
    90  				0x25, // H bit + length 5
    91  				0xae, 0xc3, 0x77, 0x1a, 0x4b,
    92  			},
    93  		},
    94  		{
    95  			value:     "Mon, 21 Oct 2013 20:13:21 GMT",
    96  			prefixLen: 7,
    97  			encoded: []byte{
    98  				0x96, // H bit + length 22
    99  				0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44,
   100  				0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b, 0x81, 0x66,
   101  				0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff,
   102  			},
   103  		},
   104  		{
   105  			value:     "https://www.example.com",
   106  			prefixLen: 7,
   107  			encoded: []byte{
   108  				0x91, // H bit + length 17
   109  				0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f,
   110  				0x0b, 0x97, 0xc8, 0xe9, 0xae, 0x82, 0xae, 0x43,
   111  				0xd3,
   112  			},
   113  		},
   114  		// Not Huffman encoded (encoded size == unencoded size).
   115  		{
   116  			value:     "a",
   117  			prefixLen: 7,
   118  			encoded: []byte{
   119  				0x01, // length 1
   120  				0x61,
   121  			},
   122  		},
   123  		// Empty string.
   124  		{
   125  			value:     "",
   126  			prefixLen: 7,
   127  			encoded: []byte{
   128  				0x00, // length 0
   129  			},
   130  		},
   131  	} {
   132  		highBitMask := ^((byte(1) << (test.prefixLen + 1)) - 1)
   133  		for _, highBits := range []byte{
   134  			0, highBitMask, 0b1010_1010 & highBitMask,
   135  		} {
   136  			gotEnc := appendPrefixedString(nil, highBits, test.prefixLen, test.value)
   137  			wantEnc := append([]byte{}, test.encoded...)
   138  			wantEnc[0] |= highBits
   139  			if !bytes.Equal(gotEnc, wantEnc) {
   140  				t.Errorf("appendPrefixedString(nil, 0b%08b, %v, %v) = {%x}, want {%x}",
   141  					highBits, test.prefixLen, test.value, gotEnc, wantEnc)
   142  			}
   143  
   144  			st1.Write(gotEnc)
   145  			if err := st1.Flush(); err != nil {
   146  				t.Fatal(err)
   147  			}
   148  			gotFirstByte, v, err := st2.readPrefixedString(test.prefixLen)
   149  			if err != nil || gotFirstByte&highBitMask != highBits || v != test.value {
   150  				t.Errorf("st.readPrefixedInt(%v) = 0b%08b, %q, %v; want 0b%08b, %q, nil", test.prefixLen, gotFirstByte, v, err, highBits, test.value)
   151  			}
   152  		}
   153  	}
   154  }
   155  
   156  func TestHuffmanDecodingFailure(t *testing.T) {
   157  	st1, st2 := newStreamPair(t)
   158  	st1.Write([]byte{
   159  		0x82, // H bit + length 4
   160  		0b_1111_1111,
   161  		0b_1111_1111,
   162  		0b_1111_1111,
   163  		0b_1111_1111,
   164  	})
   165  	if err := st1.Flush(); err != nil {
   166  		t.Fatal(err)
   167  	}
   168  	if b, v, err := st2.readPrefixedString(7); err == nil {
   169  		t.Fatalf("readPrefixedString(7) = %x, %v, nil; want error", b, v)
   170  	}
   171  }
   172  

View as plain text