-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensuring that compression readers are ensuring the underlying buffer are
closed
- Loading branch information
1 parent
970dcfa
commit 5cf5312
Showing
4 changed files
with
182 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package confighttp // import "go.opentelemetry.io/collector/config/confighttp" | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
) | ||
|
||
type compressionReader[R io.Reader] struct { | ||
io.Reader | ||
orig io.ReadCloser | ||
} | ||
|
||
var ( | ||
_ io.Reader = (*compressionReader[io.Reader])(nil) | ||
_ io.Closer = (*compressionReader[io.Reader])(nil) | ||
) | ||
|
||
// newCompressionReader is used to couple the original underlying buffer and | ||
// the compression reader to allow for close operations to correctly | ||
// free up the underlying buffer that was provided by the original reader | ||
func newCompressionReader[R io.Reader](method func(io.Reader) R, orig io.ReadCloser) io.ReadCloser { | ||
return &compressionReader[R]{ | ||
Reader: method(orig), | ||
orig: orig, | ||
} | ||
} | ||
|
||
func (cr *compressionReader[R]) Close() error { | ||
// taking the original compressed buffer and discarding it | ||
// to ensure the underlying buffers are released | ||
_, err := io.Copy(io.Discard, cr.orig) | ||
return errors.Join(err, cr.orig.Close()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package confighttp | ||
|
||
import ( | ||
"bytes" | ||
"io" | ||
"testing" | ||
"testing/iotest" | ||
|
||
"github.com/golang/snappy" | ||
"github.com/pierrec/lz4/v4" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestCompressionReaders(t *testing.T) { | ||
t.Parallel() | ||
|
||
for _, tc := range []struct { | ||
name string | ||
compress func(testing.TB, []byte) *bytes.Buffer | ||
createFn func(orig io.Reader) (io.ReadCloser, error) | ||
}{ | ||
{ | ||
name: "no compression", | ||
compress: func(_ testing.TB, b []byte) *bytes.Buffer { | ||
return bytes.NewBuffer(b) | ||
}, | ||
createFn: func(orig io.Reader) (io.ReadCloser, error) { | ||
return newCompressionReader( | ||
func(r io.Reader) io.Reader { | ||
return r | ||
}, | ||
io.NopCloser(orig), | ||
), nil | ||
}, | ||
}, | ||
{ | ||
name: "snappy", | ||
compress: compressSnappy, | ||
createFn: func(orig io.Reader) (io.ReadCloser, error) { | ||
return newCompressionReader(snappy.NewReader, io.NopCloser(orig)), nil | ||
}, | ||
}, | ||
{ | ||
name: "lz4", | ||
compress: compressLz4, | ||
createFn: func(orig io.Reader) (io.ReadCloser, error) { | ||
return newCompressionReader(lz4.NewReader, io.NopCloser(orig)), nil | ||
}, | ||
}, | ||
} { | ||
tc := tc | ||
t.Run(tc.name, func(t *testing.T) { | ||
t.Parallel() | ||
data := "hello world" | ||
payload := tc.compress(t, []byte(data)) | ||
|
||
rc, err := tc.createFn(payload) | ||
require.NoError(t, err, "Must not error creating compression reader") | ||
|
||
assert.NoError(t, iotest.TestReader(rc, []byte(data)), "Must pass the expected reader test") | ||
assert.NoError(t, rc.Close(), "Must not error on close") | ||
assert.Zero(t, payload.Len(), "Must have consumed entire payload buffer") | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters