github.com/MerlinKodo/quic-go@v0.39.2/datagram_queue_test.go (about) 1 package quic 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/MerlinKodo/quic-go/internal/utils" 8 "github.com/MerlinKodo/quic-go/internal/wire" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 ) 13 14 var _ = Describe("Datagram Queue", func() { 15 var queue *datagramQueue 16 var queued chan struct{} 17 18 BeforeEach(func() { 19 queued = make(chan struct{}, 100) 20 queue = newDatagramQueue(func() { queued <- struct{}{} }, utils.DefaultLogger) 21 }) 22 23 Context("sending", func() { 24 It("returns nil when there's no datagram to send", func() { 25 Expect(queue.Peek()).To(BeNil()) 26 }) 27 28 It("queues a datagram", func() { 29 done := make(chan struct{}) 30 frame := &wire.DatagramFrame{Data: []byte("foobar")} 31 go func() { 32 defer GinkgoRecover() 33 defer close(done) 34 Expect(queue.AddAndWait(frame)).To(Succeed()) 35 }() 36 37 Eventually(queued).Should(HaveLen(1)) 38 Consistently(done).ShouldNot(BeClosed()) 39 f := queue.Peek() 40 Expect(f.Data).To(Equal([]byte("foobar"))) 41 Eventually(done).Should(BeClosed()) 42 queue.Pop() 43 Expect(queue.Peek()).To(BeNil()) 44 }) 45 46 It("returns the same datagram multiple times, when Pop isn't called", func() { 47 sent := make(chan struct{}, 1) 48 go func() { 49 defer GinkgoRecover() 50 Expect(queue.AddAndWait(&wire.DatagramFrame{Data: []byte("foo")})).To(Succeed()) 51 sent <- struct{}{} 52 Expect(queue.AddAndWait(&wire.DatagramFrame{Data: []byte("bar")})).To(Succeed()) 53 sent <- struct{}{} 54 }() 55 56 Eventually(queued).Should(HaveLen(1)) 57 f := queue.Peek() 58 Expect(f.Data).To(Equal([]byte("foo"))) 59 Eventually(sent).Should(Receive()) 60 Expect(queue.Peek()).To(Equal(f)) 61 Expect(queue.Peek()).To(Equal(f)) 62 queue.Pop() 63 Eventually(func() *wire.DatagramFrame { f = queue.Peek(); return f }).ShouldNot(BeNil()) 64 f = queue.Peek() 65 Expect(f.Data).To(Equal([]byte("bar"))) 66 }) 67 68 It("closes", func() { 69 errChan := make(chan error, 1) 70 go func() { 71 defer GinkgoRecover() 72 errChan <- queue.AddAndWait(&wire.DatagramFrame{Data: []byte("foobar")}) 73 }() 74 75 Consistently(errChan).ShouldNot(Receive()) 76 queue.CloseWithError(errors.New("test error")) 77 Eventually(errChan).Should(Receive(MatchError("test error"))) 78 }) 79 }) 80 81 Context("receiving", func() { 82 It("receives DATAGRAM frames", func() { 83 queue.HandleDatagramFrame(&wire.DatagramFrame{Data: []byte("foo")}) 84 queue.HandleDatagramFrame(&wire.DatagramFrame{Data: []byte("bar")}) 85 data, err := queue.Receive(context.Background()) 86 Expect(err).ToNot(HaveOccurred()) 87 Expect(data).To(Equal([]byte("foo"))) 88 data, err = queue.Receive(context.Background()) 89 Expect(err).ToNot(HaveOccurred()) 90 Expect(data).To(Equal([]byte("bar"))) 91 }) 92 93 It("blocks until a frame is received", func() { 94 c := make(chan []byte, 1) 95 go func() { 96 defer GinkgoRecover() 97 data, err := queue.Receive(context.Background()) 98 Expect(err).ToNot(HaveOccurred()) 99 c <- data 100 }() 101 102 Consistently(c).ShouldNot(Receive()) 103 queue.HandleDatagramFrame(&wire.DatagramFrame{Data: []byte("foobar")}) 104 Eventually(c).Should(Receive(Equal([]byte("foobar")))) 105 }) 106 107 It("blocks until context is done", func() { 108 ctx, cancel := context.WithCancel(context.Background()) 109 errChan := make(chan error) 110 go func() { 111 defer GinkgoRecover() 112 _, err := queue.Receive(ctx) 113 errChan <- err 114 }() 115 116 Consistently(errChan).ShouldNot(Receive()) 117 cancel() 118 Eventually(errChan).Should(Receive(Equal(context.Canceled))) 119 }) 120 121 It("closes", func() { 122 errChan := make(chan error, 1) 123 go func() { 124 defer GinkgoRecover() 125 _, err := queue.Receive(context.Background()) 126 errChan <- err 127 }() 128 129 Consistently(errChan).ShouldNot(Receive()) 130 queue.CloseWithError(errors.New("test error")) 131 Eventually(errChan).Should(Receive(MatchError("test error"))) 132 }) 133 }) 134 })