github.com/tumi8/quic-go@v0.37.4-tum/integrationtests/self/stream_test.go (about) 1 package self_test 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "net" 8 "sync" 9 10 "github.com/tumi8/quic-go" 11 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Bidirectional streams", func() { 17 const numStreams = 300 18 19 var ( 20 server *quic.Listener 21 serverAddr string 22 ) 23 24 BeforeEach(func() { 25 var err error 26 server, err = quic.ListenAddr("localhost:0", getTLSConfig(), getQuicConfig(nil)) 27 Expect(err).ToNot(HaveOccurred()) 28 serverAddr = fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port) 29 }) 30 31 AfterEach(func() { 32 server.Close() 33 }) 34 35 runSendingPeer := func(conn quic.Connection) { 36 var wg sync.WaitGroup 37 wg.Add(numStreams) 38 for i := 0; i < numStreams; i++ { 39 str, err := conn.OpenStreamSync(context.Background()) 40 Expect(err).ToNot(HaveOccurred()) 41 data := GeneratePRData(25 * i) 42 go func() { 43 defer GinkgoRecover() 44 _, err := str.Write(data) 45 Expect(err).ToNot(HaveOccurred()) 46 Expect(str.Close()).To(Succeed()) 47 }() 48 go func() { 49 defer GinkgoRecover() 50 defer wg.Done() 51 dataRead, err := io.ReadAll(str) 52 Expect(err).ToNot(HaveOccurred()) 53 Expect(dataRead).To(Equal(data)) 54 }() 55 } 56 wg.Wait() 57 } 58 59 runReceivingPeer := func(conn quic.Connection) { 60 var wg sync.WaitGroup 61 wg.Add(numStreams) 62 for i := 0; i < numStreams; i++ { 63 str, err := conn.AcceptStream(context.Background()) 64 Expect(err).ToNot(HaveOccurred()) 65 go func() { 66 defer GinkgoRecover() 67 defer wg.Done() 68 // shouldn't use io.Copy here 69 // we should read from the stream as early as possible, to free flow control credit 70 data, err := io.ReadAll(str) 71 Expect(err).ToNot(HaveOccurred()) 72 _, err = str.Write(data) 73 Expect(err).ToNot(HaveOccurred()) 74 Expect(str.Close()).To(Succeed()) 75 }() 76 } 77 wg.Wait() 78 } 79 80 It(fmt.Sprintf("client opening %d streams to a server", numStreams), func() { 81 var conn quic.Connection 82 go func() { 83 defer GinkgoRecover() 84 var err error 85 conn, err = server.Accept(context.Background()) 86 Expect(err).ToNot(HaveOccurred()) 87 runReceivingPeer(conn) 88 }() 89 90 client, err := quic.DialAddr( 91 context.Background(), 92 serverAddr, 93 getTLSClientConfig(), 94 getQuicConfig(nil), 95 ) 96 Expect(err).ToNot(HaveOccurred()) 97 runSendingPeer(client) 98 client.CloseWithError(0, "") 99 <-conn.Context().Done() 100 }) 101 102 It(fmt.Sprintf("server opening %d streams to a client", numStreams), func() { 103 go func() { 104 defer GinkgoRecover() 105 conn, err := server.Accept(context.Background()) 106 Expect(err).ToNot(HaveOccurred()) 107 runSendingPeer(conn) 108 conn.CloseWithError(0, "") 109 }() 110 111 client, err := quic.DialAddr( 112 context.Background(), 113 serverAddr, 114 getTLSClientConfig(), 115 getQuicConfig(nil), 116 ) 117 Expect(err).ToNot(HaveOccurred()) 118 runReceivingPeer(client) 119 Eventually(client.Context().Done()).Should(BeClosed()) 120 }) 121 122 It(fmt.Sprintf("client and server opening %d each and sending data to the peer", numStreams), func() { 123 done1 := make(chan struct{}) 124 go func() { 125 defer GinkgoRecover() 126 conn, err := server.Accept(context.Background()) 127 Expect(err).ToNot(HaveOccurred()) 128 done := make(chan struct{}) 129 go func() { 130 defer GinkgoRecover() 131 runReceivingPeer(conn) 132 close(done) 133 }() 134 runSendingPeer(conn) 135 <-done 136 close(done1) 137 }() 138 139 client, err := quic.DialAddr( 140 context.Background(), 141 serverAddr, 142 getTLSClientConfig(), 143 getQuicConfig(nil), 144 ) 145 Expect(err).ToNot(HaveOccurred()) 146 done2 := make(chan struct{}) 147 go func() { 148 defer GinkgoRecover() 149 runSendingPeer(client) 150 close(done2) 151 }() 152 runReceivingPeer(client) 153 <-done1 154 <-done2 155 client.CloseWithError(0, "") 156 }) 157 })