spdy_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. // Copyright 2011 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. package spdy
  5. import (
  6. "bytes"
  7. "compress/zlib"
  8. "encoding/base64"
  9. "io"
  10. "io/ioutil"
  11. "net/http"
  12. "reflect"
  13. "testing"
  14. )
  15. func TestHeaderParsing(t *testing.T) {
  16. headers := http.Header{
  17. "Url": []string{"http://www.google.com/"},
  18. "Method": []string{"get"},
  19. "Version": []string{"http/1.1"},
  20. }
  21. var headerValueBlockBuf bytes.Buffer
  22. writeHeaderValueBlock(&headerValueBlockBuf, headers)
  23. const bogusStreamId = 1
  24. newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
  25. if err != nil {
  26. t.Fatal("parseHeaderValueBlock:", err)
  27. }
  28. if !reflect.DeepEqual(headers, newHeaders) {
  29. t.Fatal("got: ", newHeaders, "\nwant: ", headers)
  30. }
  31. }
  32. func TestCreateParseSynStreamFrame(t *testing.T) {
  33. buffer := new(bytes.Buffer)
  34. framer := &Framer{
  35. headerCompressionDisabled: true,
  36. w: buffer,
  37. headerBuf: new(bytes.Buffer),
  38. r: buffer,
  39. }
  40. synStreamFrame := SynStreamFrame{
  41. CFHeader: ControlFrameHeader{
  42. version: Version,
  43. frameType: TypeSynStream,
  44. },
  45. StreamId: 2,
  46. Headers: http.Header{
  47. "Url": []string{"http://www.google.com/"},
  48. "Method": []string{"get"},
  49. "Version": []string{"http/1.1"},
  50. },
  51. }
  52. if err := framer.WriteFrame(&synStreamFrame); err != nil {
  53. t.Fatal("WriteFrame without compression:", err)
  54. }
  55. frame, err := framer.ReadFrame()
  56. if err != nil {
  57. t.Fatal("ReadFrame without compression:", err)
  58. }
  59. parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
  60. if !ok {
  61. t.Fatal("Parsed incorrect frame type:", frame)
  62. }
  63. if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
  64. t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
  65. }
  66. // Test again with compression
  67. buffer.Reset()
  68. framer, err = NewFramer(buffer, buffer)
  69. if err != nil {
  70. t.Fatal("Failed to create new framer:", err)
  71. }
  72. if err := framer.WriteFrame(&synStreamFrame); err != nil {
  73. t.Fatal("WriteFrame with compression:", err)
  74. }
  75. frame, err = framer.ReadFrame()
  76. if err != nil {
  77. t.Fatal("ReadFrame with compression:", err)
  78. }
  79. parsedSynStreamFrame, ok = frame.(*SynStreamFrame)
  80. if !ok {
  81. t.Fatal("Parsed incorrect frame type:", frame)
  82. }
  83. if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
  84. t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
  85. }
  86. }
  87. func TestCreateParseSynReplyFrame(t *testing.T) {
  88. buffer := new(bytes.Buffer)
  89. framer := &Framer{
  90. headerCompressionDisabled: true,
  91. w: buffer,
  92. headerBuf: new(bytes.Buffer),
  93. r: buffer,
  94. }
  95. synReplyFrame := SynReplyFrame{
  96. CFHeader: ControlFrameHeader{
  97. version: Version,
  98. frameType: TypeSynReply,
  99. },
  100. StreamId: 2,
  101. Headers: http.Header{
  102. "Url": []string{"http://www.google.com/"},
  103. "Method": []string{"get"},
  104. "Version": []string{"http/1.1"},
  105. },
  106. }
  107. if err := framer.WriteFrame(&synReplyFrame); err != nil {
  108. t.Fatal("WriteFrame without compression:", err)
  109. }
  110. frame, err := framer.ReadFrame()
  111. if err != nil {
  112. t.Fatal("ReadFrame without compression:", err)
  113. }
  114. parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
  115. if !ok {
  116. t.Fatal("Parsed incorrect frame type:", frame)
  117. }
  118. if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
  119. t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
  120. }
  121. // Test again with compression
  122. buffer.Reset()
  123. framer, err = NewFramer(buffer, buffer)
  124. if err != nil {
  125. t.Fatal("Failed to create new framer:", err)
  126. }
  127. if err := framer.WriteFrame(&synReplyFrame); err != nil {
  128. t.Fatal("WriteFrame with compression:", err)
  129. }
  130. frame, err = framer.ReadFrame()
  131. if err != nil {
  132. t.Fatal("ReadFrame with compression:", err)
  133. }
  134. parsedSynReplyFrame, ok = frame.(*SynReplyFrame)
  135. if !ok {
  136. t.Fatal("Parsed incorrect frame type:", frame)
  137. }
  138. if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
  139. t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
  140. }
  141. }
  142. func TestCreateParseRstStream(t *testing.T) {
  143. buffer := new(bytes.Buffer)
  144. framer, err := NewFramer(buffer, buffer)
  145. if err != nil {
  146. t.Fatal("Failed to create new framer:", err)
  147. }
  148. rstStreamFrame := RstStreamFrame{
  149. CFHeader: ControlFrameHeader{
  150. version: Version,
  151. frameType: TypeRstStream,
  152. },
  153. StreamId: 1,
  154. Status: InvalidStream,
  155. }
  156. if err := framer.WriteFrame(&rstStreamFrame); err != nil {
  157. t.Fatal("WriteFrame:", err)
  158. }
  159. frame, err := framer.ReadFrame()
  160. if err != nil {
  161. t.Fatal("ReadFrame:", err)
  162. }
  163. parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
  164. if !ok {
  165. t.Fatal("Parsed incorrect frame type:", frame)
  166. }
  167. if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
  168. t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
  169. }
  170. }
  171. func TestCreateParseSettings(t *testing.T) {
  172. buffer := new(bytes.Buffer)
  173. framer, err := NewFramer(buffer, buffer)
  174. if err != nil {
  175. t.Fatal("Failed to create new framer:", err)
  176. }
  177. settingsFrame := SettingsFrame{
  178. CFHeader: ControlFrameHeader{
  179. version: Version,
  180. frameType: TypeSettings,
  181. },
  182. FlagIdValues: []SettingsFlagIdValue{
  183. {FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
  184. {FlagSettingsPersisted, SettingsUploadBandwidth, 1},
  185. },
  186. }
  187. if err := framer.WriteFrame(&settingsFrame); err != nil {
  188. t.Fatal("WriteFrame:", err)
  189. }
  190. frame, err := framer.ReadFrame()
  191. if err != nil {
  192. t.Fatal("ReadFrame:", err)
  193. }
  194. parsedSettingsFrame, ok := frame.(*SettingsFrame)
  195. if !ok {
  196. t.Fatal("Parsed incorrect frame type:", frame)
  197. }
  198. if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
  199. t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
  200. }
  201. }
  202. func TestCreateParseNoop(t *testing.T) {
  203. buffer := new(bytes.Buffer)
  204. framer, err := NewFramer(buffer, buffer)
  205. if err != nil {
  206. t.Fatal("Failed to create new framer:", err)
  207. }
  208. noopFrame := NoopFrame{
  209. CFHeader: ControlFrameHeader{
  210. version: Version,
  211. frameType: TypeNoop,
  212. },
  213. }
  214. if err := framer.WriteFrame(&noopFrame); err != nil {
  215. t.Fatal("WriteFrame:", err)
  216. }
  217. frame, err := framer.ReadFrame()
  218. if err != nil {
  219. t.Fatal("ReadFrame:", err)
  220. }
  221. parsedNoopFrame, ok := frame.(*NoopFrame)
  222. if !ok {
  223. t.Fatal("Parsed incorrect frame type:", frame)
  224. }
  225. if !reflect.DeepEqual(noopFrame, *parsedNoopFrame) {
  226. t.Fatal("got: ", *parsedNoopFrame, "\nwant: ", noopFrame)
  227. }
  228. }
  229. func TestCreateParsePing(t *testing.T) {
  230. buffer := new(bytes.Buffer)
  231. framer, err := NewFramer(buffer, buffer)
  232. if err != nil {
  233. t.Fatal("Failed to create new framer:", err)
  234. }
  235. pingFrame := PingFrame{
  236. CFHeader: ControlFrameHeader{
  237. version: Version,
  238. frameType: TypePing,
  239. },
  240. Id: 31337,
  241. }
  242. if err := framer.WriteFrame(&pingFrame); err != nil {
  243. t.Fatal("WriteFrame:", err)
  244. }
  245. frame, err := framer.ReadFrame()
  246. if err != nil {
  247. t.Fatal("ReadFrame:", err)
  248. }
  249. parsedPingFrame, ok := frame.(*PingFrame)
  250. if !ok {
  251. t.Fatal("Parsed incorrect frame type:", frame)
  252. }
  253. if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
  254. t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
  255. }
  256. }
  257. func TestCreateParseGoAway(t *testing.T) {
  258. buffer := new(bytes.Buffer)
  259. framer, err := NewFramer(buffer, buffer)
  260. if err != nil {
  261. t.Fatal("Failed to create new framer:", err)
  262. }
  263. goAwayFrame := GoAwayFrame{
  264. CFHeader: ControlFrameHeader{
  265. version: Version,
  266. frameType: TypeGoAway,
  267. },
  268. LastGoodStreamId: 31337,
  269. }
  270. if err := framer.WriteFrame(&goAwayFrame); err != nil {
  271. t.Fatal("WriteFrame:", err)
  272. }
  273. frame, err := framer.ReadFrame()
  274. if err != nil {
  275. t.Fatal("ReadFrame:", err)
  276. }
  277. parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
  278. if !ok {
  279. t.Fatal("Parsed incorrect frame type:", frame)
  280. }
  281. if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
  282. t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
  283. }
  284. }
  285. func TestCreateParseHeadersFrame(t *testing.T) {
  286. buffer := new(bytes.Buffer)
  287. framer := &Framer{
  288. headerCompressionDisabled: true,
  289. w: buffer,
  290. headerBuf: new(bytes.Buffer),
  291. r: buffer,
  292. }
  293. headersFrame := HeadersFrame{
  294. CFHeader: ControlFrameHeader{
  295. version: Version,
  296. frameType: TypeHeaders,
  297. },
  298. StreamId: 2,
  299. }
  300. headersFrame.Headers = http.Header{
  301. "Url": []string{"http://www.google.com/"},
  302. "Method": []string{"get"},
  303. "Version": []string{"http/1.1"},
  304. }
  305. if err := framer.WriteFrame(&headersFrame); err != nil {
  306. t.Fatal("WriteFrame without compression:", err)
  307. }
  308. frame, err := framer.ReadFrame()
  309. if err != nil {
  310. t.Fatal("ReadFrame without compression:", err)
  311. }
  312. parsedHeadersFrame, ok := frame.(*HeadersFrame)
  313. if !ok {
  314. t.Fatal("Parsed incorrect frame type:", frame)
  315. }
  316. if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
  317. t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
  318. }
  319. // Test again with compression
  320. buffer.Reset()
  321. framer, err = NewFramer(buffer, buffer)
  322. if err := framer.WriteFrame(&headersFrame); err != nil {
  323. t.Fatal("WriteFrame with compression:", err)
  324. }
  325. frame, err = framer.ReadFrame()
  326. if err != nil {
  327. t.Fatal("ReadFrame with compression:", err)
  328. }
  329. parsedHeadersFrame, ok = frame.(*HeadersFrame)
  330. if !ok {
  331. t.Fatal("Parsed incorrect frame type:", frame)
  332. }
  333. if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
  334. t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
  335. }
  336. }
  337. func TestCreateParseDataFrame(t *testing.T) {
  338. buffer := new(bytes.Buffer)
  339. framer, err := NewFramer(buffer, buffer)
  340. if err != nil {
  341. t.Fatal("Failed to create new framer:", err)
  342. }
  343. dataFrame := DataFrame{
  344. StreamId: 1,
  345. Data: []byte{'h', 'e', 'l', 'l', 'o'},
  346. }
  347. if err := framer.WriteFrame(&dataFrame); err != nil {
  348. t.Fatal("WriteFrame:", err)
  349. }
  350. frame, err := framer.ReadFrame()
  351. if err != nil {
  352. t.Fatal("ReadFrame:", err)
  353. }
  354. parsedDataFrame, ok := frame.(*DataFrame)
  355. if !ok {
  356. t.Fatal("Parsed incorrect frame type:", frame)
  357. }
  358. if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
  359. t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
  360. }
  361. }
  362. func TestCompressionContextAcrossFrames(t *testing.T) {
  363. buffer := new(bytes.Buffer)
  364. framer, err := NewFramer(buffer, buffer)
  365. if err != nil {
  366. t.Fatal("Failed to create new framer:", err)
  367. }
  368. headersFrame := HeadersFrame{
  369. CFHeader: ControlFrameHeader{
  370. version: Version,
  371. frameType: TypeHeaders,
  372. },
  373. StreamId: 2,
  374. Headers: http.Header{
  375. "Url": []string{"http://www.google.com/"},
  376. "Method": []string{"get"},
  377. "Version": []string{"http/1.1"},
  378. },
  379. }
  380. if err := framer.WriteFrame(&headersFrame); err != nil {
  381. t.Fatal("WriteFrame (HEADERS):", err)
  382. }
  383. synStreamFrame := SynStreamFrame{ControlFrameHeader{Version, TypeSynStream, 0, 0}, 2, 0, 0, nil}
  384. synStreamFrame.Headers = http.Header{
  385. "Url": []string{"http://www.google.com/"},
  386. "Method": []string{"get"},
  387. "Version": []string{"http/1.1"},
  388. }
  389. if err := framer.WriteFrame(&synStreamFrame); err != nil {
  390. t.Fatal("WriteFrame (SYN_STREAM):", err)
  391. }
  392. frame, err := framer.ReadFrame()
  393. if err != nil {
  394. t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
  395. }
  396. parsedHeadersFrame, ok := frame.(*HeadersFrame)
  397. if !ok {
  398. t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
  399. }
  400. if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
  401. t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
  402. }
  403. frame, err = framer.ReadFrame()
  404. if err != nil {
  405. t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
  406. }
  407. parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
  408. if !ok {
  409. t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
  410. }
  411. if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
  412. t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
  413. }
  414. }
  415. func TestMultipleSPDYFrames(t *testing.T) {
  416. // Initialize the framers.
  417. pr1, pw1 := io.Pipe()
  418. pr2, pw2 := io.Pipe()
  419. writer, err := NewFramer(pw1, pr2)
  420. if err != nil {
  421. t.Fatal("Failed to create writer:", err)
  422. }
  423. reader, err := NewFramer(pw2, pr1)
  424. if err != nil {
  425. t.Fatal("Failed to create reader:", err)
  426. }
  427. // Set up the frames we're actually transferring.
  428. headersFrame := HeadersFrame{
  429. CFHeader: ControlFrameHeader{
  430. version: Version,
  431. frameType: TypeHeaders,
  432. },
  433. StreamId: 2,
  434. Headers: http.Header{
  435. "Url": []string{"http://www.google.com/"},
  436. "Method": []string{"get"},
  437. "Version": []string{"http/1.1"},
  438. },
  439. }
  440. synStreamFrame := SynStreamFrame{
  441. CFHeader: ControlFrameHeader{
  442. version: Version,
  443. frameType: TypeSynStream,
  444. },
  445. StreamId: 2,
  446. Headers: http.Header{
  447. "Url": []string{"http://www.google.com/"},
  448. "Method": []string{"get"},
  449. "Version": []string{"http/1.1"},
  450. },
  451. }
  452. // Start the goroutines to write the frames.
  453. go func() {
  454. if err := writer.WriteFrame(&headersFrame); err != nil {
  455. t.Fatal("WriteFrame (HEADERS): ", err)
  456. }
  457. if err := writer.WriteFrame(&synStreamFrame); err != nil {
  458. t.Fatal("WriteFrame (SYN_STREAM): ", err)
  459. }
  460. }()
  461. // Read the frames and verify they look as expected.
  462. frame, err := reader.ReadFrame()
  463. if err != nil {
  464. t.Fatal("ReadFrame (HEADERS): ", err)
  465. }
  466. parsedHeadersFrame, ok := frame.(*HeadersFrame)
  467. if !ok {
  468. t.Fatal("Parsed incorrect frame type:", frame)
  469. }
  470. if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
  471. t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
  472. }
  473. frame, err = reader.ReadFrame()
  474. if err != nil {
  475. t.Fatal("ReadFrame (SYN_STREAM):", err)
  476. }
  477. parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
  478. if !ok {
  479. t.Fatal("Parsed incorrect frame type.")
  480. }
  481. if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
  482. t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
  483. }
  484. }
  485. func TestReadMalformedZlibHeader(t *testing.T) {
  486. // These were constructed by corrupting the first byte of the zlib
  487. // header after writing.
  488. malformedStructs := map[string]string{
  489. "SynStreamFrame": "gAIAAQAAABgAAAACAAAAAAAAF/nfolGyYmAAAAAA//8=",
  490. "SynReplyFrame": "gAIAAgAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
  491. "HeadersFrame": "gAIACAAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
  492. }
  493. for name, bad := range malformedStructs {
  494. b, err := base64.StdEncoding.DecodeString(bad)
  495. if err != nil {
  496. t.Errorf("Unable to decode base64 encoded frame %s: %v", name, err)
  497. }
  498. buf := bytes.NewBuffer(b)
  499. reader, err := NewFramer(buf, buf)
  500. if err != nil {
  501. t.Fatalf("NewFramer: %v", err)
  502. }
  503. _, err = reader.ReadFrame()
  504. if err != zlib.ErrHeader {
  505. t.Errorf("Frame %s, expected: %#v, actual: %#v", name, zlib.ErrHeader, err)
  506. }
  507. }
  508. }
  509. type zeroStream struct {
  510. frame Frame
  511. encoded string
  512. }
  513. var streamIdZeroFrames = map[string]zeroStream{
  514. "SynStreamFrame": {
  515. &SynStreamFrame{StreamId: 0},
  516. "gAIAAQAAABgAAAAAAAAAAAAAePnfolGyYmAAAAAA//8=",
  517. },
  518. "SynReplyFrame": {
  519. &SynReplyFrame{StreamId: 0},
  520. "gAIAAgAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
  521. },
  522. "RstStreamFrame": {
  523. &RstStreamFrame{StreamId: 0},
  524. "gAIAAwAAAAgAAAAAAAAAAA==",
  525. },
  526. "HeadersFrame": {
  527. &HeadersFrame{StreamId: 0},
  528. "gAIACAAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
  529. },
  530. "DataFrame": {
  531. &DataFrame{StreamId: 0},
  532. "AAAAAAAAAAA=",
  533. },
  534. "PingFrame": {
  535. &PingFrame{Id: 0},
  536. "gAIABgAAAAQAAAAA",
  537. },
  538. }
  539. func TestNoZeroStreamId(t *testing.T) {
  540. for name, f := range streamIdZeroFrames {
  541. b, err := base64.StdEncoding.DecodeString(f.encoded)
  542. if err != nil {
  543. t.Errorf("Unable to decode base64 encoded frame %s: %v", f, err)
  544. continue
  545. }
  546. framer, err := NewFramer(ioutil.Discard, bytes.NewReader(b))
  547. if err != nil {
  548. t.Fatalf("NewFramer: %v", err)
  549. }
  550. err = framer.WriteFrame(f.frame)
  551. checkZeroStreamId(t, name, "WriteFrame", err)
  552. _, err = framer.ReadFrame()
  553. checkZeroStreamId(t, name, "ReadFrame", err)
  554. }
  555. }
  556. func checkZeroStreamId(t *testing.T, frame string, method string, err error) {
  557. if err == nil {
  558. t.Errorf("%s ZeroStreamId, no error on %s", method, frame)
  559. return
  560. }
  561. eerr, ok := err.(*Error)
  562. if !ok || eerr.Err != ZeroStreamId {
  563. t.Errorf("%s ZeroStreamId, incorrect error %#v, frame %s", method, eerr, frame)
  564. }
  565. }