mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-03-31 10:47:35 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
107 lines
3.2 KiB
Go
107 lines
3.2 KiB
Go
package quic
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/refraction-networking/uquic/internal/mocks"
|
|
"github.com/refraction-networking/uquic/internal/protocol"
|
|
"github.com/refraction-networking/uquic/internal/wire"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/onsi/gomega/gbytes"
|
|
)
|
|
|
|
// in the tests for the stream deadlines we set a deadline
|
|
// and wait to make an assertion when Read / Write was unblocked
|
|
// on the CIs, the timing is a lot less precise, so scale every duration by this factor
|
|
func scaleDuration(t time.Duration) time.Duration {
|
|
scaleFactor := 1
|
|
if f, err := strconv.Atoi(os.Getenv("TIMESCALE_FACTOR")); err == nil { // parsing "" errors, so this works fine if the env is not set
|
|
scaleFactor = f
|
|
}
|
|
Expect(scaleFactor).ToNot(BeZero())
|
|
return time.Duration(scaleFactor) * t
|
|
}
|
|
|
|
var _ = Describe("Stream", func() {
|
|
const streamID protocol.StreamID = 1337
|
|
|
|
var (
|
|
str *stream
|
|
strWithTimeout io.ReadWriter // str wrapped with gbytes.Timeout{Reader,Writer}
|
|
mockFC *mocks.MockStreamFlowController
|
|
mockSender *MockStreamSender
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
mockSender = NewMockStreamSender(mockCtrl)
|
|
mockFC = mocks.NewMockStreamFlowController(mockCtrl)
|
|
str = newStream(streamID, mockSender, mockFC)
|
|
|
|
timeout := scaleDuration(250 * time.Millisecond)
|
|
strWithTimeout = struct {
|
|
io.Reader
|
|
io.Writer
|
|
}{
|
|
gbytes.TimeoutReader(str, timeout),
|
|
gbytes.TimeoutWriter(str, timeout),
|
|
}
|
|
})
|
|
|
|
It("gets stream id", func() {
|
|
Expect(str.StreamID()).To(Equal(protocol.StreamID(1337)))
|
|
})
|
|
|
|
Context("deadlines", func() {
|
|
It("sets a write deadline, when SetDeadline is called", func() {
|
|
str.SetDeadline(time.Now().Add(-time.Second))
|
|
n, err := strWithTimeout.Write([]byte("foobar"))
|
|
Expect(err).To(MatchError(errDeadline))
|
|
Expect(n).To(BeZero())
|
|
})
|
|
|
|
It("sets a read deadline, when SetDeadline is called", func() {
|
|
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false).AnyTimes()
|
|
f := &wire.StreamFrame{Data: []byte("foobar")}
|
|
err := str.handleStreamFrame(f)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
str.SetDeadline(time.Now().Add(-time.Second))
|
|
b := make([]byte, 6)
|
|
n, err := strWithTimeout.Read(b)
|
|
Expect(err).To(MatchError(errDeadline))
|
|
Expect(n).To(BeZero())
|
|
})
|
|
})
|
|
|
|
Context("completing", func() {
|
|
It("is not completed when only the receive side is completed", func() {
|
|
// don't EXPECT a call to mockSender.onStreamCompleted()
|
|
str.receiveStream.sender.onStreamCompleted(streamID)
|
|
})
|
|
|
|
It("is not completed when only the send side is completed", func() {
|
|
// don't EXPECT a call to mockSender.onStreamCompleted()
|
|
str.sendStream.sender.onStreamCompleted(streamID)
|
|
})
|
|
|
|
It("is completed when both sides are completed", func() {
|
|
mockSender.EXPECT().onStreamCompleted(streamID)
|
|
str.sendStream.sender.onStreamCompleted(streamID)
|
|
str.receiveStream.sender.onStreamCompleted(streamID)
|
|
})
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Deadline Error", func() {
|
|
It("is a net.Error that wraps os.ErrDeadlineError", func() {
|
|
err := deadlineError{}
|
|
Expect(err.Timeout()).To(BeTrue())
|
|
Expect(errors.Is(err, os.ErrDeadlineExceeded)).To(BeTrue())
|
|
Expect(errors.Unwrap(err)).To(Equal(os.ErrDeadlineExceeded))
|
|
})
|
|
})
|