Source file src/net/http/internal/http2/frame_test.go

     1  // Copyright 2014 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 http2
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  	"unsafe"
    15  
    16  	"golang.org/x/net/http2/hpack"
    17  )
    18  
    19  func testFramer() (*Framer, *bytes.Buffer) {
    20  	buf := new(bytes.Buffer)
    21  	return NewFramer(buf, buf), buf
    22  }
    23  
    24  func TestFrameSizes(t *testing.T) {
    25  	// Catch people rearranging the FrameHeader fields.
    26  	if got, want := int(unsafe.Sizeof(FrameHeader{})), 12; got != want {
    27  		t.Errorf("FrameHeader size = %d; want %d", got, want)
    28  	}
    29  }
    30  
    31  func TestFrameTypeString(t *testing.T) {
    32  	tests := []struct {
    33  		ft   FrameType
    34  		want string
    35  	}{
    36  		{FrameData, "DATA"},
    37  		{FramePing, "PING"},
    38  		{FrameGoAway, "GOAWAY"},
    39  		{0x20, "UNKNOWN_FRAME_TYPE_32"},
    40  	}
    41  
    42  	for i, tt := range tests {
    43  		got := tt.ft.String()
    44  		if got != tt.want {
    45  			t.Errorf("%d. String(FrameType %d) = %q; want %q", i, int(tt.ft), got, tt.want)
    46  		}
    47  	}
    48  }
    49  
    50  func TestWriteRST(t *testing.T) {
    51  	fr, buf := testFramer()
    52  	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
    53  	var errCode uint32 = 7<<24 + 6<<16 + 5<<8 + 4
    54  	fr.WriteRSTStream(streamID, ErrCode(errCode))
    55  	const wantEnc = "\x00\x00\x04\x03\x00\x01\x02\x03\x04\x07\x06\x05\x04"
    56  	if buf.String() != wantEnc {
    57  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
    58  	}
    59  	f, err := fr.ReadFrame()
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	want := &RSTStreamFrame{
    64  		FrameHeader: FrameHeader{
    65  			valid:    true,
    66  			Type:     0x3,
    67  			Flags:    0x0,
    68  			Length:   0x4,
    69  			StreamID: 0x1020304,
    70  		},
    71  		ErrCode: 0x7060504,
    72  	}
    73  	if !reflect.DeepEqual(f, want) {
    74  		t.Errorf("parsed back %#v; want %#v", f, want)
    75  	}
    76  }
    77  
    78  func TestWriteData(t *testing.T) {
    79  	fr, buf := testFramer()
    80  	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
    81  	data := []byte("ABC")
    82  	fr.WriteData(streamID, true, data)
    83  	const wantEnc = "\x00\x00\x03\x00\x01\x01\x02\x03\x04ABC"
    84  	if buf.String() != wantEnc {
    85  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
    86  	}
    87  	f, err := fr.ReadFrame()
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	df, ok := f.(*DataFrame)
    92  	if !ok {
    93  		t.Fatalf("got %T; want *DataFrame", f)
    94  	}
    95  	if !bytes.Equal(df.Data(), data) {
    96  		t.Errorf("got %q; want %q", df.Data(), data)
    97  	}
    98  	if f.Header().Flags&1 == 0 {
    99  		t.Errorf("didn't see END_STREAM flag")
   100  	}
   101  }
   102  
   103  func TestWriteDataPadded(t *testing.T) {
   104  	tests := [...]struct {
   105  		streamID   uint32
   106  		endStream  bool
   107  		data       []byte
   108  		pad        []byte
   109  		wantHeader FrameHeader
   110  	}{
   111  		// Unpadded:
   112  		0: {
   113  			streamID:  1,
   114  			endStream: true,
   115  			data:      []byte("foo"),
   116  			pad:       nil,
   117  			wantHeader: FrameHeader{
   118  				Type:     FrameData,
   119  				Flags:    FlagDataEndStream,
   120  				Length:   3,
   121  				StreamID: 1,
   122  			},
   123  		},
   124  
   125  		// Padded bit set, but no padding:
   126  		1: {
   127  			streamID:  1,
   128  			endStream: true,
   129  			data:      []byte("foo"),
   130  			pad:       []byte{},
   131  			wantHeader: FrameHeader{
   132  				Type:     FrameData,
   133  				Flags:    FlagDataEndStream | FlagDataPadded,
   134  				Length:   4,
   135  				StreamID: 1,
   136  			},
   137  		},
   138  
   139  		// Padded bit set, with padding:
   140  		2: {
   141  			streamID:  1,
   142  			endStream: false,
   143  			data:      []byte("foo"),
   144  			pad:       []byte{0, 0, 0},
   145  			wantHeader: FrameHeader{
   146  				Type:     FrameData,
   147  				Flags:    FlagDataPadded,
   148  				Length:   7,
   149  				StreamID: 1,
   150  			},
   151  		},
   152  	}
   153  	for i, tt := range tests {
   154  		fr, _ := testFramer()
   155  		fr.WriteDataPadded(tt.streamID, tt.endStream, tt.data, tt.pad)
   156  		f, err := fr.ReadFrame()
   157  		if err != nil {
   158  			t.Errorf("%d. ReadFrame: %v", i, err)
   159  			continue
   160  		}
   161  		got := f.Header()
   162  		tt.wantHeader.valid = true
   163  		if !got.Equal(tt.wantHeader) {
   164  			t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader)
   165  			continue
   166  		}
   167  		df := f.(*DataFrame)
   168  		if !bytes.Equal(df.Data(), tt.data) {
   169  			t.Errorf("%d. got %q; want %q", i, df.Data(), tt.data)
   170  		}
   171  	}
   172  }
   173  
   174  func (fh FrameHeader) Equal(b FrameHeader) bool {
   175  	return fh.valid == b.valid &&
   176  		fh.Type == b.Type &&
   177  		fh.Flags == b.Flags &&
   178  		fh.Length == b.Length &&
   179  		fh.StreamID == b.StreamID
   180  }
   181  
   182  func TestWriteHeaders(t *testing.T) {
   183  	tests := []struct {
   184  		name      string
   185  		p         HeadersFrameParam
   186  		wantEnc   string
   187  		wantFrame *HeadersFrame
   188  	}{
   189  		{
   190  			"basic",
   191  			HeadersFrameParam{
   192  				StreamID:      42,
   193  				BlockFragment: []byte("abc"),
   194  				Priority:      PriorityParam{},
   195  			},
   196  			"\x00\x00\x03\x01\x00\x00\x00\x00*abc",
   197  			&HeadersFrame{
   198  				FrameHeader: FrameHeader{
   199  					valid:    true,
   200  					StreamID: 42,
   201  					Type:     FrameHeaders,
   202  					Length:   uint32(len("abc")),
   203  				},
   204  				Priority:      PriorityParam{},
   205  				headerFragBuf: []byte("abc"),
   206  			},
   207  		},
   208  		{
   209  			"basic + end flags",
   210  			HeadersFrameParam{
   211  				StreamID:      42,
   212  				BlockFragment: []byte("abc"),
   213  				EndStream:     true,
   214  				EndHeaders:    true,
   215  				Priority:      PriorityParam{},
   216  			},
   217  			"\x00\x00\x03\x01\x05\x00\x00\x00*abc",
   218  			&HeadersFrame{
   219  				FrameHeader: FrameHeader{
   220  					valid:    true,
   221  					StreamID: 42,
   222  					Type:     FrameHeaders,
   223  					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders,
   224  					Length:   uint32(len("abc")),
   225  				},
   226  				Priority:      PriorityParam{},
   227  				headerFragBuf: []byte("abc"),
   228  			},
   229  		},
   230  		{
   231  			"with padding",
   232  			HeadersFrameParam{
   233  				StreamID:      42,
   234  				BlockFragment: []byte("abc"),
   235  				EndStream:     true,
   236  				EndHeaders:    true,
   237  				PadLength:     5,
   238  				Priority:      PriorityParam{},
   239  			},
   240  			"\x00\x00\t\x01\r\x00\x00\x00*\x05abc\x00\x00\x00\x00\x00",
   241  			&HeadersFrame{
   242  				FrameHeader: FrameHeader{
   243  					valid:    true,
   244  					StreamID: 42,
   245  					Type:     FrameHeaders,
   246  					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded,
   247  					Length:   uint32(1 + len("abc") + 5), // pad length + contents + padding
   248  				},
   249  				Priority:      PriorityParam{},
   250  				headerFragBuf: []byte("abc"),
   251  			},
   252  		},
   253  		{
   254  			"with priority",
   255  			HeadersFrameParam{
   256  				StreamID:      42,
   257  				BlockFragment: []byte("abc"),
   258  				EndStream:     true,
   259  				EndHeaders:    true,
   260  				PadLength:     2,
   261  				Priority: PriorityParam{
   262  					StreamDep: 15,
   263  					Exclusive: true,
   264  					Weight:    127,
   265  				},
   266  			},
   267  			"\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x0f\u007fabc\x00\x00",
   268  			&HeadersFrame{
   269  				FrameHeader: FrameHeader{
   270  					valid:    true,
   271  					StreamID: 42,
   272  					Type:     FrameHeaders,
   273  					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
   274  					Length:   uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
   275  				},
   276  				Priority: PriorityParam{
   277  					StreamDep: 15,
   278  					Exclusive: true,
   279  					Weight:    127,
   280  				},
   281  				headerFragBuf: []byte("abc"),
   282  			},
   283  		},
   284  		{
   285  			"with priority stream dep zero", // golang.org/issue/15444
   286  			HeadersFrameParam{
   287  				StreamID:      42,
   288  				BlockFragment: []byte("abc"),
   289  				EndStream:     true,
   290  				EndHeaders:    true,
   291  				PadLength:     2,
   292  				Priority: PriorityParam{
   293  					StreamDep: 0,
   294  					Exclusive: true,
   295  					Weight:    127,
   296  				},
   297  			},
   298  			"\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x00\u007fabc\x00\x00",
   299  			&HeadersFrame{
   300  				FrameHeader: FrameHeader{
   301  					valid:    true,
   302  					StreamID: 42,
   303  					Type:     FrameHeaders,
   304  					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
   305  					Length:   uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
   306  				},
   307  				Priority: PriorityParam{
   308  					StreamDep: 0,
   309  					Exclusive: true,
   310  					Weight:    127,
   311  				},
   312  				headerFragBuf: []byte("abc"),
   313  			},
   314  		},
   315  		{
   316  			"zero length",
   317  			HeadersFrameParam{
   318  				StreamID: 42,
   319  				Priority: PriorityParam{},
   320  			},
   321  			"\x00\x00\x00\x01\x00\x00\x00\x00*",
   322  			&HeadersFrame{
   323  				FrameHeader: FrameHeader{
   324  					valid:    true,
   325  					StreamID: 42,
   326  					Type:     FrameHeaders,
   327  					Length:   0,
   328  				},
   329  				Priority: PriorityParam{},
   330  			},
   331  		},
   332  	}
   333  	for _, tt := range tests {
   334  		fr, buf := testFramer()
   335  		if err := fr.WriteHeaders(tt.p); err != nil {
   336  			t.Errorf("test %q: %v", tt.name, err)
   337  			continue
   338  		}
   339  		if buf.String() != tt.wantEnc {
   340  			t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc)
   341  		}
   342  		f, err := fr.ReadFrame()
   343  		if err != nil {
   344  			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
   345  			continue
   346  		}
   347  		if !reflect.DeepEqual(f, tt.wantFrame) {
   348  			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
   349  		}
   350  	}
   351  }
   352  
   353  func TestWriteInvalidStreamDep(t *testing.T) {
   354  	fr, _ := testFramer()
   355  	err := fr.WriteHeaders(HeadersFrameParam{
   356  		StreamID: 42,
   357  		Priority: PriorityParam{
   358  			StreamDep: 1 << 31,
   359  		},
   360  	})
   361  	if err != errDepStreamID {
   362  		t.Errorf("header error = %v; want %q", err, errDepStreamID)
   363  	}
   364  
   365  	err = fr.WritePriority(2, PriorityParam{StreamDep: 1 << 31})
   366  	if err != errDepStreamID {
   367  		t.Errorf("priority error = %v; want %q", err, errDepStreamID)
   368  	}
   369  }
   370  
   371  func TestWriteContinuation(t *testing.T) {
   372  	const streamID = 42
   373  	tests := []struct {
   374  		name string
   375  		end  bool
   376  		frag []byte
   377  
   378  		wantFrame *ContinuationFrame
   379  	}{
   380  		{
   381  			"not end",
   382  			false,
   383  			[]byte("abc"),
   384  			&ContinuationFrame{
   385  				FrameHeader: FrameHeader{
   386  					valid:    true,
   387  					StreamID: streamID,
   388  					Type:     FrameContinuation,
   389  					Length:   uint32(len("abc")),
   390  				},
   391  				headerFragBuf: []byte("abc"),
   392  			},
   393  		},
   394  		{
   395  			"end",
   396  			true,
   397  			[]byte("def"),
   398  			&ContinuationFrame{
   399  				FrameHeader: FrameHeader{
   400  					valid:    true,
   401  					StreamID: streamID,
   402  					Type:     FrameContinuation,
   403  					Flags:    FlagContinuationEndHeaders,
   404  					Length:   uint32(len("def")),
   405  				},
   406  				headerFragBuf: []byte("def"),
   407  			},
   408  		},
   409  	}
   410  	for _, tt := range tests {
   411  		fr, _ := testFramer()
   412  		if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil {
   413  			t.Errorf("test %q: %v", tt.name, err)
   414  			continue
   415  		}
   416  		fr.AllowIllegalReads = true
   417  		f, err := fr.ReadFrame()
   418  		if err != nil {
   419  			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
   420  			continue
   421  		}
   422  		if !reflect.DeepEqual(f, tt.wantFrame) {
   423  			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
   424  		}
   425  	}
   426  }
   427  
   428  func TestParseRFC9218Priority(t *testing.T) {
   429  	tests := []struct {
   430  		name        string
   431  		priorityStr string
   432  		want        PriorityParam
   433  		wantOk      bool
   434  	}{
   435  		{
   436  			name:        "with urgency",
   437  			priorityStr: "u=0",
   438  			want: PriorityParam{
   439  				urgency:     0,
   440  				incremental: 0,
   441  			},
   442  			wantOk: true,
   443  		},
   444  		{
   445  			name:        "with implicit incremental",
   446  			priorityStr: "i",
   447  			want: PriorityParam{
   448  				urgency:     3,
   449  				incremental: 1,
   450  			},
   451  			wantOk: true,
   452  		},
   453  		{
   454  			name:        "with explicit incremental",
   455  			priorityStr: "i=?1",
   456  			want: PriorityParam{
   457  				urgency:     3,
   458  				incremental: 1,
   459  			},
   460  			wantOk: true,
   461  		},
   462  		{
   463  			name:        "with urgency and incremental",
   464  			priorityStr: "i=?0, u=4",
   465  			want: PriorityParam{
   466  				urgency:     4,
   467  				incremental: 0,
   468  			},
   469  			wantOk: true,
   470  		},
   471  		{
   472  			name:        "with other valid dictionary data",
   473  			priorityStr: "some=data;someparam;u=fake, u=1;foo, i;bar",
   474  			want: PriorityParam{
   475  				urgency:     1,
   476  				incremental: 1,
   477  			},
   478  			wantOk: true,
   479  		},
   480  		{
   481  			name:        "repeated field",
   482  			priorityStr: "u=1,i,u=5,i=?0",
   483  			want: PriorityParam{
   484  				urgency:     5,
   485  				incremental: 0,
   486  			},
   487  			wantOk: true,
   488  		},
   489  		{
   490  			name:        "wrong field type",
   491  			priorityStr: `u="urgency will be ignored", i`,
   492  			want: PriorityParam{
   493  				urgency:     3,
   494  				incremental: 1,
   495  			},
   496  			wantOk: true,
   497  		},
   498  		{
   499  			name:        "invalid dictionary",
   500  			priorityStr: `u=1,i, but this is not a valid dictionary"`,
   501  			want:        defaultRFC9218Priority(true),
   502  		},
   503  		{
   504  			name:        "out of range value",
   505  			priorityStr: "u=8",
   506  			want:        defaultRFC9218Priority(true),
   507  			wantOk:      true,
   508  		},
   509  	}
   510  	for _, tt := range tests {
   511  		got, gotOk := parseRFC9218Priority(tt.priorityStr, true)
   512  		if gotOk != tt.wantOk {
   513  			t.Errorf("test %q: mismatch.\n got ok: %#v\nwant ok: %#v\n", tt.name, got, tt.want)
   514  		}
   515  		if got != tt.want {
   516  			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, got, tt.want)
   517  		}
   518  	}
   519  }
   520  
   521  func TestWritePriority(t *testing.T) {
   522  	const streamID = 42
   523  	tests := []struct {
   524  		name      string
   525  		priority  PriorityParam
   526  		wantFrame *PriorityFrame
   527  	}{
   528  		{
   529  			"not exclusive",
   530  			PriorityParam{
   531  				StreamDep: 2,
   532  				Exclusive: false,
   533  				Weight:    127,
   534  			},
   535  			&PriorityFrame{
   536  				FrameHeader{
   537  					valid:    true,
   538  					StreamID: streamID,
   539  					Type:     FramePriority,
   540  					Length:   5,
   541  				},
   542  				PriorityParam{
   543  					StreamDep: 2,
   544  					Exclusive: false,
   545  					Weight:    127,
   546  				},
   547  			},
   548  		},
   549  
   550  		{
   551  			"exclusive",
   552  			PriorityParam{
   553  				StreamDep: 3,
   554  				Exclusive: true,
   555  				Weight:    77,
   556  			},
   557  			&PriorityFrame{
   558  				FrameHeader{
   559  					valid:    true,
   560  					StreamID: streamID,
   561  					Type:     FramePriority,
   562  					Length:   5,
   563  				},
   564  				PriorityParam{
   565  					StreamDep: 3,
   566  					Exclusive: true,
   567  					Weight:    77,
   568  				},
   569  			},
   570  		},
   571  	}
   572  	for _, tt := range tests {
   573  		fr, _ := testFramer()
   574  		if err := fr.WritePriority(streamID, tt.priority); err != nil {
   575  			t.Errorf("test %q: %v", tt.name, err)
   576  			continue
   577  		}
   578  		f, err := fr.ReadFrame()
   579  		if err != nil {
   580  			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
   581  			continue
   582  		}
   583  		if !reflect.DeepEqual(f, tt.wantFrame) {
   584  			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
   585  		}
   586  	}
   587  }
   588  
   589  func TestWritePriorityUpdate(t *testing.T) {
   590  	const streamID = 42
   591  	tests := []struct {
   592  		name      string
   593  		priority  string
   594  		wantFrame *PriorityUpdateFrame
   595  	}{
   596  		{
   597  			name:     "with urgency",
   598  			priority: "u=0",
   599  			wantFrame: &PriorityUpdateFrame{
   600  				FrameHeader: FrameHeader{
   601  					valid:    true,
   602  					StreamID: 0,
   603  					Type:     FramePriorityUpdate,
   604  					Length:   7,
   605  				},
   606  				Priority:            "u=0",
   607  				PrioritizedStreamID: streamID,
   608  			},
   609  		},
   610  		{
   611  			name:     "with incremental",
   612  			priority: "i",
   613  			wantFrame: &PriorityUpdateFrame{
   614  				FrameHeader: FrameHeader{
   615  					valid:    true,
   616  					StreamID: 0,
   617  					Type:     FramePriorityUpdate,
   618  					Length:   5,
   619  				},
   620  				Priority:            "i",
   621  				PrioritizedStreamID: streamID,
   622  			},
   623  		},
   624  		{
   625  			name:     "with urgency and incremental",
   626  			priority: "u=7,i",
   627  			wantFrame: &PriorityUpdateFrame{
   628  				FrameHeader: FrameHeader{
   629  					valid:    true,
   630  					StreamID: 0,
   631  					Type:     FramePriorityUpdate,
   632  					Length:   9,
   633  				},
   634  				Priority:            "u=7,i",
   635  				PrioritizedStreamID: streamID,
   636  			},
   637  		},
   638  		{
   639  			name:     "with other fields",
   640  			priority: "a=123,u=7,i,b;a;b",
   641  			wantFrame: &PriorityUpdateFrame{
   642  				FrameHeader: FrameHeader{
   643  					valid:    true,
   644  					StreamID: 0,
   645  					Type:     FramePriorityUpdate,
   646  					Length:   21,
   647  				},
   648  				Priority:            "a=123,u=7,i,b;a;b",
   649  				PrioritizedStreamID: streamID,
   650  			},
   651  		},
   652  		{
   653  			name:     "with string escapes",
   654  			priority: "u=\"invalid\" , i",
   655  			wantFrame: &PriorityUpdateFrame{
   656  				FrameHeader: FrameHeader{
   657  					valid:    true,
   658  					StreamID: 0,
   659  					Type:     FramePriorityUpdate,
   660  					Length:   19,
   661  				},
   662  				Priority:            "u=\"invalid\" , i",
   663  				PrioritizedStreamID: streamID,
   664  			},
   665  		},
   666  		{
   667  			name:     "with empty payload",
   668  			priority: "",
   669  			wantFrame: &PriorityUpdateFrame{
   670  				FrameHeader: FrameHeader{
   671  					valid:    true,
   672  					StreamID: 0,
   673  					Type:     FramePriorityUpdate,
   674  					Length:   4,
   675  				},
   676  				Priority:            "",
   677  				PrioritizedStreamID: streamID,
   678  			},
   679  		},
   680  	}
   681  	for _, tt := range tests {
   682  		fr, _ := testFramer()
   683  		if err := fr.WritePriorityUpdate(streamID, tt.priority); err != nil {
   684  			t.Errorf("test %q: %v", tt.name, err)
   685  			continue
   686  		}
   687  		f, err := fr.ReadFrame()
   688  		if err != nil {
   689  			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
   690  			continue
   691  		}
   692  		if !reflect.DeepEqual(f, tt.wantFrame) {
   693  			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
   694  		}
   695  	}
   696  }
   697  
   698  func TestWriteSettings(t *testing.T) {
   699  	fr, buf := testFramer()
   700  	settings := []Setting{{1, 2}, {3, 4}}
   701  	fr.WriteSettings(settings...)
   702  	const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
   703  	if buf.String() != wantEnc {
   704  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
   705  	}
   706  	f, err := fr.ReadFrame()
   707  	if err != nil {
   708  		t.Fatal(err)
   709  	}
   710  	sf, ok := f.(*SettingsFrame)
   711  	if !ok {
   712  		t.Fatalf("Got a %T; want a SettingsFrame", f)
   713  	}
   714  	var got []Setting
   715  	sf.ForeachSetting(func(s Setting) error {
   716  		got = append(got, s)
   717  		valBack, ok := sf.Value(s.ID)
   718  		if !ok || valBack != s.Val {
   719  			t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
   720  		}
   721  		return nil
   722  	})
   723  	if !reflect.DeepEqual(settings, got) {
   724  		t.Errorf("Read settings %+v != written settings %+v", got, settings)
   725  	}
   726  }
   727  
   728  func TestWriteSettingsAck(t *testing.T) {
   729  	fr, buf := testFramer()
   730  	fr.WriteSettingsAck()
   731  	const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
   732  	if buf.String() != wantEnc {
   733  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
   734  	}
   735  }
   736  
   737  func TestWriteWindowUpdate(t *testing.T) {
   738  	fr, buf := testFramer()
   739  	const streamID = 1<<24 + 2<<16 + 3<<8 + 4
   740  	const incr = 7<<24 + 6<<16 + 5<<8 + 4
   741  	if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
   742  		t.Fatal(err)
   743  	}
   744  	const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
   745  	if buf.String() != wantEnc {
   746  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
   747  	}
   748  	f, err := fr.ReadFrame()
   749  	if err != nil {
   750  		t.Fatal(err)
   751  	}
   752  	want := &WindowUpdateFrame{
   753  		FrameHeader: FrameHeader{
   754  			valid:    true,
   755  			Type:     0x8,
   756  			Flags:    0x0,
   757  			Length:   0x4,
   758  			StreamID: 0x1020304,
   759  		},
   760  		Increment: 0x7060504,
   761  	}
   762  	if !reflect.DeepEqual(f, want) {
   763  		t.Errorf("parsed back %#v; want %#v", f, want)
   764  	}
   765  }
   766  
   767  func TestWritePing(t *testing.T)    { testWritePing(t, false) }
   768  func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
   769  
   770  func testWritePing(t *testing.T, ack bool) {
   771  	fr, buf := testFramer()
   772  	if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
   773  		t.Fatal(err)
   774  	}
   775  	var wantFlags Flags
   776  	if ack {
   777  		wantFlags = FlagPingAck
   778  	}
   779  	var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
   780  	if buf.String() != wantEnc {
   781  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
   782  	}
   783  
   784  	f, err := fr.ReadFrame()
   785  	if err != nil {
   786  		t.Fatal(err)
   787  	}
   788  	want := &PingFrame{
   789  		FrameHeader: FrameHeader{
   790  			valid:    true,
   791  			Type:     0x6,
   792  			Flags:    wantFlags,
   793  			Length:   0x8,
   794  			StreamID: 0,
   795  		},
   796  		Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
   797  	}
   798  	if !reflect.DeepEqual(f, want) {
   799  		t.Errorf("parsed back %#v; want %#v", f, want)
   800  	}
   801  }
   802  
   803  func TestReadFrameHeader(t *testing.T) {
   804  	tests := []struct {
   805  		in   string
   806  		want FrameHeader
   807  	}{
   808  		{in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}},
   809  		{in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{
   810  			Length: 66051, Type: 4, Flags: 5, StreamID: 101124105,
   811  		}},
   812  		// Ignore high bit:
   813  		{in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{
   814  			Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
   815  		{in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{
   816  			Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
   817  	}
   818  	for i, tt := range tests {
   819  		got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in))
   820  		if err != nil {
   821  			t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err)
   822  			continue
   823  		}
   824  		tt.want.valid = true
   825  		if !got.Equal(tt.want) {
   826  			t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
   827  		}
   828  	}
   829  }
   830  
   831  func TestReadWriteFrameHeader(t *testing.T) {
   832  	tests := []struct {
   833  		len      uint32
   834  		typ      FrameType
   835  		flags    Flags
   836  		streamID uint32
   837  	}{
   838  		{len: 0, typ: 255, flags: 1, streamID: 0},
   839  		{len: 0, typ: 255, flags: 1, streamID: 1},
   840  		{len: 0, typ: 255, flags: 1, streamID: 255},
   841  		{len: 0, typ: 255, flags: 1, streamID: 256},
   842  		{len: 0, typ: 255, flags: 1, streamID: 65535},
   843  		{len: 0, typ: 255, flags: 1, streamID: 65536},
   844  
   845  		{len: 0, typ: 1, flags: 255, streamID: 1},
   846  		{len: 255, typ: 1, flags: 255, streamID: 1},
   847  		{len: 256, typ: 1, flags: 255, streamID: 1},
   848  		{len: 65535, typ: 1, flags: 255, streamID: 1},
   849  		{len: 65536, typ: 1, flags: 255, streamID: 1},
   850  		{len: 16777215, typ: 1, flags: 255, streamID: 1},
   851  	}
   852  	for _, tt := range tests {
   853  		fr, buf := testFramer()
   854  		fr.startWrite(tt.typ, tt.flags, tt.streamID)
   855  		fr.writeBytes(make([]byte, tt.len))
   856  		fr.endWrite()
   857  		fh, err := ReadFrameHeader(buf)
   858  		if err != nil {
   859  			t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
   860  			continue
   861  		}
   862  		if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
   863  			t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
   864  		}
   865  	}
   866  
   867  }
   868  
   869  func TestWriteTooLargeFrame(t *testing.T) {
   870  	fr, _ := testFramer()
   871  	fr.startWrite(0, 1, 1)
   872  	fr.writeBytes(make([]byte, 1<<24))
   873  	err := fr.endWrite()
   874  	if err != ErrFrameTooLarge {
   875  		t.Errorf("endWrite = %v; want errFrameTooLarge", err)
   876  	}
   877  }
   878  
   879  func TestWriteGoAway(t *testing.T) {
   880  	const debug = "foo"
   881  	fr, buf := testFramer()
   882  	if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
   883  		t.Fatal(err)
   884  	}
   885  	const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
   886  	if buf.String() != wantEnc {
   887  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
   888  	}
   889  	f, err := fr.ReadFrame()
   890  	if err != nil {
   891  		t.Fatal(err)
   892  	}
   893  	want := &GoAwayFrame{
   894  		FrameHeader: FrameHeader{
   895  			valid:    true,
   896  			Type:     0x7,
   897  			Flags:    0,
   898  			Length:   uint32(4 + 4 + len(debug)),
   899  			StreamID: 0,
   900  		},
   901  		LastStreamID: 0x01020304,
   902  		ErrCode:      0x05060708,
   903  		debugData:    []byte(debug),
   904  	}
   905  	if !reflect.DeepEqual(f, want) {
   906  		t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
   907  	}
   908  	if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
   909  		t.Errorf("debug data = %q; want %q", got, debug)
   910  	}
   911  }
   912  
   913  func TestWritePushPromise(t *testing.T) {
   914  	pp := PushPromiseParam{
   915  		StreamID:      42,
   916  		PromiseID:     42,
   917  		BlockFragment: []byte("abc"),
   918  	}
   919  	fr, buf := testFramer()
   920  	if err := fr.WritePushPromise(pp); err != nil {
   921  		t.Fatal(err)
   922  	}
   923  	const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
   924  	if buf.String() != wantEnc {
   925  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
   926  	}
   927  	f, err := fr.ReadFrame()
   928  	if err != nil {
   929  		t.Fatal(err)
   930  	}
   931  	_, ok := f.(*PushPromiseFrame)
   932  	if !ok {
   933  		t.Fatalf("got %T; want *PushPromiseFrame", f)
   934  	}
   935  	want := &PushPromiseFrame{
   936  		FrameHeader: FrameHeader{
   937  			valid:    true,
   938  			Type:     0x5,
   939  			Flags:    0x0,
   940  			Length:   0x7,
   941  			StreamID: 42,
   942  		},
   943  		PromiseID:     42,
   944  		headerFragBuf: []byte("abc"),
   945  	}
   946  	if !reflect.DeepEqual(f, want) {
   947  		t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
   948  	}
   949  }
   950  
   951  // test checkFrameOrder and that HEADERS and CONTINUATION frames can't be intermingled.
   952  func TestReadFrameOrder(t *testing.T) {
   953  	head := func(f *Framer, id uint32, end bool) {
   954  		f.WriteHeaders(HeadersFrameParam{
   955  			StreamID:      id,
   956  			BlockFragment: []byte("foo"), // unused, but non-empty
   957  			EndHeaders:    end,
   958  		})
   959  	}
   960  	cont := func(f *Framer, id uint32, end bool) {
   961  		f.WriteContinuation(id, end, []byte("foo"))
   962  	}
   963  
   964  	tests := [...]struct {
   965  		name    string
   966  		w       func(*Framer)
   967  		atLeast int
   968  		wantErr string
   969  	}{
   970  		0: {
   971  			w: func(f *Framer) {
   972  				head(f, 1, true)
   973  			},
   974  		},
   975  		1: {
   976  			w: func(f *Framer) {
   977  				head(f, 1, true)
   978  				head(f, 2, true)
   979  			},
   980  		},
   981  		2: {
   982  			wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
   983  			w: func(f *Framer) {
   984  				head(f, 1, false)
   985  				head(f, 2, true)
   986  			},
   987  		},
   988  		3: {
   989  			wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
   990  			w: func(f *Framer) {
   991  				head(f, 1, false)
   992  			},
   993  		},
   994  		4: {
   995  			w: func(f *Framer) {
   996  				head(f, 1, false)
   997  				cont(f, 1, true)
   998  				head(f, 2, true)
   999  			},
  1000  		},
  1001  		5: {
  1002  			wantErr: "got CONTINUATION for stream 2; expected stream 1",
  1003  			w: func(f *Framer) {
  1004  				head(f, 1, false)
  1005  				cont(f, 2, true)
  1006  				head(f, 2, true)
  1007  			},
  1008  		},
  1009  		6: {
  1010  			wantErr: "unexpected CONTINUATION for stream 1",
  1011  			w: func(f *Framer) {
  1012  				cont(f, 1, true)
  1013  			},
  1014  		},
  1015  		7: {
  1016  			wantErr: "unexpected CONTINUATION for stream 1",
  1017  			w: func(f *Framer) {
  1018  				cont(f, 1, false)
  1019  			},
  1020  		},
  1021  		8: {
  1022  			wantErr: "HEADERS frame with stream ID 0",
  1023  			w: func(f *Framer) {
  1024  				head(f, 0, true)
  1025  			},
  1026  		},
  1027  		9: {
  1028  			wantErr: "unexpected CONTINUATION for stream 0",
  1029  			w: func(f *Framer) {
  1030  				cont(f, 0, true)
  1031  			},
  1032  		},
  1033  		10: {
  1034  			wantErr: "unexpected CONTINUATION for stream 1",
  1035  			atLeast: 5,
  1036  			w: func(f *Framer) {
  1037  				head(f, 1, false)
  1038  				cont(f, 1, false)
  1039  				cont(f, 1, false)
  1040  				cont(f, 1, false)
  1041  				cont(f, 1, true)
  1042  				cont(f, 1, false)
  1043  			},
  1044  		},
  1045  	}
  1046  	for i, tt := range tests {
  1047  		buf := new(bytes.Buffer)
  1048  		f := NewFramer(buf, buf)
  1049  		f.AllowIllegalWrites = true
  1050  		tt.w(f)
  1051  		f.WriteData(1, true, nil) // to test transition away from last step
  1052  
  1053  		var err error
  1054  		n := 0
  1055  		var log bytes.Buffer
  1056  		for {
  1057  			var got Frame
  1058  			got, err = f.ReadFrame()
  1059  			fmt.Fprintf(&log, "  read %v, %v\n", got, err)
  1060  			if err != nil {
  1061  				break
  1062  			}
  1063  			n++
  1064  		}
  1065  		if err == io.EOF {
  1066  			err = nil
  1067  		}
  1068  		ok := tt.wantErr == ""
  1069  		if ok && err != nil {
  1070  			t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
  1071  			continue
  1072  		}
  1073  		if !ok && err != ConnectionError(ErrCodeProtocol) {
  1074  			t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
  1075  			continue
  1076  		}
  1077  		if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) {
  1078  			t.Errorf("%d. framer error = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes())
  1079  		}
  1080  		if n < tt.atLeast {
  1081  			t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
  1082  		}
  1083  	}
  1084  }
  1085  
  1086  func TestMetaFrameHeader(t *testing.T) {
  1087  	write := func(f *Framer, frags ...[]byte) {
  1088  		for i, frag := range frags {
  1089  			end := (i == len(frags)-1)
  1090  			if i == 0 {
  1091  				f.WriteHeaders(HeadersFrameParam{
  1092  					StreamID:      1,
  1093  					BlockFragment: frag,
  1094  					EndHeaders:    end,
  1095  				})
  1096  			} else {
  1097  				f.WriteContinuation(1, end, frag)
  1098  			}
  1099  		}
  1100  	}
  1101  
  1102  	want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame {
  1103  		mh := &MetaHeadersFrame{
  1104  			HeadersFrame: &HeadersFrame{
  1105  				FrameHeader: FrameHeader{
  1106  					Type:     FrameHeaders,
  1107  					Flags:    flags,
  1108  					Length:   length,
  1109  					StreamID: 1,
  1110  				},
  1111  			},
  1112  			Fields: []hpack.HeaderField(nil),
  1113  		}
  1114  		for len(pairs) > 0 {
  1115  			mh.Fields = append(mh.Fields, hpack.HeaderField{
  1116  				Name:  pairs[0],
  1117  				Value: pairs[1],
  1118  			})
  1119  			pairs = pairs[2:]
  1120  		}
  1121  		return mh
  1122  	}
  1123  	truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame {
  1124  		mh.Truncated = true
  1125  		return mh
  1126  	}
  1127  
  1128  	const noFlags Flags = 0
  1129  
  1130  	oneKBString := strings.Repeat("a", 1<<10)
  1131  
  1132  	// A Trailer declaration of 20 fields: ~250 bytes on the wire, but ~900
  1133  	// bytes by our accounting since we add 32 bytes for each entry in
  1134  	// Request.Trailer.
  1135  	var trailerNames []string
  1136  	for i := range 20 {
  1137  		trailerNames = append(trailerNames, fmt.Sprintf("x-trailer-%d", i))
  1138  	}
  1139  	trailerDecl := strings.Join(trailerNames, ",")
  1140  
  1141  	tests := [...]struct {
  1142  		name              string
  1143  		w                 func(*Framer)
  1144  		want              any // *MetaHeaderFrame or error
  1145  		wantErrReason     string
  1146  		maxHeaderListSize uint32
  1147  	}{
  1148  		0: {
  1149  			name: "single_headers",
  1150  			w: func(f *Framer) {
  1151  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/")
  1152  				write(f, all)
  1153  			},
  1154  			want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
  1155  		},
  1156  		1: {
  1157  			name: "with_continuation",
  1158  			w: func(f *Framer) {
  1159  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
  1160  				write(f, all[:1], all[1:])
  1161  			},
  1162  			want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
  1163  		},
  1164  		2: {
  1165  			name: "with_two_continuation",
  1166  			w: func(f *Framer) {
  1167  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
  1168  				write(f, all[:2], all[2:4], all[4:])
  1169  			},
  1170  			want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
  1171  		},
  1172  		3: {
  1173  			name: "big_string_okay",
  1174  			w: func(f *Framer) {
  1175  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
  1176  				write(f, all[:2], all[2:])
  1177  			},
  1178  			want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
  1179  		},
  1180  		4: {
  1181  			name: "big_string_error",
  1182  			w: func(f *Framer) {
  1183  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
  1184  				write(f, all[:2], all[2:])
  1185  			},
  1186  			maxHeaderListSize: (1 << 10) / 2,
  1187  			want:              ConnectionError(ErrCodeCompression),
  1188  		},
  1189  		5: {
  1190  			name: "max_header_list_truncated",
  1191  			w: func(f *Framer) {
  1192  				var pairs = []string{":method", "GET", ":path", "/"}
  1193  				for range 100 {
  1194  					pairs = append(pairs, "foo", "bar")
  1195  				}
  1196  				all := encodeHeaderRaw(t, pairs...)
  1197  				write(f, all[:2], all[2:])
  1198  			},
  1199  			maxHeaderListSize: (1 << 10) / 2,
  1200  			want: truncated(want(noFlags, 2,
  1201  				":method", "GET",
  1202  				":path", "/",
  1203  				"foo", "bar",
  1204  				"foo", "bar",
  1205  				"foo", "bar",
  1206  				"foo", "bar",
  1207  				"foo", "bar",
  1208  				"foo", "bar",
  1209  				"foo", "bar",
  1210  				"foo", "bar",
  1211  				"foo", "bar",
  1212  				"foo", "bar",
  1213  				"foo", "bar", // 11
  1214  			)),
  1215  		},
  1216  		6: {
  1217  			name: "pseudo_order",
  1218  			w: func(f *Framer) {
  1219  				write(f, encodeHeaderRaw(t,
  1220  					":method", "GET",
  1221  					"foo", "bar",
  1222  					":path", "/", // bogus
  1223  				))
  1224  			},
  1225  			want:          streamError(1, ErrCodeProtocol),
  1226  			wantErrReason: "pseudo header field after regular",
  1227  		},
  1228  		7: {
  1229  			name: "pseudo_unknown",
  1230  			w: func(f *Framer) {
  1231  				write(f, encodeHeaderRaw(t,
  1232  					":unknown", "foo", // bogus
  1233  					"foo", "bar",
  1234  				))
  1235  			},
  1236  			want:          streamError(1, ErrCodeProtocol),
  1237  			wantErrReason: "invalid pseudo-header \":unknown\"",
  1238  		},
  1239  		8: {
  1240  			name: "pseudo_mix_request_response",
  1241  			w: func(f *Framer) {
  1242  				write(f, encodeHeaderRaw(t,
  1243  					":method", "GET",
  1244  					":status", "100",
  1245  				))
  1246  			},
  1247  			want:          streamError(1, ErrCodeProtocol),
  1248  			wantErrReason: "mix of request and response pseudo headers",
  1249  		},
  1250  		9: {
  1251  			name: "pseudo_dup",
  1252  			w: func(f *Framer) {
  1253  				write(f, encodeHeaderRaw(t,
  1254  					":method", "GET",
  1255  					":method", "POST",
  1256  				))
  1257  			},
  1258  			want:          streamError(1, ErrCodeProtocol),
  1259  			wantErrReason: "duplicate pseudo-header \":method\"",
  1260  		},
  1261  		10: {
  1262  			name: "trailer_okay_no_pseudo",
  1263  			w:    func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
  1264  			want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
  1265  		},
  1266  		11: {
  1267  			name:          "invalid_field_name",
  1268  			w:             func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
  1269  			want:          streamError(1, ErrCodeProtocol),
  1270  			wantErrReason: "invalid header field name \"CapitalBad\"",
  1271  		},
  1272  		12: {
  1273  			name:          "invalid_field_value",
  1274  			w:             func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
  1275  			want:          streamError(1, ErrCodeProtocol),
  1276  			wantErrReason: `invalid header field value for "key"`,
  1277  		},
  1278  		13: {
  1279  			name: "trailer_declaration_okay",
  1280  			w: func(f *Framer) {
  1281  				write(f, encodeHeaderRaw(t, ":method", "GET", ":path", "/", "trailer", trailerDecl))
  1282  			},
  1283  			maxHeaderListSize: 1024,
  1284  			want: want(FlagHeadersEndHeaders, 193,
  1285  				":method", "GET",
  1286  				":path", "/",
  1287  				"trailer", trailerDecl,
  1288  			),
  1289  		},
  1290  		14: {
  1291  			name: "trailer_declaration_truncated",
  1292  			w: func(f *Framer) {
  1293  				write(f, encodeHeaderRaw(t, ":method", "GET", ":path", "/", "trailer", trailerDecl))
  1294  			},
  1295  			maxHeaderListSize: 512,
  1296  			want: truncated(want(FlagHeadersEndHeaders, 193,
  1297  				":method", "GET",
  1298  				":path", "/",
  1299  			)),
  1300  		},
  1301  	}
  1302  	for i, tt := range tests {
  1303  		buf := new(bytes.Buffer)
  1304  		f := NewFramer(buf, buf)
  1305  		f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
  1306  		f.MaxHeaderListSize = tt.maxHeaderListSize
  1307  		tt.w(f)
  1308  
  1309  		name := tt.name
  1310  		if name == "" {
  1311  			name = fmt.Sprintf("test index %d", i)
  1312  		}
  1313  
  1314  		var got any
  1315  		var err error
  1316  		got, err = f.ReadFrame()
  1317  		if err != nil {
  1318  			got = err
  1319  
  1320  			// Ignore the StreamError.Cause field, if it matches the wantErrReason.
  1321  			// The test table above predates the Cause field.
  1322  			if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
  1323  				se.Cause = nil
  1324  				got = se
  1325  			}
  1326  		}
  1327  		if !reflect.DeepEqual(got, tt.want) {
  1328  			if mhg, ok := got.(*MetaHeadersFrame); ok {
  1329  				if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
  1330  					hg := mhg.HeadersFrame
  1331  					hw := mhw.HeadersFrame
  1332  					if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
  1333  						t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
  1334  					}
  1335  				}
  1336  			}
  1337  			str := func(v any) string {
  1338  				if _, ok := v.(error); ok {
  1339  					return fmt.Sprintf("error %v", v)
  1340  				} else {
  1341  					return fmt.Sprintf("value %#v", v)
  1342  				}
  1343  			}
  1344  			t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
  1345  		}
  1346  		if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
  1347  			t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
  1348  		}
  1349  	}
  1350  }
  1351  
  1352  func TestSetReuseFrames(t *testing.T) {
  1353  	fr, buf := testFramer()
  1354  	fr.SetReuseFrames()
  1355  
  1356  	// Check that DataFrames are reused. Note that
  1357  	// SetReuseFrames only currently implements reuse of DataFrames.
  1358  	firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
  1359  
  1360  	for range 10 {
  1361  		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
  1362  		if df != firstDf {
  1363  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1364  		}
  1365  	}
  1366  
  1367  	for range 10 {
  1368  		df := readAndVerifyDataFrame("", 0, fr, buf, t)
  1369  		if df != firstDf {
  1370  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1371  		}
  1372  	}
  1373  
  1374  	for range 10 {
  1375  		df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
  1376  		if df != firstDf {
  1377  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1378  		}
  1379  	}
  1380  }
  1381  
  1382  func TestSetReuseFramesMoreThanOnce(t *testing.T) {
  1383  	fr, buf := testFramer()
  1384  	fr.SetReuseFrames()
  1385  
  1386  	firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
  1387  	fr.SetReuseFrames()
  1388  
  1389  	for range 10 {
  1390  		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
  1391  		// SetReuseFrames should be idempotent
  1392  		fr.SetReuseFrames()
  1393  		if df != firstDf {
  1394  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1395  		}
  1396  	}
  1397  }
  1398  
  1399  func TestNoSetReuseFrames(t *testing.T) {
  1400  	fr, buf := testFramer()
  1401  	const numNewDataFrames = 10
  1402  	dfSoFar := make([]any, numNewDataFrames)
  1403  
  1404  	// Check that DataFrames are not reused if SetReuseFrames wasn't called.
  1405  	// SetReuseFrames only currently implements reuse of DataFrames.
  1406  	for i := range numNewDataFrames {
  1407  		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
  1408  		for _, item := range dfSoFar {
  1409  			if df == item {
  1410  				t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
  1411  			}
  1412  		}
  1413  		dfSoFar[i] = df
  1414  	}
  1415  }
  1416  
  1417  func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
  1418  	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
  1419  	fr.WriteData(streamID, true, []byte(data))
  1420  	wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
  1421  	if buf.String() != wantEnc {
  1422  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  1423  	}
  1424  	f, err := fr.ReadFrame()
  1425  	if err != nil {
  1426  		t.Fatal(err)
  1427  	}
  1428  	df, ok := f.(*DataFrame)
  1429  	if !ok {
  1430  		t.Fatalf("got %T; want *DataFrame", f)
  1431  	}
  1432  	if !bytes.Equal(df.Data(), []byte(data)) {
  1433  		t.Errorf("got %q; want %q", df.Data(), []byte(data))
  1434  	}
  1435  	if f.Header().Flags&1 == 0 {
  1436  		t.Errorf("didn't see END_STREAM flag")
  1437  	}
  1438  	return df
  1439  }
  1440  
  1441  func encodeHeaderRaw(t testing.TB, headers ...string) []byte {
  1442  	var buf bytes.Buffer
  1443  	enc := hpack.NewEncoder(&buf)
  1444  	for len(headers) > 0 {
  1445  		k, v := headers[0], headers[1]
  1446  		err := enc.WriteField(hpack.HeaderField{Name: k, Value: v})
  1447  		if err != nil {
  1448  			t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
  1449  		}
  1450  		headers = headers[2:]
  1451  	}
  1452  	return buf.Bytes()
  1453  }
  1454  
  1455  func TestSettingsDuplicates(t *testing.T) {
  1456  	tests := []struct {
  1457  		settings []Setting
  1458  		want     bool
  1459  	}{
  1460  		{nil, false},
  1461  		{[]Setting{{ID: 1}}, false},
  1462  		{[]Setting{{ID: 1}, {ID: 2}}, false},
  1463  		{[]Setting{{ID: 1}, {ID: 2}}, false},
  1464  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
  1465  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
  1466  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}}, false},
  1467  
  1468  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 2}}, true},
  1469  		{[]Setting{{ID: 4}, {ID: 2}, {ID: 3}, {ID: 4}}, true},
  1470  
  1471  		{[]Setting{
  1472  			{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
  1473  			{ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
  1474  			{ID: 9}, {ID: 10}, {ID: 11}, {ID: 12},
  1475  		}, false},
  1476  
  1477  		{[]Setting{
  1478  			{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
  1479  			{ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
  1480  			{ID: 9}, {ID: 10}, {ID: 11}, {ID: 11},
  1481  		}, true},
  1482  	}
  1483  	for i, tt := range tests {
  1484  		fr, _ := testFramer()
  1485  		fr.WriteSettings(tt.settings...)
  1486  		f, err := fr.ReadFrame()
  1487  		if err != nil {
  1488  			t.Fatalf("%d. ReadFrame: %v", i, err)
  1489  		}
  1490  		sf := f.(*SettingsFrame)
  1491  		got := sf.HasDuplicates()
  1492  		if got != tt.want {
  1493  			t.Errorf("%d. HasDuplicates = %v; want %v", i, got, tt.want)
  1494  		}
  1495  	}
  1496  
  1497  }
  1498  
  1499  func TestTypeFrameParser(t *testing.T) {
  1500  	if len(frameNames) != len(frameParsers) {
  1501  		t.Errorf("expected len(frameNames)=%d to equal len(frameParsers)=%d",
  1502  			len(frameNames), len(frameParsers))
  1503  	}
  1504  
  1505  	// typeFrameParser() for an unknown type returns a function that returns UnknownFrame
  1506  	unknownFrameType := FrameType(FramePriorityUpdate + 1)
  1507  	unknownParser := typeFrameParser(unknownFrameType)
  1508  	frame, err := unknownParser(nil, FrameHeader{}, nil, nil)
  1509  	if err != nil {
  1510  		t.Errorf("unknownParser() must not return an error: %v", err)
  1511  	}
  1512  	if _, isUnknown := frame.(*UnknownFrame); !isUnknown {
  1513  		t.Errorf("expected UnknownFrame, got %T", frame)
  1514  	}
  1515  }
  1516  
  1517  func TestReadFrameHeaderAndBody(t *testing.T) {
  1518  	fr, _ := testFramer()
  1519  	var streamID uint32 = 1
  1520  	data := []byte("ABC")
  1521  	if err := fr.WriteData(streamID, true, data); err != nil {
  1522  		t.Fatalf("WriteData(%d, true, %q) failed: %v", streamID, data, err)
  1523  	}
  1524  
  1525  	fh, err := fr.ReadFrameHeader()
  1526  	if err != nil {
  1527  		t.Fatalf("ReadFrameHeader failed: %v", err)
  1528  	}
  1529  	wantHeader := FrameHeader{
  1530  		Type:     FrameData,
  1531  		Flags:    FlagDataEndStream,
  1532  		Length:   3,
  1533  		StreamID: 1,
  1534  		valid:    true,
  1535  	}
  1536  	if !fh.Equal(wantHeader) {
  1537  		t.Fatalf("ReadFrameHeader = %+v; want %+v", fh, wantHeader)
  1538  	}
  1539  
  1540  	f, err := fr.ReadFrameForHeader(fh)
  1541  	if err != nil {
  1542  		t.Fatalf("ReadFrameForHeader failed: %v", err)
  1543  	}
  1544  
  1545  	if !fh.Equal(f.Header()) {
  1546  		t.Fatalf("Frame.Header() = %+v; want %+v", f.Header(), fh)
  1547  	}
  1548  
  1549  	df, ok := f.(*DataFrame)
  1550  	if !ok {
  1551  		t.Fatalf("got %T; want *DataFrame", f)
  1552  	}
  1553  	if got, want := df.Data(), data; !bytes.Equal(got, want) {
  1554  		t.Errorf("DataFrame.Data() = %q; want %q", string(got), string(want))
  1555  	}
  1556  	if got, want := df.StreamEnded(), true; got != want {
  1557  		t.Errorf("DataFrame.StreamEnded() = %v; want %v", got, want)
  1558  	}
  1559  }
  1560  
  1561  func TestReadFrameHeaderFrameTooLarge(t *testing.T) {
  1562  	fr, _ := testFramer()
  1563  	fr.SetMaxReadFrameSize(2)
  1564  	if err := fr.WriteData(1, true, []byte("ABC")); err != nil {
  1565  		t.Fatalf("WriteData failed: %v", err)
  1566  	}
  1567  	fh, err := fr.ReadFrameHeader()
  1568  	if gotErr, wantErr := err, ErrFrameTooLarge; gotErr != wantErr {
  1569  		t.Fatalf("ReadFrameHeader returned error %v; want %v", gotErr, wantErr)
  1570  	}
  1571  	if fh.StreamID != 1 {
  1572  		t.Errorf("ReadFrameHeader = %v, %v; want StreamID 1", fh, err)
  1573  	}
  1574  }
  1575  
  1576  func TestReadFrameHeaderBadFrameOrder(t *testing.T) {
  1577  	fr, _ := testFramer()
  1578  	if err := fr.WriteHeaders(HeadersFrameParam{
  1579  		StreamID:      1,
  1580  		BlockFragment: []byte("foo"), // unused, but non-empty
  1581  		EndHeaders:    false,
  1582  	}); err != nil {
  1583  		t.Fatalf("WriteHeaders failed: %v", err)
  1584  	}
  1585  
  1586  	// Write a CONTINUATION frame for stream 2 without first finishing the headers for stream 1.
  1587  	if err := fr.WriteContinuation(2, true, []byte("foo")); err != nil {
  1588  		t.Fatalf("WriteContinuation failed: %v", err)
  1589  	}
  1590  
  1591  	fh, err := fr.ReadFrameHeader()
  1592  	if err != nil {
  1593  		t.Fatalf("ReadFrameHeader failed: %v", err)
  1594  	}
  1595  	if _, err = fr.ReadFrameForHeader(fh); err != nil {
  1596  		t.Fatalf("ReadFrameForHeader failed: %v", err)
  1597  	}
  1598  
  1599  	if _, err := fr.ReadFrameHeader(); err != ConnectionError(ErrCodeProtocol) {
  1600  		t.Fatalf("ReadFrameHeader returned error %v; want ConnectionError(ErrCodeProtocol)", err)
  1601  	}
  1602  }
  1603  
  1604  func TestReadFrameForHeaderUnexpectedEOF(t *testing.T) {
  1605  	fr, b := testFramer()
  1606  	if err := fr.WriteData(1, true, []byte("ABC")); err != nil {
  1607  		t.Fatalf("WriteData failed: %v", err)
  1608  	}
  1609  
  1610  	fh, err := fr.ReadFrameHeader()
  1611  	if err != nil {
  1612  		t.Fatalf("ReadFrameHeader failed: %v", err)
  1613  	}
  1614  
  1615  	// Remove one byte from the body, corrupting the frame body.
  1616  	b.Truncate(b.Len() - 1)
  1617  
  1618  	_, err = fr.ReadFrameForHeader(fh)
  1619  	if err != io.ErrUnexpectedEOF {
  1620  		t.Fatalf("ReadFrameForHeader with short body = %v; want io.ErrUnexpectedEOF", err)
  1621  	}
  1622  }
  1623  
  1624  func TestTypeFrameParserHolePanic(t *testing.T) {
  1625  	// Verify that unassigned frame types (0x0a-0x0f) don't panic. golang.org/issue/77652
  1626  	fr, _ := testFramer()
  1627  	if err := fr.WriteRawFrame(FrameType(0x0a), 0, 1, nil); err != nil {
  1628  		t.Fatal(err)
  1629  	}
  1630  
  1631  	f, err := fr.ReadFrame()
  1632  	if err != nil {
  1633  		t.Fatal(err)
  1634  	}
  1635  
  1636  	if _, ok := f.(*UnknownFrame); !ok {
  1637  		t.Errorf("got %T; want *UnknownFrame", f)
  1638  	}
  1639  }
  1640  

View as plain text