Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix WithCompression to match docs; add tests #493

Merged
merged 2 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compression.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ func newCompressionPool(
newDecompressor func() Decompressor,
newCompressor func() Compressor,
) *compressionPool {
if newDecompressor == nil && newCompressor == nil {
akshayjshah marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
return &compressionPool{
decompressors: sync.Pool{
New: func() any { return newDecompressor() },
Expand Down
107 changes: 107 additions & 0 deletions compression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,110 @@ func TestAcceptEncodingOrdering(t *testing.T) {
_, _ = client.CallUnary(context.Background(), NewRequest(&emptypb.Empty{}))
assert.True(t, called)
}

func TestClientCompressionOptionTest(t *testing.T) {
t.Parallel()
const testURL = "http://foo.bar.com/service/method"

checkPools := func(t *testing.T, config *clientConfig) {
t.Helper()
assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
for _, name := range config.CompressionNames {
pool := config.CompressionPools[name]
assert.NotNil(t, pool)
}
}
dummyDecompressCtor := func() Decompressor { return nil }
dummyCompressCtor := func() Compressor { return nil }

t.Run("defaults", func(t *testing.T) {
t.Parallel()
config, err := newClientConfig(testURL, nil)
assert.Nil(t, err)
assert.Equal(t, config.CompressionNames, []string{compressionGzip})
checkPools(t, config)
})
t.Run("WithAcceptCompression", func(t *testing.T) {
t.Parallel()
opts := []ClientOption{WithAcceptCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
config, err := newClientConfig(testURL, opts)
assert.Nil(t, err)
assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
checkPools(t, config)
})
t.Run("WithAcceptCompression-empty-name-noop", func(t *testing.T) {
t.Parallel()
opts := []ClientOption{WithAcceptCompression("", dummyDecompressCtor, dummyCompressCtor)}
config, err := newClientConfig(testURL, opts)
assert.Nil(t, err)
assert.Equal(t, config.CompressionNames, []string{compressionGzip})
checkPools(t, config)
})
t.Run("WithAcceptCompression-nil-ctors-noop", func(t *testing.T) {
t.Parallel()
opts := []ClientOption{WithAcceptCompression("foo", nil, nil)}
config, err := newClientConfig(testURL, opts)
assert.Nil(t, err)
assert.Equal(t, config.CompressionNames, []string{compressionGzip})
checkPools(t, config)
})
t.Run("WithAcceptCompression-nil-ctors-unregisters", func(t *testing.T) {
t.Parallel()
opts := []ClientOption{WithAcceptCompression("gzip", nil, nil)}
config, err := newClientConfig(testURL, opts)
assert.Nil(t, err)
assert.Equal(t, config.CompressionNames, nil)
checkPools(t, config)
})
}

func TestHandlerCompressionOptionTest(t *testing.T) {
t.Parallel()
const testProc = "/service/method"

checkPools := func(t *testing.T, config *handlerConfig) {
t.Helper()
assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
for _, name := range config.CompressionNames {
pool := config.CompressionPools[name]
assert.NotNil(t, pool)
}
}
dummyDecompressCtor := func() Decompressor { return nil }
dummyCompressCtor := func() Compressor { return nil }

t.Run("defaults", func(t *testing.T) {
t.Parallel()
config := newHandlerConfig(testProc, nil)
assert.Equal(t, config.CompressionNames, []string{compressionGzip})
checkPools(t, config)
})
t.Run("WithCompression", func(t *testing.T) {
t.Parallel()
opts := []HandlerOption{WithCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
config := newHandlerConfig(testProc, opts)
assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
checkPools(t, config)
})
t.Run("WithCompression-empty-name-noop", func(t *testing.T) {
t.Parallel()
opts := []HandlerOption{WithCompression("", dummyDecompressCtor, dummyCompressCtor)}
config := newHandlerConfig(testProc, opts)
assert.Equal(t, config.CompressionNames, []string{compressionGzip})
checkPools(t, config)
})
t.Run("WithCompression-nil-ctors-noop", func(t *testing.T) {
t.Parallel()
opts := []HandlerOption{WithCompression("foo", nil, nil)}
config := newHandlerConfig(testProc, opts)
assert.Equal(t, config.CompressionNames, []string{compressionGzip})
checkPools(t, config)
})
t.Run("WithCompression-nil-ctors-unregisters", func(t *testing.T) {
t.Parallel()
opts := []HandlerOption{WithCompression("gzip", nil, nil)}
config := newHandlerConfig(testProc, opts)
assert.Equal(t, config.CompressionNames, nil)
checkPools(t, config)
})
}
39 changes: 20 additions & 19 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,13 @@ type ClientOption interface {
// Clients accept gzipped responses by default, using a compressor backed by the
// standard library's [gzip] package with the default compression level. Use
// [WithSendGzip] to compress requests with gzip.
//
// Calling WithAcceptCompression with an empty name is a no-op.
func WithAcceptCompression(
name string,
newDecompressor func() Decompressor,
newCompressor func() Compressor,
) ClientOption {
if newDecompressor == nil && newCompressor == nil {
return &compressionOption{Name: name}
}
return &compressionOption{
Name: name,
CompressionPool: newCompressionPool(newDecompressor, newCompressor),
Expand Down Expand Up @@ -93,7 +92,7 @@ func WithSendCompression(name string) ClientOption {

// WithSendGzip configures the client to gzip requests. Since clients have
// access to a gzip compressor by default, WithSendGzip doesn't require
// [WithSendCompresion].
// [WithSendCompression].
//
// Some servers don't support gzip, so clients default to sending uncompressed
// requests.
Expand All @@ -116,9 +115,11 @@ type HandlerOption interface {
// compressors and decompressors.
//
// By default, handlers support gzip using the standard library's
// [compress/gzip] package at the default compression level.
// [compress/gzip] package at the default compression level. To remove support for
// a previously-registered compression algorithm, use WithCompression with nil
// decompressor and compressor constructors.
//
// Calling WithCompression with an empty name or nil constructors is a no-op.
// Calling WithCompression with an empty name is a no-op.
func WithCompression(
name string,
newDecompressor func() Decompressor,
Expand Down Expand Up @@ -320,31 +321,31 @@ type compressionOption struct {
}

func (o *compressionOption) applyToClient(config *clientConfig) {
o.apply(&config.CompressionNames, config.CompressionPools)
}

func (o *compressionOption) applyToHandler(config *handlerConfig) {
o.apply(&config.CompressionNames, config.CompressionPools)
}

func (o *compressionOption) apply(configuredNames *[]string, configuredPools map[string]*compressionPool) {
if o.Name == "" {
return
}
if o.CompressionPool == nil {
delete(config.CompressionPools, o.Name)
delete(configuredPools, o.Name)
var names []string
for _, name := range config.CompressionNames {
for _, name := range *configuredNames {
if name == o.Name {
continue
}
names = append(names, name)
}
config.CompressionNames = names
return
}
config.CompressionPools[o.Name] = o.CompressionPool
config.CompressionNames = append(config.CompressionNames, o.Name)
}

func (o *compressionOption) applyToHandler(config *handlerConfig) {
if o.Name == "" || o.CompressionPool == nil {
*configuredNames = names
return
}
config.CompressionPools[o.Name] = o.CompressionPool
config.CompressionNames = append(config.CompressionNames, o.Name)
configuredPools[o.Name] = o.CompressionPool
*configuredNames = append(*configuredNames, o.Name)
}

type compressMinBytesOption struct {
Expand Down