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 5package http2 6 7import ( 8 "fmt" 9 "math" 10 "reflect" 11 "testing" 12) 13 14func makeWriteNonStreamRequest() FrameWriteRequest { 15 return FrameWriteRequest{writeSettingsAck{}, nil, nil} 16} 17 18func makeWriteHeadersRequest(streamID uint32) FrameWriteRequest { 19 st := &stream{id: streamID} 20 return FrameWriteRequest{&writeResHeaders{streamID: streamID, httpResCode: 200}, st, nil} 21} 22 23func makeHandlerPanicRST(streamID uint32) FrameWriteRequest { 24 st := &stream{id: streamID} 25 return FrameWriteRequest{&handlerPanicRST{StreamID: streamID}, st, nil} 26} 27 28func checkConsume(wr FrameWriteRequest, nbytes int32, want []FrameWriteRequest) error { 29 consumed, rest, n := wr.Consume(nbytes) 30 var wantConsumed, wantRest FrameWriteRequest 31 switch len(want) { 32 case 0: 33 case 1: 34 wantConsumed = want[0] 35 case 2: 36 wantConsumed = want[0] 37 wantRest = want[1] 38 } 39 if !reflect.DeepEqual(consumed, wantConsumed) || !reflect.DeepEqual(rest, wantRest) || n != len(want) { 40 return fmt.Errorf("got %v, %v, %v\nwant %v, %v, %v", consumed, rest, n, wantConsumed, wantRest, len(want)) 41 } 42 return nil 43} 44 45func TestFrameWriteRequestNonData(t *testing.T) { 46 wr := makeWriteNonStreamRequest() 47 if got, want := wr.DataSize(), 0; got != want { 48 t.Errorf("DataSize: got %v, want %v", got, want) 49 } 50 51 // Non-DATA frames are always consumed whole. 52 if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil { 53 t.Errorf("Consume:\n%v", err) 54 } 55} 56 57func TestFrameWriteRequestData(t *testing.T) { 58 st := &stream{ 59 id: 1, 60 sc: &serverConn{maxFrameSize: 16}, 61 } 62 const size = 32 63 wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)} 64 if got, want := wr.DataSize(), size; got != want { 65 t.Errorf("DataSize: got %v, want %v", got, want) 66 } 67 68 // No flow-control bytes available: cannot consume anything. 69 if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil { 70 t.Errorf("Consume(limited by flow control):\n%v", err) 71 } 72 73 // Add enough flow-control bytes to consume the entire frame, 74 // but we're now restricted by st.sc.maxFrameSize. 75 st.flow.add(size) 76 want := []FrameWriteRequest{ 77 { 78 write: &writeData{st.id, make([]byte, st.sc.maxFrameSize), false}, 79 stream: st, 80 done: nil, 81 }, 82 { 83 write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize), true}, 84 stream: st, 85 done: wr.done, 86 }, 87 } 88 if err := checkConsume(wr, math.MaxInt32, want); err != nil { 89 t.Errorf("Consume(limited by maxFrameSize):\n%v", err) 90 } 91 rest := want[1] 92 93 // Consume 8 bytes from the remaining frame. 94 want = []FrameWriteRequest{ 95 { 96 write: &writeData{st.id, make([]byte, 8), false}, 97 stream: st, 98 done: nil, 99 }, 100 { 101 write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true}, 102 stream: st, 103 done: wr.done, 104 }, 105 } 106 if err := checkConsume(rest, 8, want); err != nil { 107 t.Errorf("Consume(8):\n%v", err) 108 } 109 rest = want[1] 110 111 // Consume all remaining bytes. 112 want = []FrameWriteRequest{ 113 { 114 write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true}, 115 stream: st, 116 done: wr.done, 117 }, 118 } 119 if err := checkConsume(rest, math.MaxInt32, want); err != nil { 120 t.Errorf("Consume(remainder):\n%v", err) 121 } 122} 123 124func TestFrameWriteRequest_StreamID(t *testing.T) { 125 const streamID = 123 126 wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)} 127 if got := wr.StreamID(); got != streamID { 128 t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID) 129 } 130} 131