Skip to content

Commit cb48c59

Browse files
author
Tomoya Usami
committed
Introduce the simpleBuffer as implementation of the httputil.BufferPool.
Signed-off-by: Tomoya Usami <[email protected]>
1 parent 4bc56bb commit cb48c59

File tree

3 files changed

+337
-1
lines changed

3 files changed

+337
-1
lines changed

infra/simple_buffer.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2024 LY Corporation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package infra
16+
17+
import (
18+
"net/http/httputil"
19+
"sync"
20+
"sync/atomic"
21+
)
22+
23+
type simpleBuffer struct {
24+
pool sync.Pool
25+
size *uint64
26+
}
27+
28+
// NewSimpleBuffer implements httputil.BufferPool for providing byte slices of same size.
29+
func NewSimpleBuffer(size uint64) httputil.BufferPool {
30+
if size == 0 {
31+
return nil
32+
}
33+
34+
b := &simpleBuffer{
35+
size: &size,
36+
}
37+
38+
b.pool = sync.Pool{
39+
New: func() interface{} {
40+
return make([]byte, atomic.LoadUint64(b.size))
41+
},
42+
}
43+
44+
return b
45+
}
46+
47+
// Get returns a slice from the pool, and remove it from the pool. New slice may be created when needed.
48+
func (b *simpleBuffer) Get() []byte {
49+
return b.pool.Get().([]byte)
50+
}
51+
52+
// Put adds the given slice back to internal pool.
53+
func (b *simpleBuffer) Put(buf []byte) {
54+
bufCap := cap(buf)
55+
b.pool.Put(buf[0:bufCap])
56+
}

