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  	tests := [...]struct {
  1133  		name              string
  1134  		w                 func(*Framer)
  1135  		want              interface{} // *MetaHeaderFrame or error
  1136  		wantErrReason     string
  1137  		maxHeaderListSize uint32
  1138  	}{
  1139  		0: {
  1140  			name: "single_headers",
  1141  			w: func(f *Framer) {
  1142  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/")
  1143  				write(f, all)
  1144  			},
  1145  			want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
  1146  		},
  1147  		1: {
  1148  			name: "with_continuation",
  1149  			w: func(f *Framer) {
  1150  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
  1151  				write(f, all[:1], all[1:])
  1152  			},
  1153  			want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
  1154  		},
  1155  		2: {
  1156  			name: "with_two_continuation",
  1157  			w: func(f *Framer) {
  1158  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
  1159  				write(f, all[:2], all[2:4], all[4:])
  1160  			},
  1161  			want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
  1162  		},
  1163  		3: {
  1164  			name: "big_string_okay",
  1165  			w: func(f *Framer) {
  1166  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
  1167  				write(f, all[:2], all[2:])
  1168  			},
  1169  			want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
  1170  		},
  1171  		4: {
  1172  			name: "big_string_error",
  1173  			w: func(f *Framer) {
  1174  				all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
  1175  				write(f, all[:2], all[2:])
  1176  			},
  1177  			maxHeaderListSize: (1 << 10) / 2,
  1178  			want:              ConnectionError(ErrCodeCompression),
  1179  		},
  1180  		5: {
  1181  			name: "max_header_list_truncated",
  1182  			w: func(f *Framer) {
  1183  				var pairs = []string{":method", "GET", ":path", "/"}
  1184  				for i := 0; i < 100; i++ {
  1185  					pairs = append(pairs, "foo", "bar")
  1186  				}
  1187  				all := encodeHeaderRaw(t, pairs...)
  1188  				write(f, all[:2], all[2:])
  1189  			},
  1190  			maxHeaderListSize: (1 << 10) / 2,
  1191  			want: truncated(want(noFlags, 2,
  1192  				":method", "GET",
  1193  				":path", "/",
  1194  				"foo", "bar",
  1195  				"foo", "bar",
  1196  				"foo", "bar",
  1197  				"foo", "bar",
  1198  				"foo", "bar",
  1199  				"foo", "bar",
  1200  				"foo", "bar",
  1201  				"foo", "bar",
  1202  				"foo", "bar",
  1203  				"foo", "bar",
  1204  				"foo", "bar", // 11
  1205  			)),
  1206  		},
  1207  		6: {
  1208  			name: "pseudo_order",
  1209  			w: func(f *Framer) {
  1210  				write(f, encodeHeaderRaw(t,
  1211  					":method", "GET",
  1212  					"foo", "bar",
  1213  					":path", "/", // bogus
  1214  				))
  1215  			},
  1216  			want:          streamError(1, ErrCodeProtocol),
  1217  			wantErrReason: "pseudo header field after regular",
  1218  		},
  1219  		7: {
  1220  			name: "pseudo_unknown",
  1221  			w: func(f *Framer) {
  1222  				write(f, encodeHeaderRaw(t,
  1223  					":unknown", "foo", // bogus
  1224  					"foo", "bar",
  1225  				))
  1226  			},
  1227  			want:          streamError(1, ErrCodeProtocol),
  1228  			wantErrReason: "invalid pseudo-header \":unknown\"",
  1229  		},
  1230  		8: {
  1231  			name: "pseudo_mix_request_response",
  1232  			w: func(f *Framer) {
  1233  				write(f, encodeHeaderRaw(t,
  1234  					":method", "GET",
  1235  					":status", "100",
  1236  				))
  1237  			},
  1238  			want:          streamError(1, ErrCodeProtocol),
  1239  			wantErrReason: "mix of request and response pseudo headers",
  1240  		},
  1241  		9: {
  1242  			name: "pseudo_dup",
  1243  			w: func(f *Framer) {
  1244  				write(f, encodeHeaderRaw(t,
  1245  					":method", "GET",
  1246  					":method", "POST",
  1247  				))
  1248  			},
  1249  			want:          streamError(1, ErrCodeProtocol),
  1250  			wantErrReason: "duplicate pseudo-header \":method\"",
  1251  		},
  1252  		10: {
  1253  			name: "trailer_okay_no_pseudo",
  1254  			w:    func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
  1255  			want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
  1256  		},
  1257  		11: {
  1258  			name:          "invalid_field_name",
  1259  			w:             func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
  1260  			want:          streamError(1, ErrCodeProtocol),
  1261  			wantErrReason: "invalid header field name \"CapitalBad\"",
  1262  		},
  1263  		12: {
  1264  			name:          "invalid_field_value",
  1265  			w:             func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
  1266  			want:          streamError(1, ErrCodeProtocol),
  1267  			wantErrReason: `invalid header field value for "key"`,
  1268  		},
  1269  	}
  1270  	for i, tt := range tests {
  1271  		buf := new(bytes.Buffer)
  1272  		f := NewFramer(buf, buf)
  1273  		f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
  1274  		f.MaxHeaderListSize = tt.maxHeaderListSize
  1275  		tt.w(f)
  1276  
  1277  		name := tt.name
  1278  		if name == "" {
  1279  			name = fmt.Sprintf("test index %d", i)
  1280  		}
  1281  
  1282  		var got interface{}
  1283  		var err error
  1284  		got, err = f.ReadFrame()
  1285  		if err != nil {
  1286  			got = err
  1287  
  1288  			// Ignore the StreamError.Cause field, if it matches the wantErrReason.
  1289  			// The test table above predates the Cause field.
  1290  			if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
  1291  				se.Cause = nil
  1292  				got = se
  1293  			}
  1294  		}
  1295  		if !reflect.DeepEqual(got, tt.want) {
  1296  			if mhg, ok := got.(*MetaHeadersFrame); ok {
  1297  				if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
  1298  					hg := mhg.HeadersFrame
  1299  					hw := mhw.HeadersFrame
  1300  					if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
  1301  						t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
  1302  					}
  1303  				}
  1304  			}
  1305  			str := func(v interface{}) string {
  1306  				if _, ok := v.(error); ok {
  1307  					return fmt.Sprintf("error %v", v)
  1308  				} else {
  1309  					return fmt.Sprintf("value %#v", v)
  1310  				}
  1311  			}
  1312  			t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
  1313  		}
  1314  		if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
  1315  			t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
  1316  		}
  1317  	}
  1318  }
  1319  
  1320  func TestSetReuseFrames(t *testing.T) {
  1321  	fr, buf := testFramer()
  1322  	fr.SetReuseFrames()
  1323  
  1324  	// Check that DataFrames are reused. Note that
  1325  	// SetReuseFrames only currently implements reuse of DataFrames.
  1326  	firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
  1327  
  1328  	for i := 0; i < 10; i++ {
  1329  		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
  1330  		if df != firstDf {
  1331  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1332  		}
  1333  	}
  1334  
  1335  	for i := 0; i < 10; i++ {
  1336  		df := readAndVerifyDataFrame("", 0, fr, buf, t)
  1337  		if df != firstDf {
  1338  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1339  		}
  1340  	}
  1341  
  1342  	for i := 0; i < 10; i++ {
  1343  		df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
  1344  		if df != firstDf {
  1345  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1346  		}
  1347  	}
  1348  }
  1349  
  1350  func TestSetReuseFramesMoreThanOnce(t *testing.T) {
  1351  	fr, buf := testFramer()
  1352  	fr.SetReuseFrames()
  1353  
  1354  	firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
  1355  	fr.SetReuseFrames()
  1356  
  1357  	for i := 0; i < 10; i++ {
  1358  		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
  1359  		// SetReuseFrames should be idempotent
  1360  		fr.SetReuseFrames()
  1361  		if df != firstDf {
  1362  			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
  1363  		}
  1364  	}
  1365  }
  1366  
  1367  func TestNoSetReuseFrames(t *testing.T) {
  1368  	fr, buf := testFramer()
  1369  	const numNewDataFrames = 10
  1370  	dfSoFar := make([]interface{}, numNewDataFrames)
  1371  
  1372  	// Check that DataFrames are not reused if SetReuseFrames wasn't called.
  1373  	// SetReuseFrames only currently implements reuse of DataFrames.
  1374  	for i := 0; i < numNewDataFrames; i++ {
  1375  		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
  1376  		for _, item := range dfSoFar {
  1377  			if df == item {
  1378  				t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
  1379  			}
  1380  		}
  1381  		dfSoFar[i] = df
  1382  	}
  1383  }
  1384  
  1385  func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
  1386  	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
  1387  	fr.WriteData(streamID, true, []byte(data))
  1388  	wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
  1389  	if buf.String() != wantEnc {
  1390  		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  1391  	}
  1392  	f, err := fr.ReadFrame()
  1393  	if err != nil {
  1394  		t.Fatal(err)
  1395  	}
  1396  	df, ok := f.(*DataFrame)
  1397  	if !ok {
  1398  		t.Fatalf("got %T; want *DataFrame", f)
  1399  	}
  1400  	if !bytes.Equal(df.Data(), []byte(data)) {
  1401  		t.Errorf("got %q; want %q", df.Data(), []byte(data))
  1402  	}
  1403  	if f.Header().Flags&1 == 0 {
  1404  		t.Errorf("didn't see END_STREAM flag")
  1405  	}
  1406  	return df
  1407  }
  1408  
  1409  func encodeHeaderRaw(t testing.TB, headers ...string) []byte {
  1410  	var buf bytes.Buffer
  1411  	enc := hpack.NewEncoder(&buf)
  1412  	for len(headers) > 0 {
  1413  		k, v := headers[0], headers[1]
  1414  		err := enc.WriteField(hpack.HeaderField{Name: k, Value: v})
  1415  		if err != nil {
  1416  			t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
  1417  		}
  1418  		headers = headers[2:]
  1419  	}
  1420  	return buf.Bytes()
  1421  }
  1422  
  1423  func TestSettingsDuplicates(t *testing.T) {
  1424  	tests := []struct {
  1425  		settings []Setting
  1426  		want     bool
  1427  	}{
  1428  		{nil, false},
  1429  		{[]Setting{{ID: 1}}, false},
  1430  		{[]Setting{{ID: 1}, {ID: 2}}, false},
  1431  		{[]Setting{{ID: 1}, {ID: 2}}, false},
  1432  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
  1433  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
  1434  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}}, false},
  1435  
  1436  		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 2}}, true},
  1437  		{[]Setting{{ID: 4}, {ID: 2}, {ID: 3}, {ID: 4}}, true},
  1438  
  1439  		{[]Setting{
  1440  			{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
  1441  			{ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
  1442  			{ID: 9}, {ID: 10}, {ID: 11}, {ID: 12},
  1443  		}, false},
  1444  
  1445  		{[]Setting{
  1446  			{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
  1447  			{ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
  1448  			{ID: 9}, {ID: 10}, {ID: 11}, {ID: 11},
  1449  		}, true},
  1450  	}
  1451  	for i, tt := range tests {
  1452  		fr, _ := testFramer()
  1453  		fr.WriteSettings(tt.settings...)
  1454  		f, err := fr.ReadFrame()
  1455  		if err != nil {
  1456  			t.Fatalf("%d. ReadFrame: %v", i, err)
  1457  		}
  1458  		sf := f.(*SettingsFrame)
  1459  		got := sf.HasDuplicates()
  1460  		if got != tt.want {
  1461  			t.Errorf("%d. HasDuplicates = %v; want %v", i, got, tt.want)
  1462  		}
  1463  	}
  1464  
  1465  }
  1466  
  1467  func TestTypeFrameParser(t *testing.T) {
  1468  	if len(frameNames) != len(frameParsers) {
  1469  		t.Errorf("expected len(frameNames)=%d to equal len(frameParsers)=%d",
  1470  			len(frameNames), len(frameParsers))
  1471  	}
  1472  
  1473  	// typeFrameParser() for an unknown type returns a function that returns UnknownFrame
  1474  	unknownFrameType := FrameType(FramePriorityUpdate + 1)
  1475  	unknownParser := typeFrameParser(unknownFrameType)
  1476  	frame, err := unknownParser(nil, FrameHeader{}, nil, nil)
  1477  	if err != nil {
  1478  		t.Errorf("unknownParser() must not return an error: %v", err)
  1479  	}
  1480  	if _, isUnknown := frame.(*UnknownFrame); !isUnknown {
  1481  		t.Errorf("expected UnknownFrame, got %T", frame)
  1482  	}
  1483  }
  1484  
  1485  func TestReadFrameHeaderAndBody(t *testing.T) {
  1486  	fr, _ := testFramer()
  1487  	var streamID uint32 = 1
  1488  	data := []byte("ABC")
  1489  	if err := fr.WriteData(streamID, true, data); err != nil {
  1490  		t.Fatalf("WriteData(%d, true, %q) failed: %v", streamID, data, err)
  1491  	}
  1492  
  1493  	fh, err := fr.ReadFrameHeader()
  1494  	if err != nil {
  1495  		t.Fatalf("ReadFrameHeader failed: %v", err)
  1496  	}
  1497  	wantHeader := FrameHeader{
  1498  		Type:     FrameData,
  1499  		Flags:    FlagDataEndStream,
  1500  		Length:   3,
  1501  		StreamID: 1,
  1502  		valid:    true,
  1503  	}
  1504  	if !fh.Equal(wantHeader) {
  1505  		t.Fatalf("ReadFrameHeader = %+v; want %+v", fh, wantHeader)
  1506  	}
  1507  
  1508  	f, err := fr.ReadFrameForHeader(fh)
  1509  	if err != nil {
  1510  		t.Fatalf("ReadFrameForHeader failed: %v", err)
  1511  	}
  1512  
  1513  	if !fh.Equal(f.Header()) {
  1514  		t.Fatalf("Frame.Header() = %+v; want %+v", f.Header(), fh)
  1515  	}
  1516  
  1517  	df, ok := f.(*DataFrame)
  1518  	if !ok {
  1519  		t.Fatalf("got %T; want *DataFrame", f)
  1520  	}
  1521  	if got, want := df.Data(), data; !bytes.Equal(got, want) {
  1522  		t.Errorf("DataFrame.Data() = %q; want %q", string(got), string(want))
  1523  	}
  1524  	if got, want := df.StreamEnded(), true; got != want {
  1525  		t.Errorf("DataFrame.StreamEnded() = %v; want %v", got, want)
  1526  	}
  1527  }
  1528  
  1529  func TestReadFrameHeaderFrameTooLarge(t *testing.T) {
  1530  	fr, _ := testFramer()
  1531  	fr.SetMaxReadFrameSize(2)
  1532  	if err := fr.WriteData(1, true, []byte("ABC")); err != nil {
  1533  		t.Fatalf("WriteData failed: %v", err)
  1534  	}
  1535  	fh, err := fr.ReadFrameHeader()
  1536  	if gotErr, wantErr := err, ErrFrameTooLarge; gotErr != wantErr {
  1537  		t.Fatalf("ReadFrameHeader returned error %v; want %v", gotErr, wantErr)
  1538  	}
  1539  	if fh.StreamID != 1 {
  1540  		t.Errorf("ReadFrameHeader = %v, %v; want StreamID 1", fh, err)
  1541  	}
  1542  }
  1543  
  1544  func TestReadFrameHeaderBadFrameOrder(t *testing.T) {
  1545  	fr, _ := testFramer()
  1546  	if err := fr.WriteHeaders(HeadersFrameParam{
  1547  		StreamID:      1,
  1548  		BlockFragment: []byte("foo"), // unused, but non-empty
  1549  		EndHeaders:    false,
  1550  	}); err != nil {
  1551  		t.Fatalf("WriteHeaders failed: %v", err)
  1552  	}
  1553  
  1554  	// Write a CONTINUATION frame for stream 2 without first finishing the headers for stream 1.
  1555  	if err := fr.WriteContinuation(2, true, []byte("foo")); err != nil {
  1556  		t.Fatalf("WriteContinuation failed: %v", err)
  1557  	}
  1558  
  1559  	fh, err := fr.ReadFrameHeader()
  1560  	if err != nil {
  1561  		t.Fatalf("ReadFrameHeader failed: %v", err)
  1562  	}
  1563  	if _, err = fr.ReadFrameForHeader(fh); err != nil {
  1564  		t.Fatalf("ReadFrameForHeader failed: %v", err)
  1565  	}
  1566  
  1567  	if _, err := fr.ReadFrameHeader(); err != ConnectionError(ErrCodeProtocol) {
  1568  		t.Fatalf("ReadFrameHeader returned error %v; want ConnectionError(ErrCodeProtocol)", err)
  1569  	}
  1570  }
  1571  
  1572  func TestReadFrameForHeaderUnexpectedEOF(t *testing.T) {
  1573  	fr, b := testFramer()
  1574  	if err := fr.WriteData(1, true, []byte("ABC")); err != nil {
  1575  		t.Fatalf("WriteData failed: %v", err)
  1576  	}
  1577  
  1578  	fh, err := fr.ReadFrameHeader()
  1579  	if err != nil {
  1580  		t.Fatalf("ReadFrameHeader failed: %v", err)
  1581  	}
  1582  
  1583  	// Remove one byte from the body, corrupting the frame body.
  1584  	b.Truncate(b.Len() - 1)
  1585  
  1586  	_, err = fr.ReadFrameForHeader(fh)
  1587  	if err != io.ErrUnexpectedEOF {
  1588  		t.Fatalf("ReadFrameForHeader with short body = %v; want io.ErrUnexpectedEOF", err)
  1589  	}
  1590  }
  1591  
  1592  func TestTypeFrameParserHolePanic(t *testing.T) {
  1593  	// Verify that unassigned frame types (0x0a-0x0f) don't panic. golang.org/issue/77652
  1594  	fr, _ := testFramer()
  1595  	if err := fr.WriteRawFrame(FrameType(0x0a), 0, 1, nil); err != nil {
  1596  		t.Fatal(err)
  1597  	}
  1598  
  1599  	f, err := fr.ReadFrame()
  1600  	if err != nil {
  1601  		t.Fatal(err)
  1602  	}
  1603  
  1604  	if _, ok := f.(*UnknownFrame); !ok {
  1605  		t.Errorf("got %T; want *UnknownFrame", f)
  1606  	}
  1607  }
  1608  

View as plain text