golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/http2/writesched_test.go (about) 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 const size = 32 80 wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)} 81 if got, want := wr.DataSize(), size; got != want { 82 t.Errorf("DataSize: got %v, want %v", got, want) 83 } 84 85 // No flow-control bytes available: cannot consume anything. 86 if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil { 87 t.Errorf("Consume(limited by flow control):\n%v", err) 88 } 89 90 wr = makeWriteNonStreamRequest() 91 if got, want := wr.DataSize(), 0; got != want { 92 t.Errorf("DataSize: got %v, want %v", got, want) 93 } 94 95 // Non-DATA frames are always consumed whole. 96 if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil { 97 t.Errorf("Consume:\n%v", err) 98 } 99 100 wr = makeWriteRSTStream(1) 101 if got, want := wr.DataSize(), 0; got != want { 102 t.Errorf("DataSize: got %v, want %v", got, want) 103 } 104 105 // RST_STREAM frames are always consumed whole. 106 if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil { 107 t.Errorf("Consume:\n%v", err) 108 } 109 } 110 111 func TestFrameWriteRequestData(t *testing.T) { 112 st := &stream{ 113 id: 1, 114 sc: &serverConn{maxFrameSize: 16}, 115 } 116 const size = 32 117 wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)} 118 if got, want := wr.DataSize(), size; got != want { 119 t.Errorf("DataSize: got %v, want %v", got, want) 120 } 121 122 // No flow-control bytes available: cannot consume anything. 123 if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil { 124 t.Errorf("Consume(limited by flow control):\n%v", err) 125 } 126 127 // Add enough flow-control bytes to consume the entire frame, 128 // but we're now restricted by st.sc.maxFrameSize. 129 st.flow.add(size) 130 want := []FrameWriteRequest{ 131 { 132 write: &writeData{st.id, make([]byte, st.sc.maxFrameSize), false}, 133 stream: st, 134 done: nil, 135 }, 136 { 137 write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize), true}, 138 stream: st, 139 done: wr.done, 140 }, 141 } 142 if err := checkConsume(wr, math.MaxInt32, want); err != nil { 143 t.Errorf("Consume(limited by maxFrameSize):\n%v", err) 144 } 145 rest := want[1] 146 147 // Consume 8 bytes from the remaining frame. 148 want = []FrameWriteRequest{ 149 { 150 write: &writeData{st.id, make([]byte, 8), false}, 151 stream: st, 152 done: nil, 153 }, 154 { 155 write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true}, 156 stream: st, 157 done: wr.done, 158 }, 159 } 160 if err := checkConsume(rest, 8, want); err != nil { 161 t.Errorf("Consume(8):\n%v", err) 162 } 163 rest = want[1] 164 165 // Consume all remaining bytes. 166 want = []FrameWriteRequest{ 167 { 168 write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true}, 169 stream: st, 170 done: wr.done, 171 }, 172 } 173 if err := checkConsume(rest, math.MaxInt32, want); err != nil { 174 t.Errorf("Consume(remainder):\n%v", err) 175 } 176 } 177 178 func TestFrameWriteRequest_StreamID(t *testing.T) { 179 const streamID = 123 180 wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)} 181 if got := wr.StreamID(); got != streamID { 182 t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID) 183 } 184 }