infra/simple_buffer_test.go

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
// Copyright 2024 LY Corporation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package infra
16+
17+
import (
18+
"reflect"
19+
"sync"
20+
"testing"
21+
)
22+
23+
func TestNewSimpleBuffer(t *testing.T) {
24+
type args struct {
25+
size uint64
26+
}
27+
type testcase struct {
28+
name string
29+
args args
30+
want *simpleBuffer
31+
checkFunc func(got, want *simpleBuffer) error
32+
}
33+
tests := []testcase{
34+
{
35+
name: "Check newBuffer, with 0 size",
36+
args: args{
37+
size: 0,
38+
},
39+
want: nil,
40+
checkFunc: func(got, want *simpleBuffer) error {
41+
if !reflect.DeepEqual(got, want) {
42+
return &NotEqualError{"", got, want}
43+
}
44+
return nil
45+
},
46+
},
47+
{
48+
name: "Check newBuffer, positive size",
49+
args: args{
50+
size: 37,
51+
},
52+
want: &simpleBuffer{
53+
size: func(i uint64) *uint64 { return &i }(37),
54+
},
55+
checkFunc: func(got, want *simpleBuffer) error {
56+
if *(got.size) != *(want.size) {
57+
return &NotEqualError{"size", *(got.size), *(want.size)}
58+
}
59+
60+
buffer := got.Get()
61+
if uint64(cap(buffer)) != *(want.size) {
62+
return &NotEqualError{"pool", cap(buffer), *(want.size)}
63+
}
64+
65+
return nil
66+
},
67+
},
68+
}
69+
70+
for _, tt := range tests {
71+
t.Run(tt.name, func(t *testing.T) {
72+
got := NewSimpleBuffer(tt.args.size)
73+
74+
if got == nil && tt.want == nil {
75+
// skip on both nil
76+
return
77+
}
78+
if err := tt.checkFunc(got.(*simpleBuffer), tt.want); err != nil {
79+
t.Errorf("newBuffer() %v", err)
80+
return
81+
}
82+
})
83+
}
84+
}
85+
86+
func TestSimpleBufferGet(t *testing.T) {
87+
type fields struct {
88+
pool sync.Pool
89+
size *uint64
90+
}
91+
type testcase struct {
92+
name string
93+
fields fields
94+
want []byte
95+
}
96+
tests := []testcase{
97+
{
98+
name: "Check simpleBuffer Get, get from internal pool",
99+
fields: fields{
100+
pool: sync.Pool{
101+
New: func() interface{} {
102+
return []byte("pool-new-91")
103+
},
104+
},
105+
},
106+
want: []byte("pool-new-91"),
107+
},
108+
}
109+
110+
for _, tt := range tests {
111+
t.Run(tt.name, func(t *testing.T) {
112+
b := &simpleBuffer{
113+
pool: tt.fields.pool,
114+
size: tt.fields.size,
115+
}
116+
117+
got := b.Get()
118+
if !reflect.DeepEqual(got, tt.want) {
119+
t.Errorf("simpleBuffer.Get() %v", &NotEqualError{"", got, tt.want})
120+
return
121+
}
122+
})
123+
}
124+
}
125+
126+
func TestSimpleBufferPut(t *testing.T) {
127+
type fields struct {
128+
pool sync.Pool
129+
size *uint64
130+
}
131+
type args struct {
132+
buf []byte
133+
}
134+
type testcase struct {
135+
name string
136+
fields fields
137+
args args
138+
checkFunc func(got *simpleBuffer) error
139+
}
140+
tests := []testcase{
141+
{
142+
name: "Check simpleBuffer Put, with 0 size",
143+
fields: fields{
144+
pool: sync.Pool{New: func() interface{} { return make([]byte, 128) }},
145+
size: func(i uint64) *uint64 { return &i }(128),
146+
},
147+
args: args{
148+
buf: make([]byte, 0),
149+
},
150+
checkFunc: func(got *simpleBuffer) error {
151+
wantSize := uint64(128)
152+
wantBufLen := 0
153+
wantBufCap := 0
154+
155+
gotSize := *(got.size)
156+
if gotSize != wantSize {
157+
return &NotEqualError{"size", gotSize, wantSize}
158+
}
159+
160+
gotBuffer := got.Get()
161+
gotBufLen := len(gotBuffer)
162+
if gotBufLen != wantBufLen {
163+
return &NotEqualError{"buffer len", gotBufLen, wantBufLen}
164+
}
165+
gotBufCap := cap(gotBuffer)
166+
if gotBufCap != wantBufCap {
167+
return &NotEqualError{"buffer cap", gotBufCap, wantBufCap}
168+
}
169+
return nil
170+
},
171+
},
172+
{
173+
name: "Check simpleBuffer Put, with buffer len and cap > current size",
174+
fields: fields{
175+
pool: sync.Pool{New: func() interface{} { return make([]byte, 128) }},
176+
size: func(i uint64) *uint64 { return &i }(128),
177+
},
178+
args: args{
179+
buf: make([]byte, 129),
180+
},
181+
checkFunc: func(got *simpleBuffer) error {
182+
wantSize := uint64(128)
183+
wantBufLen := 129
184+
wantBufCap := 129
185+
186+
gotSize := *(got.size)
187+
if gotSize != wantSize {
188+
return &NotEqualError{"size", gotSize, wantSize}
189+
}
190+
191+
gotBuffer := got.Get()
192+
gotBufLen := len(gotBuffer)
193+
if gotBufLen != wantBufLen {
194+
return &NotEqualError{"len(buffer)", gotBufLen, wantBufLen}
195+
}
196+
gotBufCap := cap(gotBuffer)
197+
if gotBufCap != wantBufCap {
198+
return &NotEqualError{"cap(buffer)", gotBufCap, wantBufCap}
199+
}
200+
return nil
201+
},
202+
},
203+
{
204+
name: "Check simpleBuffer Put, with buffer len and cap == current size",
205+
fields: fields{
206+
pool: sync.Pool{New: func() interface{} { return make([]byte, 128) }},
207+
size: func(i uint64) *uint64 { return &i }(128),
208+
},
209+
args: args{
210+
buf: make([]byte, 128),
211+
},
212+
checkFunc: func(got *simpleBuffer) error {
213+
wantSize := uint64(128)
214+
wantBufLen := 128
215+
wantBufCap := 128
216+
217+
gotSize := *(got.size)
218+
if gotSize != wantSize {
219+
return &NotEqualError{"size", gotSize, wantSize}
220+
}
221+
222+
gotBuffer := got.Get()
223+
gotBufLen := len(gotBuffer)
224+
if gotBufLen != wantBufLen {
225+
return &NotEqualError{"len(buffer)", gotBufLen, wantBufLen}
226+
}
227+
gotBufCap := cap(gotBuffer)
228+
if gotBufCap != wantBufCap {
229+
return &NotEqualError{"cap(buffer)", gotBufCap, wantBufCap}
230+
}
231+
return nil
232+
},
233+
},
234+
{
235+
name: "Check simpleBuffer Put, with buffer len > cap",
236+
fields: fields{
237+
pool: sync.Pool{New: func() interface{} { return make([]byte, 128) }},
238+
size: func(i uint64) *uint64 { return &i }(128),
239+
},
240+
args: args{
241+
buf: make([]byte, 129, 256),
242+
},
243+
checkFunc: func(got *simpleBuffer) error {
244+
wantSize := uint64(128)
245+
wantBufLen := 256
246+
wantBufCap := 256
247+
248+
gotSize := *(got.size)
249+
if gotSize != wantSize {
250+
return &NotEqualError{"size", gotSize, wantSize}
251+
}
252+
253+
gotBuffer := got.Get()
254+
gotBufLen := len(gotBuffer)
255+
if gotBufLen != wantBufLen {
256+
return &NotEqualError{"len(buffer)", gotBufLen, wantBufLen}
257+
}
258+
gotBufCap := cap(gotBuffer)
259+
if gotBufCap != wantBufCap {
260+
return &NotEqualError{"cap(buffer)", gotBufCap, wantBufCap}
261+
}
262+
return nil
263+
},
264+
},
265+
}
266+
267+
for _, tt := range tests {
268+
t.Run(tt.name, func(t *testing.T) {
269+
b := &simpleBuffer{
270+
pool: tt.fields.pool,
271+
size: tt.fields.size,
272+
}
273+
b.Put(tt.args.buf)
274+
if err := tt.checkFunc(b); err != nil {
275+
t.Errorf("buffer.Put() %v", err)
276+
return
277+
}
278+
})
279+
}
280+
}

usecase/authz_proxyd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func New(cfg config.Config) (AuthzProxyDaemon, error) {
7373

7474
serverOption := []service.Option{
7575
service.WithServerConfig(cfg.Server),
76-
service.WithRestHandler(handler.New(cfg.Proxy, infra.NewBuffer(cfg.Proxy.BufferSize), athenz, metrics)),
76+
service.WithRestHandler(handler.New(cfg.Proxy, infra.NewSimpleBuffer(cfg.Proxy.BufferSize), athenz, metrics)),
7777
service.WithDebugHandler(debugMux),
7878
service.WithGRPCHandler(gh),
7979
service.WithGRPCCloser(closer),

0 commit comments

Comments
 (0)