release connection-level flow control credit when a stream is reset

This commit is contained in:
Marten Seemann 2019-01-22 23:45:40 +07:00
parent 1864e301ef
commit 1d7d532035
5 changed files with 99 additions and 26 deletions

View file

@ -458,26 +458,22 @@ var _ = Describe("Receive Stream", func() {
close(done)
}()
Consistently(done).ShouldNot(BeClosed())
err := str.CancelRead(1234)
Expect(err).ToNot(HaveOccurred())
Expect(str.CancelRead(1234)).To(Succeed())
Eventually(done).Should(BeClosed())
})
It("doesn't allow further calls to Read", func() {
mockSender.EXPECT().queueControlFrame(gomock.Any())
err := str.CancelRead(1234)
Expect(err).ToNot(HaveOccurred())
_, err = strWithTimeout.Read([]byte{0})
Expect(str.CancelRead(1234)).To(Succeed())
_, err := strWithTimeout.Read([]byte{0})
Expect(err).To(MatchError("Read on stream 1337 canceled with error code 1234"))
})
It("does nothing when CancelRead is called twice", func() {
mockSender.EXPECT().queueControlFrame(gomock.Any())
err := str.CancelRead(1234)
Expect(err).ToNot(HaveOccurred())
err = str.CancelRead(2345)
Expect(err).ToNot(HaveOccurred())
_, err = strWithTimeout.Read([]byte{0})
Expect(str.CancelRead(1234)).To(Succeed())
Expect(str.CancelRead(1234)).To(Succeed())
_, err := strWithTimeout.Read([]byte{0})
Expect(err).To(MatchError("Read on stream 1337 canceled with error code 1234"))
})
@ -505,7 +501,10 @@ var _ = Describe("Receive Stream", func() {
})
It("doesn't send a STOP_SENDING frame, if the stream was already reset", func() {
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true)
gomock.InOrder(
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true),
mockFC.EXPECT().Abandon(),
)
mockSender.EXPECT().onStreamCompleted(streamID)
Expect(str.handleResetStreamFrame(&wire.ResetStreamFrame{
StreamID: streamID,
@ -513,6 +512,32 @@ var _ = Describe("Receive Stream", func() {
})).To(Succeed())
Expect(str.CancelRead(1234)).To(Succeed())
})
It("sends a STOP_SENDING and completes the stream after receiving the final offset", func() {
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(1000), true)
Expect(str.handleStreamFrame(&wire.StreamFrame{
Offset: 1000,
FinBit: true,
})).To(Succeed())
mockFC.EXPECT().Abandon()
mockSender.EXPECT().queueControlFrame(gomock.Any())
mockSender.EXPECT().onStreamCompleted(streamID)
Expect(str.CancelRead(1234)).To(Succeed())
})
It("completes the stream when receiving the FinBit after the stream was canceled", func() {
mockSender.EXPECT().queueControlFrame(gomock.Any())
Expect(str.CancelRead(1234)).To(Succeed())
gomock.InOrder(
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(1000), true),
mockFC.EXPECT().Abandon(),
)
mockSender.EXPECT().onStreamCompleted(streamID)
Expect(str.handleStreamFrame(&wire.StreamFrame{
Offset: 1000,
FinBit: true,
})).To(Succeed())
})
})
Context("receiving RESET_STREAM frames", func() {
@ -523,7 +548,6 @@ var _ = Describe("Receive Stream", func() {
}
It("unblocks Read", func() {
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true)
done := make(chan struct{})
go func() {
defer GinkgoRecover()
@ -536,16 +560,22 @@ var _ = Describe("Receive Stream", func() {
}()
Consistently(done).ShouldNot(BeClosed())
mockSender.EXPECT().onStreamCompleted(streamID)
gomock.InOrder(
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true),
mockFC.EXPECT().Abandon(),
)
str.handleResetStreamFrame(rst)
Eventually(done).Should(BeClosed())
})
It("doesn't allow further calls to Read", func() {
mockSender.EXPECT().onStreamCompleted(streamID)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true)
err := str.handleResetStreamFrame(rst)
Expect(err).ToNot(HaveOccurred())
_, err = strWithTimeout.Read([]byte{0})
gomock.InOrder(
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true),
mockFC.EXPECT().Abandon(),
)
Expect(str.handleResetStreamFrame(rst)).To(Succeed())
_, err := strWithTimeout.Read([]byte{0})
Expect(err).To(MatchError("Stream 1337 was reset with error code 1234"))
Expect(err).To(BeAssignableToTypeOf(streamCanceledError{}))
Expect(err.(streamCanceledError).Canceled()).To(BeTrue())
@ -561,11 +591,10 @@ var _ = Describe("Receive Stream", func() {
It("ignores duplicate RESET_STREAM frames", func() {
mockSender.EXPECT().onStreamCompleted(streamID)
mockFC.EXPECT().Abandon()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true).Times(2)
err := str.handleResetStreamFrame(rst)
Expect(err).ToNot(HaveOccurred())
err = str.handleResetStreamFrame(rst)
Expect(err).ToNot(HaveOccurred())
Expect(str.handleResetStreamFrame(rst)).To(Succeed())
Expect(str.handleResetStreamFrame(rst)).To(Succeed())
})
It("doesn't do anyting when it was closed for shutdown", func() {