Repository: quic-go/quic-go
Pull request #4494 (2024-05-07 01:21:32)

ci: update golangci-lint-action to v6 and golangci-lint to v1.58.0

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/quic-go/quic-go/pull/4494?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 85.13%. Comparing base [(`03a32d0`)](https://app.codecov.io/gh/quic-go/quic-go/commit/03a32d0daa232fef3313726e244bc7b56eb88bcc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) to head [(`f916a92`)](https://app.codecov.io/gh/quic-go/quic-go/pull/4494?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4494      +/-   ##
==========================================
- Coverage   85.17%   85.13%   -0.04%     
==========================================
  Files         154      151       -3     
  Lines       14756    14478     -278     
==========================================
- Hits        12567    12325     -242     
+ Misses       1684     1666      -18     
+ Partials      505      487      -18     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/quic-go/quic-go/pull/4494?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).


Patch:
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index f1990ceb..2f9f95bb 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -40,7 +40,7 @@ jobs:
       matrix:
         go: [  "1.21.x", "1.22.x" ]
     env:
-      GOLANGCI_LINT_VERSION: v1.56.1
+      GOLANGCI_LINT_VERSION: v1.58.0
     name: golangci-lint (Go ${{ matrix.go }})
     steps:
       - uses: actions/checkout@v4
@@ -48,44 +48,39 @@ jobs:
         with:
           go-version: ${{ matrix.go }}
       - name: golangci-lint (Linux)
-        uses: golangci/golangci-lint-action@v5
+        uses: golangci/golangci-lint-action@v6
         with:
-          skip-pkg-cache: true
           args: --timeout=3m
           version: ${{ env.GOLANGCI_LINT_VERSION }}
       - name: golangci-lint (Windows)
         if: success() || failure() # run this step even if the previous one failed
-        uses: golangci/golangci-lint-action@v5
+        uses: golangci/golangci-lint-action@v6
         env:
           GOOS: "windows"
         with:
-          skip-pkg-cache: true
           args: --timeout=3m
           version: ${{ env.GOLANGCI_LINT_VERSION }}
       - name: golangci-lint (OSX)
         if: success() || failure() # run this step even if the previous one failed
-        uses: golangci/golangci-lint-action@v5
+        uses: golangci/golangci-lint-action@v6
         env:
           GOOS: "darwin"
         with:
-          skip-pkg-cache: true
           args: --timeout=3m
           version: ${{ env.GOLANGCI_LINT_VERSION }}
       - name: golangci-lint (FreeBSD)
         if: success() || failure() # run this step even if the previous one failed
-        uses: golangci/golangci-lint-action@v5
+        uses: golangci/golangci-lint-action@v6
         env:
           GOOS: "freebsd"
         with:
-          skip-pkg-cache: true
           args: --timeout=3m
           version: ${{ env.GOLANGCI_LINT_VERSION }}
       - name: golangci-lint (others)
         if: success() || failure() # run this step even if the previous one failed
-        uses: golangci/golangci-lint-action@v5
+        uses: golangci/golangci-lint-action@v6
         env:
           GOOS: "solaris" # some OS that we don't have any build tags for
         with:
-          skip-pkg-cache: true
           args: --timeout=3m
           version: ${{ env.GOLANGCI_LINT_VERSION }}
diff --git a/.golangci.yml b/.golangci.yml
index daa3e38e..7fc11de4 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,6 +1,3 @@
-run:
-  skip-files:
-    - internal/handshake/cipher_suite.go
 linters-settings:
   misspell:
     ignore-words:
@@ -26,6 +23,7 @@ linters:
     - gofmt # redundant, since gofmt *should* be a no-op after gofumpt
     - gofumpt
     - gosimple
+    - govet
     - ineffassign
     - misspell
     - prealloc
@@ -34,9 +32,10 @@ linters:
     - unconvert
     - unparam
     - unused
-    - vet
 
 issues:
+  exclude-files:
+    - internal/handshake/cipher_suite.go
   exclude-rules:
     - path: internal/qtls
       linters:
diff --git a/http3/state_tracking_stream.go b/http3/state_tracking_stream.go
index 4a73460e..a5cd834c 100644
--- a/http3/state_tracking_stream.go
+++ b/http3/state_tracking_stream.go
@@ -3,6 +3,7 @@ package http3
 import (
 	"context"
 	"errors"
+	"os"
 	"sync"
 
 	"github.com/quic-go/quic-go"
@@ -75,7 +76,7 @@ func (s *stateTrackingStream) CancelWrite(e quic.StreamErrorCode) {
 
 func (s *stateTrackingStream) Write(b []byte) (int, error) {
 	n, err := s.Stream.Write(b)
-	if err != nil {
+	if err != nil && !errors.Is(err, os.ErrDeadlineExceeded) {
 		s.closeSend(err)
 	}
 	return n, err
@@ -88,7 +89,7 @@ func (s *stateTrackingStream) CancelRead(e quic.StreamErrorCode) {
 
 func (s *stateTrackingStream) Read(b []byte) (int, error) {
 	n, err := s.Stream.Read(b)
-	if err != nil {
+	if err != nil && !errors.Is(err, os.ErrDeadlineExceeded) {
 		s.closeReceive(err)
 	}
 	return n, err


Test patch:
diff --git a/http3/state_tracking_stream_test.go b/http3/state_tracking_stream_test.go
index 4bf1e227..e900cf1a 100644
--- a/http3/state_tracking_stream_test.go
+++ b/http3/state_tracking_stream_test.go
@@ -5,6 +5,7 @@ import (
 	"context"
 	"errors"
 	"io"
+	"os"
 
 	"github.com/quic-go/quic-go"
 	mockquic "github.com/quic-go/quic-go/internal/mocks/quic"
@@ -43,7 +44,7 @@ var _ = Describe("State Tracking Stream", func() {
 		Expect(states[0].err).To(Equal(io.EOF))
 	})
 
-	It("recognizes read cancellations", func() {
+	It("recognizes local read cancellations", func() {
 		qstr := mockquic.NewMockStream(mockCtrl)
 		qstr.EXPECT().StreamID().AnyTimes()
 		qstr.EXPECT().Context().Return(context.Background()).AnyTimes()
@@ -64,6 +65,39 @@ var _ = Describe("State Tracking Stream", func() {
 		Expect(states[0].err).To(Equal(&quic.StreamError{ErrorCode: 1337}))
 	})
 
+	It("recognizes remote cancellations", func() {
+		qstr := mockquic.NewMockStream(mockCtrl)
+		qstr.EXPECT().StreamID().AnyTimes()
+		qstr.EXPECT().Context().Return(context.Background()).AnyTimes()
+		var states []stateTransition
+		str := newStateTrackingStream(qstr, func(state streamState, err error) {
+			states = append(states, stateTransition{state, err})
+		})
+
+		testErr := errors.New("test error")
+		qstr.EXPECT().Read(gomock.Any()).Return(0, testErr)
+		_, err := str.Read(make([]byte, 3))
+		Expect(err).To(MatchError(testErr))
+		Expect(states).To(HaveLen(1))
+		Expect(states[0].state).To(Equal(streamStateReceiveClosed))
+		Expect(states[0].err).To(MatchError(testErr))
+	})
+
+	It("doesn't misinterpret read deadline errors", func() {
+		qstr := mockquic.NewMockStream(mockCtrl)
+		qstr.EXPECT().StreamID().AnyTimes()
+		qstr.EXPECT().Context().Return(context.Background()).AnyTimes()
+		var states []stateTransition
+		str := newStateTrackingStream(qstr, func(state streamState, err error) {
+			states = append(states, stateTransition{state, err})
+		})
+
+		qstr.EXPECT().Read(gomock.Any()).Return(0, os.ErrDeadlineExceeded)
+		_, err := str.Read(make([]byte, 3))
+		Expect(err).To(MatchError(os.ErrDeadlineExceeded))
+		Expect(states).To(BeEmpty())
+	})
+
 	It("recognizes when the send side is closed, when write errors", func() {
 		qstr := mockquic.NewMockStream(mockCtrl)
 		qstr.EXPECT().StreamID().AnyTimes()
@@ -86,6 +120,22 @@ var _ = Describe("State Tracking Stream", func() {
 		Expect(states[0].err).To(Equal(testErr))
 	})
 
+	It("recognizes when the send side is closed, when write errors", func() {
+		qstr := mockquic.NewMockStream(mockCtrl)
+		qstr.EXPECT().StreamID().AnyTimes()
+		qstr.EXPECT().Context().Return(context.Background()).AnyTimes()
+		var states []stateTransition
+		str := newStateTrackingStream(qstr, func(state streamState, err error) {
+			states = append(states, stateTransition{state, err})
+		})
+
+		qstr.EXPECT().Write([]byte("foo")).Return(0, os.ErrDeadlineExceeded)
+		Expect(states).To(BeEmpty())
+		_, err := str.Write([]byte("foo"))
+		Expect(err).To(MatchError(os.ErrDeadlineExceeded))
+		Expect(states).To(BeEmpty())
+	})
+
 	It("recognizes when the send side is closed, when CancelWrite is called", func() {
 		qstr := mockquic.NewMockStream(mockCtrl)
 		qstr.EXPECT().StreamID().AnyTimes()