frame_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. // Copyright 2014 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 http2
  5. import (
  6. "bytes"
  7. "reflect"
  8. "testing"
  9. "unsafe"
  10. )
  11. func testFramer() (*Framer, *bytes.Buffer) {
  12. buf := new(bytes.Buffer)
  13. return NewFramer(buf, buf), buf
  14. }
  15. func TestFrameSizes(t *testing.T) {
  16. // Catch people rearranging the FrameHeader fields.
  17. if got, want := int(unsafe.Sizeof(FrameHeader{})), 12; got != want {
  18. t.Errorf("FrameHeader size = %d; want %d", got, want)
  19. }
  20. }
  21. func TestWriteRST(t *testing.T) {
  22. fr, buf := testFramer()
  23. var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
  24. var errCode uint32 = 7<<24 + 6<<16 + 5<<8 + 4
  25. fr.WriteRSTStream(streamID, ErrCode(errCode))
  26. const wantEnc = "\x00\x00\x04\x03\x00\x01\x02\x03\x04\x07\x06\x05\x04"
  27. if buf.String() != wantEnc {
  28. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  29. }
  30. f, err := fr.ReadFrame()
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. want := &RSTStreamFrame{
  35. FrameHeader: FrameHeader{
  36. valid: true,
  37. Type: 0x3,
  38. Flags: 0x0,
  39. Length: 0x4,
  40. StreamID: 0x1020304,
  41. },
  42. ErrCode: 0x7060504,
  43. }
  44. if !reflect.DeepEqual(f, want) {
  45. t.Errorf("parsed back %#v; want %#v", f, want)
  46. }
  47. }
  48. func TestWriteData(t *testing.T) {
  49. fr, buf := testFramer()
  50. var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
  51. data := []byte("ABC")
  52. fr.WriteData(streamID, true, data)
  53. const wantEnc = "\x00\x00\x03\x00\x01\x01\x02\x03\x04ABC"
  54. if buf.String() != wantEnc {
  55. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  56. }
  57. f, err := fr.ReadFrame()
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. df, ok := f.(*DataFrame)
  62. if !ok {
  63. t.Fatalf("got %T; want *DataFrame", f)
  64. }
  65. if !bytes.Equal(df.Data(), data) {
  66. t.Errorf("got %q; want %q", df.Data(), data)
  67. }
  68. if f.Header().Flags&1 == 0 {
  69. t.Errorf("didn't see END_STREAM flag")
  70. }
  71. }
  72. func TestWriteHeaders(t *testing.T) {
  73. tests := []struct {
  74. name string
  75. p HeadersFrameParam
  76. wantEnc string
  77. wantFrame *HeadersFrame
  78. }{
  79. {
  80. "basic",
  81. HeadersFrameParam{
  82. StreamID: 42,
  83. BlockFragment: []byte("abc"),
  84. Priority: PriorityParam{},
  85. },
  86. "\x00\x00\x03\x01\x00\x00\x00\x00*abc",
  87. &HeadersFrame{
  88. FrameHeader: FrameHeader{
  89. valid: true,
  90. StreamID: 42,
  91. Type: FrameHeaders,
  92. Length: uint32(len("abc")),
  93. },
  94. Priority: PriorityParam{},
  95. headerFragBuf: []byte("abc"),
  96. },
  97. },
  98. {
  99. "basic + end flags",
  100. HeadersFrameParam{
  101. StreamID: 42,
  102. BlockFragment: []byte("abc"),
  103. EndStream: true,
  104. EndHeaders: true,
  105. Priority: PriorityParam{},
  106. },
  107. "\x00\x00\x03\x01\x05\x00\x00\x00*abc",
  108. &HeadersFrame{
  109. FrameHeader: FrameHeader{
  110. valid: true,
  111. StreamID: 42,
  112. Type: FrameHeaders,
  113. Flags: FlagHeadersEndStream | FlagHeadersEndHeaders,
  114. Length: uint32(len("abc")),
  115. },
  116. Priority: PriorityParam{},
  117. headerFragBuf: []byte("abc"),
  118. },
  119. },
  120. {
  121. "with padding",
  122. HeadersFrameParam{
  123. StreamID: 42,
  124. BlockFragment: []byte("abc"),
  125. EndStream: true,
  126. EndHeaders: true,
  127. PadLength: 5,
  128. Priority: PriorityParam{},
  129. },
  130. "\x00\x00\t\x01\r\x00\x00\x00*\x05abc\x00\x00\x00\x00\x00",
  131. &HeadersFrame{
  132. FrameHeader: FrameHeader{
  133. valid: true,
  134. StreamID: 42,
  135. Type: FrameHeaders,
  136. Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded,
  137. Length: uint32(1 + len("abc") + 5), // pad length + contents + padding
  138. },
  139. Priority: PriorityParam{},
  140. headerFragBuf: []byte("abc"),
  141. },
  142. },
  143. {
  144. "with priority",
  145. HeadersFrameParam{
  146. StreamID: 42,
  147. BlockFragment: []byte("abc"),
  148. EndStream: true,
  149. EndHeaders: true,
  150. PadLength: 2,
  151. Priority: PriorityParam{
  152. StreamDep: 15,
  153. Exclusive: true,
  154. Weight: 127,
  155. },
  156. },
  157. "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x0f\u007fabc\x00\x00",
  158. &HeadersFrame{
  159. FrameHeader: FrameHeader{
  160. valid: true,
  161. StreamID: 42,
  162. Type: FrameHeaders,
  163. Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
  164. Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
  165. },
  166. Priority: PriorityParam{
  167. StreamDep: 15,
  168. Exclusive: true,
  169. Weight: 127,
  170. },
  171. headerFragBuf: []byte("abc"),
  172. },
  173. },
  174. }
  175. for _, tt := range tests {
  176. fr, buf := testFramer()
  177. if err := fr.WriteHeaders(tt.p); err != nil {
  178. t.Errorf("test %q: %v", tt.name, err)
  179. continue
  180. }
  181. if buf.String() != tt.wantEnc {
  182. t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc)
  183. }
  184. f, err := fr.ReadFrame()
  185. if err != nil {
  186. t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
  187. continue
  188. }
  189. if !reflect.DeepEqual(f, tt.wantFrame) {
  190. t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
  191. }
  192. }
  193. }
  194. func TestWriteContinuation(t *testing.T) {
  195. const streamID = 42
  196. tests := []struct {
  197. name string
  198. end bool
  199. frag []byte
  200. wantFrame *ContinuationFrame
  201. }{
  202. {
  203. "not end",
  204. false,
  205. []byte("abc"),
  206. &ContinuationFrame{
  207. FrameHeader: FrameHeader{
  208. valid: true,
  209. StreamID: streamID,
  210. Type: FrameContinuation,
  211. Length: uint32(len("abc")),
  212. },
  213. headerFragBuf: []byte("abc"),
  214. },
  215. },
  216. {
  217. "end",
  218. true,
  219. []byte("def"),
  220. &ContinuationFrame{
  221. FrameHeader: FrameHeader{
  222. valid: true,
  223. StreamID: streamID,
  224. Type: FrameContinuation,
  225. Flags: FlagContinuationEndHeaders,
  226. Length: uint32(len("def")),
  227. },
  228. headerFragBuf: []byte("def"),
  229. },
  230. },
  231. }
  232. for _, tt := range tests {
  233. fr, _ := testFramer()
  234. if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil {
  235. t.Errorf("test %q: %v", tt.name, err)
  236. continue
  237. }
  238. f, err := fr.ReadFrame()
  239. if err != nil {
  240. t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
  241. continue
  242. }
  243. if !reflect.DeepEqual(f, tt.wantFrame) {
  244. t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
  245. }
  246. }
  247. }
  248. func TestWritePriority(t *testing.T) {
  249. const streamID = 42
  250. tests := []struct {
  251. name string
  252. priority PriorityParam
  253. wantFrame *PriorityFrame
  254. }{
  255. {
  256. "not exclusive",
  257. PriorityParam{
  258. StreamDep: 2,
  259. Exclusive: false,
  260. Weight: 127,
  261. },
  262. &PriorityFrame{
  263. FrameHeader{
  264. valid: true,
  265. StreamID: streamID,
  266. Type: FramePriority,
  267. Length: 5,
  268. },
  269. PriorityParam{
  270. StreamDep: 2,
  271. Exclusive: false,
  272. Weight: 127,
  273. },
  274. },
  275. },
  276. {
  277. "exclusive",
  278. PriorityParam{
  279. StreamDep: 3,
  280. Exclusive: true,
  281. Weight: 77,
  282. },
  283. &PriorityFrame{
  284. FrameHeader{
  285. valid: true,
  286. StreamID: streamID,
  287. Type: FramePriority,
  288. Length: 5,
  289. },
  290. PriorityParam{
  291. StreamDep: 3,
  292. Exclusive: true,
  293. Weight: 77,
  294. },
  295. },
  296. },
  297. }
  298. for _, tt := range tests {
  299. fr, _ := testFramer()
  300. if err := fr.WritePriority(streamID, tt.priority); err != nil {
  301. t.Errorf("test %q: %v", tt.name, err)
  302. continue
  303. }
  304. f, err := fr.ReadFrame()
  305. if err != nil {
  306. t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
  307. continue
  308. }
  309. if !reflect.DeepEqual(f, tt.wantFrame) {
  310. t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
  311. }
  312. }
  313. }
  314. func TestWriteSettings(t *testing.T) {
  315. fr, buf := testFramer()
  316. settings := []Setting{{1, 2}, {3, 4}}
  317. fr.WriteSettings(settings...)
  318. const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
  319. if buf.String() != wantEnc {
  320. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  321. }
  322. f, err := fr.ReadFrame()
  323. if err != nil {
  324. t.Fatal(err)
  325. }
  326. sf, ok := f.(*SettingsFrame)
  327. if !ok {
  328. t.Fatalf("Got a %T; want a SettingsFrame", f)
  329. }
  330. var got []Setting
  331. sf.ForeachSetting(func(s Setting) error {
  332. got = append(got, s)
  333. valBack, ok := sf.Value(s.ID)
  334. if !ok || valBack != s.Val {
  335. t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
  336. }
  337. return nil
  338. })
  339. if !reflect.DeepEqual(settings, got) {
  340. t.Errorf("Read settings %+v != written settings %+v", got, settings)
  341. }
  342. }
  343. func TestWriteSettingsAck(t *testing.T) {
  344. fr, buf := testFramer()
  345. fr.WriteSettingsAck()
  346. const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
  347. if buf.String() != wantEnc {
  348. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  349. }
  350. }
  351. func TestWriteWindowUpdate(t *testing.T) {
  352. fr, buf := testFramer()
  353. const streamID = 1<<24 + 2<<16 + 3<<8 + 4
  354. const incr = 7<<24 + 6<<16 + 5<<8 + 4
  355. if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
  356. t.Fatal(err)
  357. }
  358. const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
  359. if buf.String() != wantEnc {
  360. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  361. }
  362. f, err := fr.ReadFrame()
  363. if err != nil {
  364. t.Fatal(err)
  365. }
  366. want := &WindowUpdateFrame{
  367. FrameHeader: FrameHeader{
  368. valid: true,
  369. Type: 0x8,
  370. Flags: 0x0,
  371. Length: 0x4,
  372. StreamID: 0x1020304,
  373. },
  374. Increment: 0x7060504,
  375. }
  376. if !reflect.DeepEqual(f, want) {
  377. t.Errorf("parsed back %#v; want %#v", f, want)
  378. }
  379. }
  380. func TestWritePing(t *testing.T) { testWritePing(t, false) }
  381. func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
  382. func testWritePing(t *testing.T, ack bool) {
  383. fr, buf := testFramer()
  384. if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
  385. t.Fatal(err)
  386. }
  387. var wantFlags Flags
  388. if ack {
  389. wantFlags = FlagPingAck
  390. }
  391. var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
  392. if buf.String() != wantEnc {
  393. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  394. }
  395. f, err := fr.ReadFrame()
  396. if err != nil {
  397. t.Fatal(err)
  398. }
  399. want := &PingFrame{
  400. FrameHeader: FrameHeader{
  401. valid: true,
  402. Type: 0x6,
  403. Flags: wantFlags,
  404. Length: 0x8,
  405. StreamID: 0,
  406. },
  407. Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
  408. }
  409. if !reflect.DeepEqual(f, want) {
  410. t.Errorf("parsed back %#v; want %#v", f, want)
  411. }
  412. }
  413. func TestReadFrameHeader(t *testing.T) {
  414. tests := []struct {
  415. len uint32
  416. typ FrameType
  417. flags Flags
  418. streamID uint32
  419. }{
  420. {len: 0, typ: 255, flags: 1, streamID: 0},
  421. {len: 0, typ: 255, flags: 1, streamID: 1},
  422. {len: 0, typ: 255, flags: 1, streamID: 255},
  423. {len: 0, typ: 255, flags: 1, streamID: 256},
  424. {len: 0, typ: 255, flags: 1, streamID: 65535},
  425. {len: 0, typ: 255, flags: 1, streamID: 65536},
  426. {len: 0, typ: 1, flags: 255, streamID: 1},
  427. {len: 255, typ: 1, flags: 255, streamID: 1},
  428. {len: 256, typ: 1, flags: 255, streamID: 1},
  429. {len: 65535, typ: 1, flags: 255, streamID: 1},
  430. {len: 65536, typ: 1, flags: 255, streamID: 1},
  431. {len: 16777215, typ: 1, flags: 255, streamID: 1},
  432. }
  433. for _, tt := range tests {
  434. fr, buf := testFramer()
  435. fr.startWrite(tt.typ, tt.flags, tt.streamID)
  436. fr.writeBytes(make([]byte, tt.len))
  437. fr.endWrite()
  438. fh, err := ReadFrameHeader(buf)
  439. if err != nil {
  440. t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
  441. continue
  442. }
  443. if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
  444. t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
  445. }
  446. }
  447. }
  448. func TestWriteTooLargeFrame(t *testing.T) {
  449. fr, _ := testFramer()
  450. fr.startWrite(0, 1, 1)
  451. fr.writeBytes(make([]byte, 1<<24))
  452. err := fr.endWrite()
  453. if err != ErrFrameTooLarge {
  454. t.Errorf("endWrite = %v; want errFrameTooLarge", err)
  455. }
  456. }
  457. func TestWriteGoAway(t *testing.T) {
  458. const debug = "foo"
  459. fr, buf := testFramer()
  460. if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
  461. t.Fatal(err)
  462. }
  463. const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
  464. if buf.String() != wantEnc {
  465. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  466. }
  467. f, err := fr.ReadFrame()
  468. if err != nil {
  469. t.Fatal(err)
  470. }
  471. want := &GoAwayFrame{
  472. FrameHeader: FrameHeader{
  473. valid: true,
  474. Type: 0x7,
  475. Flags: 0,
  476. Length: uint32(4 + 4 + len(debug)),
  477. StreamID: 0,
  478. },
  479. LastStreamID: 0x01020304,
  480. ErrCode: 0x05060708,
  481. debugData: []byte(debug),
  482. }
  483. if !reflect.DeepEqual(f, want) {
  484. t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
  485. }
  486. if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
  487. t.Errorf("debug data = %q; want %q", got, debug)
  488. }
  489. }
  490. func TestWritePushPromise(t *testing.T) {
  491. pp := PushPromiseParam{
  492. StreamID: 42,
  493. PromiseID: 42,
  494. BlockFragment: []byte("abc"),
  495. }
  496. fr, buf := testFramer()
  497. if err := fr.WritePushPromise(pp); err != nil {
  498. t.Fatal(err)
  499. }
  500. const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
  501. if buf.String() != wantEnc {
  502. t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
  503. }
  504. f, err := fr.ReadFrame()
  505. if err != nil {
  506. t.Fatal(err)
  507. }
  508. _, ok := f.(*PushPromiseFrame)
  509. if !ok {
  510. t.Fatalf("got %T; want *PushPromiseFrame", f)
  511. }
  512. want := &PushPromiseFrame{
  513. FrameHeader: FrameHeader{
  514. valid: true,
  515. Type: 0x5,
  516. Flags: 0x0,
  517. Length: 0x7,
  518. StreamID: 42,
  519. },
  520. PromiseID: 42,
  521. headerFragBuf: []byte("abc"),
  522. }
  523. if !reflect.DeepEqual(f, want) {
  524. t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
  525. }
  526. }