OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / http2 / writesched_priority_test.go
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         "bytes"
9         "fmt"
10         "sort"
11         "testing"
12 )
13
14 func defaultPriorityWriteScheduler() *priorityWriteScheduler {
15         return NewPriorityWriteScheduler(nil).(*priorityWriteScheduler)
16 }
17
18 func checkPriorityWellFormed(ws *priorityWriteScheduler) error {
19         for id, n := range ws.nodes {
20                 if id != n.id {
21                         return fmt.Errorf("bad ws.nodes: ws.nodes[%d] = %d", id, n.id)
22                 }
23                 if n.parent == nil {
24                         if n.next != nil || n.prev != nil {
25                                 return fmt.Errorf("bad node %d: nil parent but prev/next not nil", id)
26                         }
27                         continue
28                 }
29                 found := false
30                 for k := n.parent.kids; k != nil; k = k.next {
31                         if k.id == id {
32                                 found = true
33                                 break
34                         }
35                 }
36                 if !found {
37                         return fmt.Errorf("bad node %d: not found in parent %d kids list", id, n.parent.id)
38                 }
39         }
40         return nil
41 }
42
43 func fmtTree(ws *priorityWriteScheduler, fmtNode func(*priorityNode) string) string {
44         var ids []int
45         for _, n := range ws.nodes {
46                 ids = append(ids, int(n.id))
47         }
48         sort.Ints(ids)
49
50         var buf bytes.Buffer
51         for _, id := range ids {
52                 if buf.Len() != 0 {
53                         buf.WriteString(" ")
54                 }
55                 if id == 0 {
56                         buf.WriteString(fmtNode(&ws.root))
57                 } else {
58                         buf.WriteString(fmtNode(ws.nodes[uint32(id)]))
59                 }
60         }
61         return buf.String()
62 }
63
64 func fmtNodeParentSkipRoot(n *priorityNode) string {
65         switch {
66         case n.id == 0:
67                 return ""
68         case n.parent == nil:
69                 return fmt.Sprintf("%d{parent:nil}", n.id)
70         default:
71                 return fmt.Sprintf("%d{parent:%d}", n.id, n.parent.id)
72         }
73 }
74
75 func fmtNodeWeightParentSkipRoot(n *priorityNode) string {
76         switch {
77         case n.id == 0:
78                 return ""
79         case n.parent == nil:
80                 return fmt.Sprintf("%d{weight:%d,parent:nil}", n.id, n.weight)
81         default:
82                 return fmt.Sprintf("%d{weight:%d,parent:%d}", n.id, n.weight, n.parent.id)
83         }
84 }
85
86 func TestPriorityTwoStreams(t *testing.T) {
87         ws := defaultPriorityWriteScheduler()
88         ws.OpenStream(1, OpenStreamOptions{})
89         ws.OpenStream(2, OpenStreamOptions{})
90
91         want := "1{weight:15,parent:0} 2{weight:15,parent:0}"
92         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
93                 t.Errorf("After open\ngot  %q\nwant %q", got, want)
94         }
95
96         // Move 1's parent to 2.
97         ws.AdjustStream(1, PriorityParam{
98                 StreamDep: 2,
99                 Weight:    32,
100                 Exclusive: false,
101         })
102         want = "1{weight:32,parent:2} 2{weight:15,parent:0}"
103         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
104                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
105         }
106
107         if err := checkPriorityWellFormed(ws); err != nil {
108                 t.Error(err)
109         }
110 }
111
112 func TestPriorityAdjustExclusiveZero(t *testing.T) {
113         // 1, 2, and 3 are all children of the 0 stream.
114         // Exclusive reprioritization to any of the streams should bring
115         // the rest of the streams under the reprioritized stream.
116         ws := defaultPriorityWriteScheduler()
117         ws.OpenStream(1, OpenStreamOptions{})
118         ws.OpenStream(2, OpenStreamOptions{})
119         ws.OpenStream(3, OpenStreamOptions{})
120
121         want := "1{weight:15,parent:0} 2{weight:15,parent:0} 3{weight:15,parent:0}"
122         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
123                 t.Errorf("After open\ngot  %q\nwant %q", got, want)
124         }
125
126         ws.AdjustStream(2, PriorityParam{
127                 StreamDep: 0,
128                 Weight:    20,
129                 Exclusive: true,
130         })
131         want = "1{weight:15,parent:2} 2{weight:20,parent:0} 3{weight:15,parent:2}"
132         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
133                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
134         }
135
136         if err := checkPriorityWellFormed(ws); err != nil {
137                 t.Error(err)
138         }
139 }
140
141 func TestPriorityAdjustOwnParent(t *testing.T) {
142         // Assigning a node as its own parent should have no effect.
143         ws := defaultPriorityWriteScheduler()
144         ws.OpenStream(1, OpenStreamOptions{})
145         ws.OpenStream(2, OpenStreamOptions{})
146         ws.AdjustStream(2, PriorityParam{
147                 StreamDep: 2,
148                 Weight:    20,
149                 Exclusive: true,
150         })
151         want := "1{weight:15,parent:0} 2{weight:15,parent:0}"
152         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
153                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
154         }
155         if err := checkPriorityWellFormed(ws); err != nil {
156                 t.Error(err)
157         }
158 }
159
160 func TestPriorityClosedStreams(t *testing.T) {
161         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxClosedNodesInTree: 2}).(*priorityWriteScheduler)
162         ws.OpenStream(1, OpenStreamOptions{})
163         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
164         ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
165         ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
166
167         // Close the first three streams. We lose 1, but keep 2 and 3.
168         ws.CloseStream(1)
169         ws.CloseStream(2)
170         ws.CloseStream(3)
171
172         want := "2{weight:15,parent:0} 3{weight:15,parent:2} 4{weight:15,parent:3}"
173         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
174                 t.Errorf("After close\ngot  %q\nwant %q", got, want)
175         }
176         if err := checkPriorityWellFormed(ws); err != nil {
177                 t.Error(err)
178         }
179
180         // Adding a stream as an exclusive child of 1 gives it default
181         // priorities, since 1 is gone.
182         ws.OpenStream(5, OpenStreamOptions{})
183         ws.AdjustStream(5, PriorityParam{StreamDep: 1, Weight: 15, Exclusive: true})
184
185         // Adding a stream as an exclusive child of 2 should work, since 2 is not gone.
186         ws.OpenStream(6, OpenStreamOptions{})
187         ws.AdjustStream(6, PriorityParam{StreamDep: 2, Weight: 15, Exclusive: true})
188
189         want = "2{weight:15,parent:0} 3{weight:15,parent:6} 4{weight:15,parent:3} 5{weight:15,parent:0} 6{weight:15,parent:2}"
190         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
191                 t.Errorf("After add streams\ngot  %q\nwant %q", got, want)
192         }
193         if err := checkPriorityWellFormed(ws); err != nil {
194                 t.Error(err)
195         }
196 }
197
198 func TestPriorityClosedStreamsDisabled(t *testing.T) {
199         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler)
200         ws.OpenStream(1, OpenStreamOptions{})
201         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
202         ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
203
204         // Close the first two streams. We keep only 3.
205         ws.CloseStream(1)
206         ws.CloseStream(2)
207
208         want := "3{weight:15,parent:0}"
209         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
210                 t.Errorf("After close\ngot  %q\nwant %q", got, want)
211         }
212         if err := checkPriorityWellFormed(ws); err != nil {
213                 t.Error(err)
214         }
215 }
216
217 func TestPriorityIdleStreams(t *testing.T) {
218         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxIdleNodesInTree: 2}).(*priorityWriteScheduler)
219         ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle
220         ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle
221         ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle
222         ws.OpenStream(4, OpenStreamOptions{})
223         ws.OpenStream(5, OpenStreamOptions{})
224         ws.OpenStream(6, OpenStreamOptions{})
225         ws.AdjustStream(4, PriorityParam{StreamDep: 1, Weight: 15})
226         ws.AdjustStream(5, PriorityParam{StreamDep: 2, Weight: 15})
227         ws.AdjustStream(6, PriorityParam{StreamDep: 3, Weight: 15})
228
229         want := "2{weight:15,parent:0} 3{weight:20,parent:2} 4{weight:15,parent:0} 5{weight:15,parent:2} 6{weight:15,parent:3}"
230         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
231                 t.Errorf("After open\ngot  %q\nwant %q", got, want)
232         }
233         if err := checkPriorityWellFormed(ws); err != nil {
234                 t.Error(err)
235         }
236 }
237
238 func TestPriorityIdleStreamsDisabled(t *testing.T) {
239         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler)
240         ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle
241         ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle
242         ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle
243         ws.OpenStream(4, OpenStreamOptions{})
244
245         want := "4{weight:15,parent:0}"
246         if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
247                 t.Errorf("After open\ngot  %q\nwant %q", got, want)
248         }
249         if err := checkPriorityWellFormed(ws); err != nil {
250                 t.Error(err)
251         }
252 }
253
254 func TestPrioritySection531NonExclusive(t *testing.T) {
255         // Example from RFC 7540 Section 5.3.1.
256         // A,B,C,D = 1,2,3,4
257         ws := defaultPriorityWriteScheduler()
258         ws.OpenStream(1, OpenStreamOptions{})
259         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
260         ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
261         ws.OpenStream(4, OpenStreamOptions{})
262         ws.AdjustStream(4, PriorityParam{
263                 StreamDep: 1,
264                 Weight:    15,
265                 Exclusive: false,
266         })
267         want := "1{parent:0} 2{parent:1} 3{parent:1} 4{parent:1}"
268         if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
269                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
270         }
271         if err := checkPriorityWellFormed(ws); err != nil {
272                 t.Error(err)
273         }
274 }
275
276 func TestPrioritySection531Exclusive(t *testing.T) {
277         // Example from RFC 7540 Section 5.3.1.
278         // A,B,C,D = 1,2,3,4
279         ws := defaultPriorityWriteScheduler()
280         ws.OpenStream(1, OpenStreamOptions{})
281         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
282         ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
283         ws.OpenStream(4, OpenStreamOptions{})
284         ws.AdjustStream(4, PriorityParam{
285                 StreamDep: 1,
286                 Weight:    15,
287                 Exclusive: true,
288         })
289         want := "1{parent:0} 2{parent:4} 3{parent:4} 4{parent:1}"
290         if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
291                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
292         }
293         if err := checkPriorityWellFormed(ws); err != nil {
294                 t.Error(err)
295         }
296 }
297
298 func makeSection533Tree() *priorityWriteScheduler {
299         // Initial tree from RFC 7540 Section 5.3.3.
300         // A,B,C,D,E,F = 1,2,3,4,5,6
301         ws := defaultPriorityWriteScheduler()
302         ws.OpenStream(1, OpenStreamOptions{})
303         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
304         ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
305         ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
306         ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
307         ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
308         return ws
309 }
310
311 func TestPrioritySection533NonExclusive(t *testing.T) {
312         // Example from RFC 7540 Section 5.3.3.
313         // A,B,C,D,E,F = 1,2,3,4,5,6
314         ws := defaultPriorityWriteScheduler()
315         ws.OpenStream(1, OpenStreamOptions{})
316         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
317         ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
318         ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
319         ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
320         ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
321         ws.AdjustStream(1, PriorityParam{
322                 StreamDep: 4,
323                 Weight:    15,
324                 Exclusive: false,
325         })
326         want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:4}"
327         if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
328                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
329         }
330         if err := checkPriorityWellFormed(ws); err != nil {
331                 t.Error(err)
332         }
333 }
334
335 func TestPrioritySection533Exclusive(t *testing.T) {
336         // Example from RFC 7540 Section 5.3.3.
337         // A,B,C,D,E,F = 1,2,3,4,5,6
338         ws := defaultPriorityWriteScheduler()
339         ws.OpenStream(1, OpenStreamOptions{})
340         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
341         ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
342         ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
343         ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
344         ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
345         ws.AdjustStream(1, PriorityParam{
346                 StreamDep: 4,
347                 Weight:    15,
348                 Exclusive: true,
349         })
350         want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:1}"
351         if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
352                 t.Errorf("After adjust\ngot  %q\nwant %q", got, want)
353         }
354         if err := checkPriorityWellFormed(ws); err != nil {
355                 t.Error(err)
356         }
357 }
358
359 func checkPopAll(ws WriteScheduler, order []uint32) error {
360         for k, id := range order {
361                 wr, ok := ws.Pop()
362                 if !ok {
363                         return fmt.Errorf("Pop[%d]: got ok=false, want %d (order=%v)", k, id, order)
364                 }
365                 if got := wr.StreamID(); got != id {
366                         return fmt.Errorf("Pop[%d]: got %v, want %d (order=%v)", k, got, id, order)
367                 }
368         }
369         wr, ok := ws.Pop()
370         if ok {
371                 return fmt.Errorf("Pop[%d]: got %v, want ok=false (order=%v)", len(order), wr.StreamID(), order)
372         }
373         return nil
374 }
375
376 func TestPriorityPopFrom533Tree(t *testing.T) {
377         ws := makeSection533Tree()
378
379         ws.Push(makeWriteHeadersRequest(3 /*C*/))
380         ws.Push(makeWriteNonStreamRequest())
381         ws.Push(makeWriteHeadersRequest(5 /*E*/))
382         ws.Push(makeWriteHeadersRequest(1 /*A*/))
383         t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot))
384
385         if err := checkPopAll(ws, []uint32{0 /*NonStream*/, 1, 3, 5}); err != nil {
386                 t.Error(err)
387         }
388 }
389
390 func TestPriorityPopFromLinearTree(t *testing.T) {
391         ws := defaultPriorityWriteScheduler()
392         ws.OpenStream(1, OpenStreamOptions{})
393         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
394         ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
395         ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
396
397         ws.Push(makeWriteHeadersRequest(3))
398         ws.Push(makeWriteHeadersRequest(4))
399         ws.Push(makeWriteHeadersRequest(1))
400         ws.Push(makeWriteHeadersRequest(2))
401         ws.Push(makeWriteNonStreamRequest())
402         ws.Push(makeWriteNonStreamRequest())
403         t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot))
404
405         if err := checkPopAll(ws, []uint32{0, 0 /*NonStreams*/, 1, 2, 3, 4}); err != nil {
406                 t.Error(err)
407         }
408 }
409
410 func TestPriorityFlowControl(t *testing.T) {
411         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: false})
412         ws.OpenStream(1, OpenStreamOptions{})
413         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
414
415         sc := &serverConn{maxFrameSize: 16}
416         st1 := &stream{id: 1, sc: sc}
417         st2 := &stream{id: 2, sc: sc}
418
419         ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 16), false}, st1, nil})
420         ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 16), false}, st2, nil})
421         ws.AdjustStream(2, PriorityParam{StreamDep: 1})
422
423         // No flow-control bytes available.
424         if wr, ok := ws.Pop(); ok {
425                 t.Fatalf("Pop(limited by flow control)=%v,true, want false", wr)
426         }
427
428         // Add enough flow-control bytes to write st2 in two Pop calls.
429         // Should write data from st2 even though it's lower priority than st1.
430         for i := 1; i <= 2; i++ {
431                 st2.flow.add(8)
432                 wr, ok := ws.Pop()
433                 if !ok {
434                         t.Fatalf("Pop(%d)=false, want true", i)
435                 }
436                 if got, want := wr.DataSize(), 8; got != want {
437                         t.Fatalf("Pop(%d)=%d bytes, want %d bytes", i, got, want)
438                 }
439         }
440 }
441
442 func TestPriorityThrottleOutOfOrderWrites(t *testing.T) {
443         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: true})
444         ws.OpenStream(1, OpenStreamOptions{})
445         ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
446
447         sc := &serverConn{maxFrameSize: 4096}
448         st1 := &stream{id: 1, sc: sc}
449         st2 := &stream{id: 2, sc: sc}
450         st1.flow.add(4096)
451         st2.flow.add(4096)
452         ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 4096), false}, st2, nil})
453         ws.AdjustStream(2, PriorityParam{StreamDep: 1})
454
455         // We have enough flow-control bytes to write st2 in a single Pop call.
456         // However, due to out-of-order write throttling, the first call should
457         // only write 1KB.
458         wr, ok := ws.Pop()
459         if !ok {
460                 t.Fatalf("Pop(st2.first)=false, want true")
461         }
462         if got, want := wr.StreamID(), uint32(2); got != want {
463                 t.Fatalf("Pop(st2.first)=stream %d, want stream %d", got, want)
464         }
465         if got, want := wr.DataSize(), 1024; got != want {
466                 t.Fatalf("Pop(st2.first)=%d bytes, want %d bytes", got, want)
467         }
468
469         // Now add data on st1. This should take precedence.
470         ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 4096), false}, st1, nil})
471         wr, ok = ws.Pop()
472         if !ok {
473                 t.Fatalf("Pop(st1)=false, want true")
474         }
475         if got, want := wr.StreamID(), uint32(1); got != want {
476                 t.Fatalf("Pop(st1)=stream %d, want stream %d", got, want)
477         }
478         if got, want := wr.DataSize(), 4096; got != want {
479                 t.Fatalf("Pop(st1)=%d bytes, want %d bytes", got, want)
480         }
481
482         // Should go back to writing 1KB from st2.
483         wr, ok = ws.Pop()
484         if !ok {
485                 t.Fatalf("Pop(st2.last)=false, want true")
486         }
487         if got, want := wr.StreamID(), uint32(2); got != want {
488                 t.Fatalf("Pop(st2.last)=stream %d, want stream %d", got, want)
489         }
490         if got, want := wr.DataSize(), 1024; got != want {
491                 t.Fatalf("Pop(st2.last)=%d bytes, want %d bytes", got, want)
492         }
493 }
494
495 func TestPriorityWeights(t *testing.T) {
496         ws := defaultPriorityWriteScheduler()
497         ws.OpenStream(1, OpenStreamOptions{})
498         ws.OpenStream(2, OpenStreamOptions{})
499
500         sc := &serverConn{maxFrameSize: 8}
501         st1 := &stream{id: 1, sc: sc}
502         st2 := &stream{id: 2, sc: sc}
503         st1.flow.add(40)
504         st2.flow.add(40)
505
506         ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 40), false}, st1, nil})
507         ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 40), false}, st2, nil})
508         ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 34})
509         ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 9})
510
511         // st1 gets 3.5x the bandwidth of st2 (3.5 = (34+1)/(9+1)).
512         // The maximum frame size is 8 bytes. The write sequence should be:
513         //   st1, total bytes so far is (st1=8,  st=0)
514         //   st2, total bytes so far is (st1=8,  st=8)
515         //   st1, total bytes so far is (st1=16, st=8)
516         //   st1, total bytes so far is (st1=24, st=8)   // 3x bandwidth
517         //   st1, total bytes so far is (st1=32, st=8)   // 4x bandwidth
518         //   st2, total bytes so far is (st1=32, st=16)  // 2x bandwidth
519         //   st1, total bytes so far is (st1=40, st=16)
520         //   st2, total bytes so far is (st1=40, st=24)
521         //   st2, total bytes so far is (st1=40, st=32)
522         //   st2, total bytes so far is (st1=40, st=40)
523         if err := checkPopAll(ws, []uint32{1, 2, 1, 1, 1, 2, 1, 2, 2, 2}); err != nil {
524                 t.Error(err)
525         }
526 }
527
528 func TestPriorityRstStreamOnNonOpenStreams(t *testing.T) {
529         ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{
530                 MaxClosedNodesInTree: 0,
531                 MaxIdleNodesInTree:   0,
532         })
533         ws.OpenStream(1, OpenStreamOptions{})
534         ws.CloseStream(1)
535         ws.Push(FrameWriteRequest{write: streamError(1, ErrCodeProtocol)})
536         ws.Push(FrameWriteRequest{write: streamError(2, ErrCodeProtocol)})
537
538         if err := checkPopAll(ws, []uint32{1, 2}); err != nil {
539                 t.Error(err)
540         }
541 }