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  })