You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

281 lines
7.1 KiB

  1. /*
  2. * Copyright 2016 gRPC authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package test
  17. import (
  18. "bytes"
  19. "errors"
  20. "io"
  21. "strings"
  22. "testing"
  23. "time"
  24. "golang.org/x/net/http2"
  25. "golang.org/x/net/http2/hpack"
  26. )
  27. // This is a subset of http2's serverTester type.
  28. //
  29. // serverTester wraps a io.ReadWriter (acting like the underlying
  30. // network connection) and provides utility methods to read and write
  31. // http2 frames.
  32. //
  33. // NOTE(bradfitz): this could eventually be exported somewhere. Others
  34. // have asked for it too. For now I'm still experimenting with the
  35. // API and don't feel like maintaining a stable testing API.
  36. type serverTester struct {
  37. cc io.ReadWriteCloser // client conn
  38. t testing.TB
  39. fr *http2.Framer
  40. // writing headers:
  41. headerBuf bytes.Buffer
  42. hpackEnc *hpack.Encoder
  43. // reading frames:
  44. frc chan http2.Frame
  45. frErrc chan error
  46. readTimer *time.Timer
  47. }
  48. func newServerTesterFromConn(t testing.TB, cc io.ReadWriteCloser) *serverTester {
  49. st := &serverTester{
  50. t: t,
  51. cc: cc,
  52. frc: make(chan http2.Frame, 1),
  53. frErrc: make(chan error, 1),
  54. }
  55. st.hpackEnc = hpack.NewEncoder(&st.headerBuf)
  56. st.fr = http2.NewFramer(cc, cc)
  57. st.fr.ReadMetaHeaders = hpack.NewDecoder(4096 /*initialHeaderTableSize*/, nil)
  58. return st
  59. }
  60. func (st *serverTester) readFrame() (http2.Frame, error) {
  61. go func() {
  62. fr, err := st.fr.ReadFrame()
  63. if err != nil {
  64. st.frErrc <- err
  65. } else {
  66. st.frc <- fr
  67. }
  68. }()
  69. t := time.NewTimer(2 * time.Second)
  70. defer t.Stop()
  71. select {
  72. case f := <-st.frc:
  73. return f, nil
  74. case err := <-st.frErrc:
  75. return nil, err
  76. case <-t.C:
  77. return nil, errors.New("timeout waiting for frame")
  78. }
  79. }
  80. // greet initiates the client's HTTP/2 connection into a state where
  81. // frames may be sent.
  82. func (st *serverTester) greet() {
  83. st.writePreface()
  84. st.writeInitialSettings()
  85. st.wantSettings()
  86. st.writeSettingsAck()
  87. for {
  88. f, err := st.readFrame()
  89. if err != nil {
  90. st.t.Fatal(err)
  91. }
  92. switch f := f.(type) {
  93. case *http2.WindowUpdateFrame:
  94. // grpc's transport/http2_server sends this
  95. // before the settings ack. The Go http2
  96. // server uses a setting instead.
  97. case *http2.SettingsFrame:
  98. if f.IsAck() {
  99. return
  100. }
  101. st.t.Fatalf("during greet, got non-ACK settings frame")
  102. default:
  103. st.t.Fatalf("during greet, unexpected frame type %T", f)
  104. }
  105. }
  106. }
  107. func (st *serverTester) writePreface() {
  108. n, err := st.cc.Write([]byte(http2.ClientPreface))
  109. if err != nil {
  110. st.t.Fatalf("Error writing client preface: %v", err)
  111. }
  112. if n != len(http2.ClientPreface) {
  113. st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(http2.ClientPreface))
  114. }
  115. }
  116. func (st *serverTester) writeInitialSettings() {
  117. if err := st.fr.WriteSettings(); err != nil {
  118. st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err)
  119. }
  120. }
  121. func (st *serverTester) writeSettingsAck() {
  122. if err := st.fr.WriteSettingsAck(); err != nil {
  123. st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err)
  124. }
  125. }
  126. func (st *serverTester) wantSettings() *http2.SettingsFrame {
  127. f, err := st.readFrame()
  128. if err != nil {
  129. st.t.Fatalf("Error while expecting a SETTINGS frame: %v", err)
  130. }
  131. sf, ok := f.(*http2.SettingsFrame)
  132. if !ok {
  133. st.t.Fatalf("got a %T; want *SettingsFrame", f)
  134. }
  135. return sf
  136. }
  137. func (st *serverTester) wantSettingsAck() {
  138. f, err := st.readFrame()
  139. if err != nil {
  140. st.t.Fatal(err)
  141. }
  142. sf, ok := f.(*http2.SettingsFrame)
  143. if !ok {
  144. st.t.Fatalf("Wanting a settings ACK, received a %T", f)
  145. }
  146. if !sf.IsAck() {
  147. st.t.Fatal("Settings Frame didn't have ACK set")
  148. }
  149. }
  150. // wait for any activity from the server
  151. func (st *serverTester) wantAnyFrame() http2.Frame {
  152. f, err := st.fr.ReadFrame()
  153. if err != nil {
  154. st.t.Fatal(err)
  155. }
  156. return f
  157. }
  158. func (st *serverTester) encodeHeaderField(k, v string) {
  159. err := st.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v})
  160. if err != nil {
  161. st.t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
  162. }
  163. }
  164. // encodeHeader encodes headers and returns their HPACK bytes. headers
  165. // must contain an even number of key/value pairs. There may be
  166. // multiple pairs for keys (e.g. "cookie"). The :method, :path, and
  167. // :scheme headers default to GET, / and https.
  168. func (st *serverTester) encodeHeader(headers ...string) []byte {
  169. if len(headers)%2 == 1 {
  170. panic("odd number of kv args")
  171. }
  172. st.headerBuf.Reset()
  173. if len(headers) == 0 {
  174. // Fast path, mostly for benchmarks, so test code doesn't pollute
  175. // profiles when we're looking to improve server allocations.
  176. st.encodeHeaderField(":method", "GET")
  177. st.encodeHeaderField(":path", "/")
  178. st.encodeHeaderField(":scheme", "https")
  179. return st.headerBuf.Bytes()
  180. }
  181. if len(headers) == 2 && headers[0] == ":method" {
  182. // Another fast path for benchmarks.
  183. st.encodeHeaderField(":method", headers[1])
  184. st.encodeHeaderField(":path", "/")
  185. st.encodeHeaderField(":scheme", "https")
  186. return st.headerBuf.Bytes()
  187. }
  188. pseudoCount := map[string]int{}
  189. keys := []string{":method", ":path", ":scheme"}
  190. vals := map[string][]string{
  191. ":method": {"GET"},
  192. ":path": {"/"},
  193. ":scheme": {"https"},
  194. }
  195. for len(headers) > 0 {
  196. k, v := headers[0], headers[1]
  197. headers = headers[2:]
  198. if _, ok := vals[k]; !ok {
  199. keys = append(keys, k)
  200. }
  201. if strings.HasPrefix(k, ":") {
  202. pseudoCount[k]++
  203. if pseudoCount[k] == 1 {
  204. vals[k] = []string{v}
  205. } else {
  206. // Allows testing of invalid headers w/ dup pseudo fields.
  207. vals[k] = append(vals[k], v)
  208. }
  209. } else {
  210. vals[k] = append(vals[k], v)
  211. }
  212. }
  213. for _, k := range keys {
  214. for _, v := range vals[k] {
  215. st.encodeHeaderField(k, v)
  216. }
  217. }
  218. return st.headerBuf.Bytes()
  219. }
  220. func (st *serverTester) writeHeadersGRPC(streamID uint32, path string) {
  221. st.writeHeaders(http2.HeadersFrameParam{
  222. StreamID: streamID,
  223. BlockFragment: st.encodeHeader(
  224. ":method", "POST",
  225. ":path", path,
  226. "content-type", "application/grpc",
  227. "te", "trailers",
  228. ),
  229. EndStream: false,
  230. EndHeaders: true,
  231. })
  232. }
  233. func (st *serverTester) writeHeaders(p http2.HeadersFrameParam) {
  234. if err := st.fr.WriteHeaders(p); err != nil {
  235. st.t.Fatalf("Error writing HEADERS: %v", err)
  236. }
  237. }
  238. func (st *serverTester) writeData(streamID uint32, endStream bool, data []byte) {
  239. if err := st.fr.WriteData(streamID, endStream, data); err != nil {
  240. st.t.Fatalf("Error writing DATA: %v", err)
  241. }
  242. }
  243. func (st *serverTester) writeRSTStream(streamID uint32, code http2.ErrCode) {
  244. if err := st.fr.WriteRSTStream(streamID, code); err != nil {
  245. st.t.Fatalf("Error writing RST_STREAM: %v", err)
  246. }
  247. }
  248. func (st *serverTester) writeDataPadded(streamID uint32, endStream bool, data, padding []byte) {
  249. if err := st.fr.WriteDataPadded(streamID, endStream, data, padding); err != nil {
  250. st.t.Fatalf("Error writing DATA with padding: %v", err)
  251. }
  252. }