Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f99076c

Browse filesBrowse files
committed
test: close response body in watch tests
- Close response body after http calls in the watch tests - Add apitesting utility methods for closing and testing errors from response body and websocket. - Validate read after close errors.
1 parent 08bbc5b commit f99076c
Copy full SHA for f99076c

File tree

Expand file treeCollapse file tree

4 files changed

+194
-21
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+194
-21
lines changed
+104Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package apitesting
18+
19+
import (
20+
"errors"
21+
"fmt"
22+
"io"
23+
"strings"
24+
)
25+
26+
// errReadOnClosedResBody is returned by methods in the "http" package, when
27+
// reading from a response body after it's been closed.
28+
// Detecting this error is required because read is not cancellable.
29+
// From https://github.com/golang/go/blob/go1.20/src/net/http/transport.go#L2779
30+
var errReadOnClosedResBody = errors.New("http: read on closed response body")
31+
32+
// errCloseOnClosedWebSocket is returned by methods in the "k8s.io/utils/net"
33+
// package, when accepting or closing a websocket multiListener that is already
34+
// closed.
35+
var errCloseOnClosedWebSocket = fmt.Errorf("use of closed network connection")
36+
37+
// AssertReadOnClosedBodyError fails the test if the error indicates that the
38+
// HTTP response body was read from after being closed.
39+
func AssertReadOnClosedBodyError(t TestingT, err error) {
40+
t.Helper()
41+
assertEqualError(t, err, errReadOnClosedResBody.Error())
42+
}
43+
44+
// AssertWebSocketClosedError fails the test if the error indicates that the
45+
// WebSocket was read from or written to after being closed.
46+
func AssertWebSocketClosedError(t TestingT, err error) {
47+
t.Helper()
48+
// The expected error is a net.OpError instance, but we don't know the
49+
// operation, source, or destination, so we can't match the exact error.
50+
assertErrorContains(t, err, errCloseOnClosedWebSocket.Error())
51+
}
52+
53+
// Close closes the closer and fails the test if close errors.
54+
//
55+
// Defer when your test does not need to fully read or drain the response body
56+
// before ending.
57+
func Close(t TestingT, body io.Closer) {
58+
t.Helper()
59+
assertNoError(t, body.Close())
60+
}
61+
62+
// TestingT simulates assert.TestingT and assert.tHelper without requiring an
63+
// extra non-test dependency.
64+
type TestingT interface {
65+
Errorf(format string, args ...interface{})
66+
Helper()
67+
}
68+
69+
// assertEqualError simulates assert.EqualError without requiring an extra
70+
// non-test dependency. Use github.com/stretchr/testify/assert for tests.
71+
func assertEqualError(t TestingT, err error, errString string) {
72+
t.Helper()
73+
if err == nil {
74+
t.Errorf("An error is expected but got nil.")
75+
return
76+
}
77+
expected := errString
78+
actual := err.Error()
79+
if expected != actual {
80+
t.Errorf("Error message not equal:\n"+
81+
"expected: %q\n"+
82+
"actual : %q", expected, actual)
83+
}
84+
}
85+
86+
// assertErrorContains simulates assert.ErrorContains without requiring an extra
87+
// non-test dependency. Use github.com/stretchr/testify/assert for tests.
88+
func assertErrorContains(t TestingT, err error, substr string) {
89+
t.Helper()
90+
if err == nil {
91+
t.Errorf("An error is expected but got nil.")
92+
} else if !strings.Contains(err.Error(), substr) {
93+
t.Errorf("Error %#v does not contain %#v", err, substr)
94+
}
95+
}
96+
97+
// assertNoError simulates assert.NoError without requiring an extra non-test
98+
// dependency. Use github.com/stretchr/testify/assert for tests.
99+
func assertNoError(t TestingT, err error) {
100+
t.Helper()
101+
if err != nil {
102+
t.Errorf("Received unexpected error:\n%+v", err)
103+
}
104+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.