github.com/MerlinKodo/quic-go@v0.39.2/integrationtests/self/packetization_test.go (about) 1 package self_test 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "time" 8 9 "github.com/MerlinKodo/quic-go" 10 quicproxy "github.com/MerlinKodo/quic-go/integrationtests/tools/proxy" 11 "github.com/MerlinKodo/quic-go/logging" 12 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 ) 16 17 var _ = Describe("Packetization", func() { 18 // In this test, the client sends 100 small messages. The server echoes these messages. 19 // This means that every endpoint will send 100 ack-eliciting packets in short succession. 20 // This test then tests that no more than 110 packets are sent in every direction, making sure that ACK are bundled. 21 It("bundles ACKs", func() { 22 const numMsg = 100 23 24 serverCounter, serverTracer := newPacketTracer() 25 server, err := quic.ListenAddr( 26 "localhost:0", 27 getTLSConfig(), 28 getQuicConfig(&quic.Config{ 29 DisablePathMTUDiscovery: true, 30 Tracer: newTracer(serverTracer), 31 }), 32 ) 33 Expect(err).ToNot(HaveOccurred()) 34 defer server.Close() 35 serverAddr := fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port) 36 37 proxy, err := quicproxy.NewQuicProxy("localhost:0", &quicproxy.Opts{ 38 RemoteAddr: serverAddr, 39 DelayPacket: func(dir quicproxy.Direction, _ []byte) time.Duration { 40 return 5 * time.Millisecond 41 }, 42 }) 43 Expect(err).ToNot(HaveOccurred()) 44 defer proxy.Close() 45 46 clientCounter, clientTracer := newPacketTracer() 47 conn, err := quic.DialAddr( 48 context.Background(), 49 fmt.Sprintf("localhost:%d", proxy.LocalPort()), 50 getTLSClientConfig(), 51 getQuicConfig(&quic.Config{ 52 DisablePathMTUDiscovery: true, 53 Tracer: newTracer(clientTracer), 54 }), 55 ) 56 Expect(err).ToNot(HaveOccurred()) 57 defer conn.CloseWithError(0, "") 58 59 go func() { 60 defer GinkgoRecover() 61 conn, err := server.Accept(context.Background()) 62 Expect(err).ToNot(HaveOccurred()) 63 str, err := conn.AcceptStream(context.Background()) 64 Expect(err).ToNot(HaveOccurred()) 65 b := make([]byte, 1) 66 // Echo every byte received from the client. 67 for { 68 if _, err := str.Read(b); err != nil { 69 break 70 } 71 _, err = str.Write(b) 72 Expect(err).ToNot(HaveOccurred()) 73 } 74 }() 75 76 str, err := conn.OpenStreamSync(context.Background()) 77 Expect(err).ToNot(HaveOccurred()) 78 b := make([]byte, 1) 79 // Send numMsg 1-byte messages. 80 for i := 0; i < numMsg; i++ { 81 _, err = str.Write([]byte{uint8(i)}) 82 Expect(err).ToNot(HaveOccurred()) 83 _, err = str.Read(b) 84 Expect(err).ToNot(HaveOccurred()) 85 Expect(b[0]).To(Equal(uint8(i))) 86 } 87 Expect(conn.CloseWithError(0, "")).To(Succeed()) 88 89 countBundledPackets := func(packets []shortHeaderPacket) (numBundled int) { 90 for _, p := range packets { 91 var hasAck, hasStreamFrame bool 92 for _, f := range p.frames { 93 switch f.(type) { 94 case *logging.AckFrame: 95 hasAck = true 96 case *logging.StreamFrame: 97 hasStreamFrame = true 98 } 99 } 100 if hasAck && hasStreamFrame { 101 numBundled++ 102 } 103 } 104 return 105 } 106 107 numBundledIncoming := countBundledPackets(clientCounter.getRcvdShortHeaderPackets()) 108 numBundledOutgoing := countBundledPackets(serverCounter.getRcvdShortHeaderPackets()) 109 fmt.Fprintf(GinkgoWriter, "bundled incoming packets: %d / %d\n", numBundledIncoming, numMsg) 110 fmt.Fprintf(GinkgoWriter, "bundled outgoing packets: %d / %d\n", numBundledOutgoing, numMsg) 111 Expect(numBundledIncoming).To(And( 112 BeNumerically("<=", numMsg), 113 BeNumerically(">", numMsg*9/10), 114 )) 115 Expect(numBundledOutgoing).To(And( 116 BeNumerically("<=", numMsg), 117 BeNumerically(">", numMsg*9/10), 118 )) 119 }) 120 })