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

     1  // Copyright 2016 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  	"fmt"
     9  	"math"
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  func makeWriteNonStreamRequest() FrameWriteRequest {
    15  	return FrameWriteRequest{writeSettingsAck{}, nil, nil}
    16  }
    17  
    18  func makeWriteHeadersRequest(streamID uint32) FrameWriteRequest {
    19  	st := &stream{id: streamID}
    20  	return FrameWriteRequest{&writeResHeaders{streamID: streamID, httpResCode: 200}, st, nil}
    21  }
    22  
    23  func makeHandlerPanicRST(streamID uint32) FrameWriteRequest {
    24  	st := &stream{id: streamID}
    25  	return FrameWriteRequest{&handlerPanicRST{StreamID: streamID}, st, nil}
    26  }
    27  
    28  func makeWriteRSTStream(streamID uint32) FrameWriteRequest {
    29  	return FrameWriteRequest{write: streamError(streamID, ErrCodeInternal)}
    30  }
    31  
    32  func checkConsume(wr FrameWriteRequest, nbytes int32, want []FrameWriteRequest) error {
    33  	consumed, rest, n := wr.Consume(nbytes)
    34  	var wantConsumed, wantRest FrameWriteRequest
    35  	switch len(want) {
    36  	case 0:
    37  	case 1:
    38  		wantConsumed = want[0]
    39  	case 2:
    40  		wantConsumed = want[0]
    41  		wantRest = want[1]
    42  	}
    43  	if !reflect.DeepEqual(consumed, wantConsumed) || !reflect.DeepEqual(rest, wantRest) || n != len(want) {
    44  		return fmt.Errorf("got %v, %v, %v\nwant %v, %v, %v", consumed, rest, n, wantConsumed, wantRest, len(want))
    45  	}
    46  	return nil
    47  }
    48  
    49  func TestFrameWriteRequestNonData(t *testing.T) {
    50  	wr := makeWriteNonStreamRequest()
    51  	if got, want := wr.DataSize(), 0; got != want {
    52  		t.Errorf("DataSize: got %v, want %v", got, want)
    53  	}
    54  
    55  	// Non-DATA frames are always consumed whole.
    56  	if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil {
    57  		t.Errorf("Consume:\n%v", err)
    58  	}
    59  
    60  	wr = makeWriteRSTStream(123)
    61  	if got, want := wr.DataSize(), 0; got != want {
    62  		t.Errorf("DataSize: got %v, want %v", got, want)
    63  	}
    64  
    65  	// RST_STREAM frames are always consumed whole.
    66  	if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil {
    67  		t.Errorf("Consume:\n%v", err)
    68  	}
    69  }
    70  
    71  // #49741 RST_STREAM and Control frames should have more priority than data
    72  // frames to avoid blocking streams caused by clients not able to drain the
    73  // queue.
    74  func TestFrameWriteRequestWithData(t *testing.T) {
    75  	st := &stream{
    76  		id: 1,
    77  		sc: &serverConn{maxFrameSize: 16},
    78  	}
    79  	st.flow.conn = &connOutflow{}
    80  	const size = 32
    81  	wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)}
    82  	if got, want := wr.DataSize(), size; got != want {
    83  		t.Errorf("DataSize: got %v, want %v", got, want)
    84  	}
    85  
    86  	// No flow-control bytes available: cannot consume anything.
    87  	if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil {
    88  		t.Errorf("Consume(limited by flow control):\n%v", err)
    89  	}
    90  
    91  	wr = makeWriteNonStreamRequest()
    92  	if got, want := wr.DataSize(), 0; got != want {
    93  		t.Errorf("DataSize: got %v, want %v", got, want)
    94  	}
    95  
    96  	// Non-DATA frames are always consumed whole.
    97  	if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil {
    98  		t.Errorf("Consume:\n%v", err)
    99  	}
   100  
   101  	wr = makeWriteRSTStream(1)
   102  	if got, want := wr.DataSize(), 0; got != want {
   103  		t.Errorf("DataSize: got %v, want %v", got, want)
   104  	}
   105  
   106  	// RST_STREAM frames are always consumed whole.
   107  	if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil {
   108  		t.Errorf("Consume:\n%v", err)
   109  	}
   110  }
   111  
   112  func TestFrameWriteRequestData(t *testing.T) {
   113  	st := &stream{
   114  		id: 1,
   115  		sc: &serverConn{maxFrameSize: 16},
   116  	}
   117  	st.flow.conn = &connOutflow{}
   118  	st.flow.conn.add(maxFlowWindow) // conn-level flow is large
   119  	const size = 32
   120  	wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)}
   121  	if got, want := wr.DataSize(), size; got != want {
   122  		t.Errorf("DataSize: got %v, want %v", got, want)
   123  	}
   124  
   125  	// No flow-control bytes available: cannot consume anything.
   126  	if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil {
   127  		t.Errorf("Consume(limited by flow control):\n%v", err)
   128  	}
   129  
   130  	// Add enough flow-control bytes to consume the entire frame,
   131  	// but we're now restricted by st.sc.maxFrameSize.
   132  	st.flow.add(size)
   133  	want := []FrameWriteRequest{
   134  		{
   135  			write:  &writeData{st.id, make([]byte, st.sc.maxFrameSize), false},
   136  			stream: st,
   137  			done:   nil,
   138  		},
   139  		{
   140  			write:  &writeData{st.id, make([]byte, size-st.sc.maxFrameSize), true},
   141  			stream: st,
   142  			done:   wr.done,
   143  		},
   144  	}
   145  	if err := checkConsume(wr, math.MaxInt32, want); err != nil {
   146  		t.Errorf("Consume(limited by maxFrameSize):\n%v", err)
   147  	}
   148  	rest := want[1]
   149  
   150  	// Consume 8 bytes from the remaining frame.
   151  	want = []FrameWriteRequest{
   152  		{
   153  			write:  &writeData{st.id, make([]byte, 8), false},
   154  			stream: st,
   155  			done:   nil,
   156  		},
   157  		{
   158  			write:  &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true},
   159  			stream: st,
   160  			done:   wr.done,
   161  		},
   162  	}
   163  	if err := checkConsume(rest, 8, want); err != nil {
   164  		t.Errorf("Consume(8):\n%v", err)
   165  	}
   166  	rest = want[1]
   167  
   168  	// Consume all remaining bytes.
   169  	want = []FrameWriteRequest{
   170  		{
   171  			write:  &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true},
   172  			stream: st,
   173  			done:   wr.done,
   174  		},
   175  	}
   176  	if err := checkConsume(rest, math.MaxInt32, want); err != nil {
   177  		t.Errorf("Consume(remainder):\n%v", err)
   178  	}
   179  }
   180  
   181  func TestFrameWriteRequest_StreamID(t *testing.T) {
   182  	const streamID = 123
   183  	wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)}
   184  	if got := wr.StreamID(); got != streamID {
   185  		t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID)
   186  	}
   187  }
   188  

View as plain text