@@ -20,6 +20,7 @@ import (
20
20
"bytes"
21
21
"compress/gzip"
22
22
"encoding/hex"
23
+ "errors"
23
24
"fmt"
24
25
"io"
25
26
"io/ioutil"
@@ -28,7 +29,7 @@ import (
28
29
"reflect"
29
30
"testing"
30
31
31
- "k8s.io/apimachinery/pkg/api/errors"
32
+ kerrors "k8s.io/apimachinery/pkg/api/errors"
32
33
"k8s.io/apimachinery/pkg/runtime"
33
34
"k8s.io/apimachinery/pkg/runtime/schema"
34
35
"k8s.io/apimachinery/pkg/util/diff"
@@ -37,6 +38,76 @@ import (
37
38
featuregatetesting "k8s.io/component-base/featuregate/testing"
38
39
)
39
40
41
+ func TestSerializeObjectParallel (t * testing.T ) {
42
+ largePayload := bytes .Repeat ([]byte ("0123456789abcdef" ), defaultGzipThresholdBytes / 16 + 1 )
43
+ type test struct {
44
+ name string
45
+
46
+ compressionEnabled bool
47
+
48
+ mediaType string
49
+ out []byte
50
+ outErrs []error
51
+ req * http.Request
52
+ statusCode int
53
+ object runtime.Object
54
+
55
+ wantCode int
56
+ wantHeaders http.Header
57
+ wantBody []byte
58
+ }
59
+ newTest := func () test {
60
+ return test {
61
+ name : "compress on gzip" ,
62
+ compressionEnabled : true ,
63
+ out : largePayload ,
64
+ mediaType : "application/json" ,
65
+ req : & http.Request {Header : http.Header {
66
+ "Accept-Encoding" : []string {"gzip" },
67
+ }},
68
+ wantCode : http .StatusOK ,
69
+ wantHeaders : http.Header {
70
+ "Content-Type" : []string {"application/json" },
71
+ "Content-Encoding" : []string {"gzip" },
72
+ "Vary" : []string {"Accept-Encoding" },
73
+ },
74
+ }
75
+ }
76
+ for i := 0 ; i < 100 ; i ++ {
77
+ ctt := newTest ()
78
+ t .Run (ctt .name , func (t * testing.T ) {
79
+ defer func () {
80
+ if r := recover (); r != nil {
81
+ t .Fatalf ("recovered from err %v" , r )
82
+ }
83
+ }()
84
+ t .Parallel ()
85
+ defer featuregatetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , features .APIResponseCompression , ctt .compressionEnabled )()
86
+
87
+ encoder := & fakeEncoder {
88
+ buf : ctt .out ,
89
+ errs : ctt .outErrs ,
90
+ }
91
+ if ctt .statusCode == 0 {
92
+ ctt .statusCode = http .StatusOK
93
+ }
94
+ recorder := & fakeResponseRecorder {
95
+ ResponseRecorder : httptest .NewRecorder (),
96
+ fe : encoder ,
97
+ errorAfterEncoding : true ,
98
+ }
99
+ SerializeObject (ctt .mediaType , encoder , recorder , ctt .req , ctt .statusCode , ctt .object )
100
+ result := recorder .Result ()
101
+ if result .StatusCode != ctt .wantCode {
102
+ t .Fatalf ("unexpected code: %v" , result .StatusCode )
103
+ }
104
+ if ! reflect .DeepEqual (result .Header , ctt .wantHeaders ) {
105
+ t .Fatal (diff .ObjectReflectDiff (ctt .wantHeaders , result .Header ))
106
+ }
107
+ })
108
+ }
109
+ }
110
+
40
111
func TestSerializeObject (t * testing.T ) {
41
112
smallPayload := []byte ("{test-object,test-object}" )
42
113
largePayload := bytes .Repeat ([]byte ("0123456789abcdef" ), defaultGzipThresholdBytes / 16 + 1 )
@@ -111,7 +182,7 @@ func TestSerializeObject(t *testing.T) {
111
182
{
112
183
name : "fail to encode object or status with status code" ,
113
184
out : smallPayload ,
114
- outErrs : []error {errors .NewNotFound (schema.GroupResource {}, "test" ), fmt .Errorf ("bad2" )},
185
+ outErrs : []error {kerrors .NewNotFound (schema.GroupResource {}, "test" ), fmt .Errorf ("bad2" )},
115
186
mediaType : "application/json" ,
116
187
req : & http.Request {Header : http.Header {}},
117
188
statusCode : http .StatusOK ,
@@ -123,7 +194,7 @@ func TestSerializeObject(t *testing.T) {
123
194
{
124
195
name : "fail to encode object or status with status code and keeps previous error" ,
125
196
out : smallPayload ,
126
- outErrs : []error {errors .NewNotFound (schema.GroupResource {}, "test" ), fmt .Errorf ("bad2" )},
197
+ outErrs : []error {kerrors .NewNotFound (schema.GroupResource {}, "test" ), fmt .Errorf ("bad2" )},
127
198
mediaType : "application/json" ,
128
199
req : & http.Request {Header : http.Header {}},
129
200
statusCode : http .StatusNotAcceptable ,
@@ -270,10 +341,25 @@ func TestSerializeObject(t *testing.T) {
270
341
}
271
342
}
272
343
344
+ type fakeResponseRecorder struct {
345
+ * httptest.ResponseRecorder
346
+ fe * fakeEncoder
347
+ errorAfterEncoding bool
348
+ }
349
+
350
+ func (frw * fakeResponseRecorder ) Write (buf []byte ) (int , error ) {
351
+ if frw .errorAfterEncoding && frw .fe .encodeCalled {
352
+ return 0 , errors .New ("returning a requested error" )
353
+ }
354
+ return frw .ResponseRecorder .Write (buf )
355
+ }
356
+
273
357
type fakeEncoder struct {
274
358
obj runtime.Object
275
359
buf []byte
276
360
errs []error
361
+
362
+ encodeCalled bool
277
363
}
278
364
279
365
func (e * fakeEncoder ) Encode (obj runtime.Object , w io.Writer ) error {
@@ -284,6 +370,7 @@ func (e *fakeEncoder) Encode(obj runtime.Object, w io.Writer) error {
284
370
return err
285
371
}
286
372
_ , err := w .Write (e .buf )
373
+ e .encodeCalled = true
287
374
return err
288
375
}
289
376
0 commit comments