@@ -24,7 +24,7 @@ import (
2424 "github.com/stretchr/testify/require"
2525)
2626
27- func TestUpstreamDoQ (t * testing.T ) {
27+ func TestDNSOverQUIC (t * testing.T ) {
2828 tlsConf , rootCAs := createServerTLSConfig (t , "127.0.0.1" )
2929
3030 srv := startDoQServer (t , tlsConf , 0 )
@@ -77,7 +77,7 @@ func TestUpstreamDoQ(t *testing.T) {
7777 checkRaceCondition (u )
7878}
7979
80- func TestUpstream_Exchange_quicServerCloseConn (t * testing.T ) {
80+ func TestDNSOverQUIC_Exchange_quicCloseConn (t * testing.T ) {
8181 // Use the same tlsConf for all servers to preserve the data necessary for
8282 // 0-RTT connections.
8383 tlsConf , rootCAs := createServerTLSConfig (t , "127.0.0.1" )
@@ -129,7 +129,7 @@ func TestUpstream_Exchange_quicServerCloseConn(t *testing.T) {
129129 wg .Wait ()
130130}
131131
132- func TestUpstreamDoQ_serverRestart (t * testing.T ) {
132+ func TestDNSOverQUIC_serverRestart (t * testing.T ) {
133133 t .Parallel ()
134134
135135 // Use the same tlsConf for all servers to preserve the data necessary for
@@ -182,7 +182,7 @@ func TestUpstreamDoQ_serverRestart(t *testing.T) {
182182 })
183183}
184184
185- func TestUpstreamDoQ_0RTT (t * testing.T ) {
185+ func TestDNSOverQUIC_0RTT (t * testing.T ) {
186186 tlsConf , rootCAs := createServerTLSConfig (t , "127.0.0.1" )
187187
188188 srv := startDoQServer (t , tlsConf , 0 )
@@ -232,6 +232,112 @@ func TestUpstreamDoQ_0RTT(t *testing.T) {
232232 require .True (t , conns [1 ].is0RTT ())
233233}
234234
235+ func TestDNSOverQUIC_ReadMsg_partialRead (t * testing.T ) {
236+ oldReq := createHostTestMessage ("old.example" )
237+ oldResp := (& dns.Msg {}).SetReply (oldReq )
238+ oldResp .Answer = []dns.RR {& dns.A {
239+ Hdr : dns.RR_Header {
240+ Name : dns .Fqdn ("old.example" ),
241+ Rrtype : dns .TypeA ,
242+ Class : dns .ClassINET ,
243+ Ttl : 60 ,
244+ },
245+ A : net.IP {192 , 0 , 2 , 1 },
246+ }}
247+
248+ oldPacked , err := oldResp .Pack ()
249+ require .NoError (t , err )
250+
251+ oldBuf := make ([]byte , 2 + len (oldPacked ))
252+ binary .BigEndian .PutUint16 (oldBuf , uint16 (len (oldPacked )))
253+ copy (oldBuf [2 :], oldPacked )
254+
255+ pool := & sync.Pool {
256+ New : func () (buf any ) {
257+ b := make ([]byte , dns .MaxMsgSize )
258+ copy (b , oldBuf )
259+
260+ return & b
261+ },
262+ }
263+
264+ ups , err := newDoQ (& url.URL {Host : "example:853" }, & Options {})
265+ require .NoError (t , err )
266+ testutil .CleanupAndRequireSuccess (t , ups .Close )
267+
268+ doq := testutil .RequireTypeAssert [* dnsOverQUIC ](t , ups )
269+ doq .bytesPool = pool
270+
271+ newAnsIP := net.IP {192 , 0 , 2 , 2 }
272+
273+ newReq := createHostTestMessage ("new.example" )
274+ newResp := (& dns.Msg {}).SetReply (newReq )
275+ newResp .Answer = []dns.RR {& dns.A {
276+ Hdr : dns.RR_Header {
277+ Name : dns .Fqdn ("new.example" ),
278+ Rrtype : dns .TypeA ,
279+ Class : dns .ClassINET ,
280+ Ttl : 60 ,
281+ },
282+ A : newAnsIP ,
283+ }}
284+
285+ newPacked , err := newResp .Pack ()
286+ require .NoError (t , err )
287+
288+ newBuf := make ([]byte , 2 + len (newPacked ))
289+ binary .BigEndian .PutUint16 (newBuf , uint16 (len (newPacked )))
290+ copy (newBuf [2 :], newPacked )
291+
292+ stream := & testQUICStream {
293+ onRead : func (p []byte ) (n int , err error ) {
294+ if len (newBuf ) == 0 {
295+ return 0 , io .EOF
296+ }
297+
298+ n = min (1 , len (newBuf ), len (p ))
299+
300+ copy (p , newBuf [:n ])
301+ newBuf = newBuf [n :]
302+
303+ return n , nil
304+ },
305+ onCancelRead : func (code quic.StreamErrorCode ) {
306+ assert .Equal (t , quic .StreamErrorCode (0 ), code )
307+ },
308+ }
309+
310+ got , err := doq .readMsg (stream )
311+ require .NoError (t , err )
312+ require .Len (t , got .Answer , 1 )
313+
314+ assert .Equal (t , dns .Fqdn ("new.example" ), got .Question [0 ].Name )
315+
316+ a := testutil .RequireTypeAssert [* dns.A ](t , got .Answer [0 ])
317+
318+ assert .Equal (t , newAnsIP , a .A )
319+ }
320+
321+ // testQUICStream is a mock implementation of the [quicStream] interface for
322+ // tests.
323+ type testQUICStream struct {
324+ onRead func (p []byte ) (n int , err error )
325+ onCancelRead func (code quic.StreamErrorCode )
326+ }
327+
328+ // type check
329+ var _ quicStream = (* testQUICStream )(nil )
330+
331+ // Read implements the [quicStream] interface for *testQUICStream.
332+ func (s * testQUICStream ) Read (p []byte ) (n int , err error ) {
333+ return s .onRead (p )
334+ }
335+
336+ // CancelRead implements the [quicStream] interface for *testQUICStream.
337+ func (s * testQUICStream ) CancelRead (code quic.StreamErrorCode ) {
338+ s .onCancelRead (code )
339+ }
340+
235341// testDoHServer is an instance of a test DNS-over-QUIC server.
236342type testDoQServer struct {
237343 // listener is the QUIC connections listener.
0 commit comments