forked from quic-go/quic-go
For very small sizes, cryptoStream.PopCryptoStream could have returned CRYPTO frames larger than the requested size. Instead, it should return a nil frame.
108 lines
3.5 KiB
Go
108 lines
3.5 KiB
Go
package quic
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/quic-go/quic-go/internal/protocol"
|
|
"github.com/quic-go/quic-go/internal/qerr"
|
|
"github.com/quic-go/quic-go/internal/wire"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCryptoStreamDataAssembly(t *testing.T) {
|
|
str := newCryptoStream()
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("bar"), Offset: 3}))
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("foo")}))
|
|
// receive a retransmission
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("bar"), Offset: 3}))
|
|
|
|
var data []byte
|
|
for {
|
|
b := str.GetCryptoData()
|
|
if b == nil {
|
|
break
|
|
}
|
|
data = append(data, b...)
|
|
}
|
|
require.Equal(t, []byte("foobar"), data)
|
|
}
|
|
|
|
func TestCryptoStreamMaxOffset(t *testing.T) {
|
|
str := newCryptoStream()
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{
|
|
Offset: protocol.MaxCryptoStreamOffset - 5,
|
|
Data: []byte("foo"),
|
|
}))
|
|
require.ErrorIs(t,
|
|
str.HandleCryptoFrame(&wire.CryptoFrame{
|
|
Offset: protocol.MaxCryptoStreamOffset - 2,
|
|
Data: []byte("bar"),
|
|
}),
|
|
&qerr.TransportError{ErrorCode: qerr.CryptoBufferExceeded},
|
|
)
|
|
}
|
|
|
|
func TestCryptoStreamFinishWithQueuedData(t *testing.T) {
|
|
t.Run("with data at current offset", func(t *testing.T) {
|
|
str := newCryptoStream()
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("foo")}))
|
|
require.Equal(t, []byte("foo"), str.GetCryptoData())
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("bar"), Offset: 3}))
|
|
require.ErrorIs(t, str.Finish(), &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
|
|
})
|
|
|
|
t.Run("with data at a higher offset", func(t *testing.T) {
|
|
str := newCryptoStream()
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("foobar"), Offset: 20}))
|
|
require.ErrorIs(t, str.Finish(), &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
|
|
})
|
|
}
|
|
|
|
func TestCryptoStreamReceiveDataAfterFinish(t *testing.T) {
|
|
str := newCryptoStream()
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("foobar")}))
|
|
require.Equal(t, []byte("foobar"), str.GetCryptoData())
|
|
require.NoError(t, str.Finish())
|
|
// receiving a retransmission is ok
|
|
require.NoError(t, str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("bar"), Offset: 3}))
|
|
// but receiving new data is not
|
|
require.ErrorIs(t,
|
|
str.HandleCryptoFrame(&wire.CryptoFrame{Data: []byte("baz"), Offset: 4}),
|
|
&qerr.TransportError{ErrorCode: qerr.ProtocolViolation},
|
|
)
|
|
}
|
|
|
|
func TestCryptoStreamWrite(t *testing.T) {
|
|
expectedCryptoFrameLen := func(offset protocol.ByteCount) protocol.ByteCount {
|
|
f := &wire.CryptoFrame{Offset: offset}
|
|
return f.Length(protocol.Version1)
|
|
}
|
|
|
|
str := newCryptoStream()
|
|
|
|
require.False(t, str.HasData())
|
|
_, err := str.Write([]byte("foo"))
|
|
require.NoError(t, err)
|
|
require.True(t, str.HasData())
|
|
_, err = str.Write([]byte("bar"))
|
|
require.NoError(t, err)
|
|
_, err = str.Write([]byte("baz"))
|
|
require.NoError(t, err)
|
|
require.True(t, str.HasData())
|
|
|
|
for i := range expectedCryptoFrameLen(0) {
|
|
require.Nil(t, str.PopCryptoFrame(i))
|
|
}
|
|
|
|
f := str.PopCryptoFrame(expectedCryptoFrameLen(0) + 1)
|
|
require.Equal(t, &wire.CryptoFrame{Data: []byte("f")}, f)
|
|
require.True(t, str.HasData())
|
|
f = str.PopCryptoFrame(expectedCryptoFrameLen(1) + 3)
|
|
// the three write calls were coalesced into a single frame
|
|
require.Equal(t, &wire.CryptoFrame{Offset: 1, Data: []byte("oob")}, f)
|
|
f = str.PopCryptoFrame(protocol.MaxByteCount)
|
|
require.Equal(t, &wire.CryptoFrame{Offset: 4, Data: []byte("arbaz")}, f)
|
|
require.False(t, str.HasData())
|
|
}
|