Wrote pool config and tests.
This commit is contained in:
169
config.go
169
config.go
@@ -13,6 +13,82 @@ type CloseHandler func(code int, text string) error
|
|||||||
|
|
||||||
type PoolConfig struct {
|
type PoolConfig struct {
|
||||||
ConnectionConfig *ConnectionConfig
|
ConnectionConfig *ConnectionConfig
|
||||||
|
IdleTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type PoolOption func(*PoolConfig) error
|
||||||
|
|
||||||
|
func NewPoolConfig(options ...PoolOption) (*PoolConfig, error) {
|
||||||
|
conf := GetDefaultPoolConfig()
|
||||||
|
if err := applyPoolOptions(conf, options...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := validatePoolConfig(conf); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDefaultPoolConfig() *PoolConfig {
|
||||||
|
return &PoolConfig{
|
||||||
|
IdleTimeout: 20 * time.Second,
|
||||||
|
ConnectionConfig: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyPoolOptions(config *PoolConfig, options ...PoolOption) error {
|
||||||
|
for _, option := range options {
|
||||||
|
if err := option(config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validatePoolConfig(config *PoolConfig) error {
|
||||||
|
err := validateIdleTimeout(config.IdleTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.ConnectionConfig != nil {
|
||||||
|
err = validateConnectionConfig(config.ConnectionConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateIdleTimeout(value time.Duration) error {
|
||||||
|
if value < 0 {
|
||||||
|
return errors.InvalidIdleTimeout
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// When IdleTimeout is set to zero, idle timeouts are disabled.
|
||||||
|
func WithIdleTimeout(value time.Duration) PoolOption {
|
||||||
|
return func(c *PoolConfig) error {
|
||||||
|
err := validateIdleTimeout(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.IdleTimeout = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithConnectionConfig(cc *ConnectionConfig) PoolOption {
|
||||||
|
return func(c *PoolConfig) error {
|
||||||
|
err := validateConnectionConfig(cc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.ConnectionConfig = cc
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection Config
|
// Connection Config
|
||||||
@@ -70,7 +146,32 @@ func applyConnectionOptions(config *ConnectionConfig, options ...ConnectionOptio
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateConnectionConfig(config *ConnectionConfig) error {
|
func validateConnectionConfig(config *ConnectionConfig) error {
|
||||||
|
err := validateWriteTimeout(config.WriteTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if config.Retry != nil {
|
if config.Retry != nil {
|
||||||
|
err = validateMaxRetries(config.Retry.MaxRetries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validateInitialDelay(config.Retry.InitialDelay)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validateMaxDelay(config.Retry.MaxDelay)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validateJitterFactor(config.Retry.JitterFactor)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if config.Retry.InitialDelay > config.Retry.MaxDelay {
|
if config.Retry.InitialDelay > config.Retry.MaxDelay {
|
||||||
return errors.NewConfigError("initial delay may not exceed maximum delay")
|
return errors.NewConfigError("initial delay may not exceed maximum delay")
|
||||||
}
|
}
|
||||||
@@ -79,7 +180,40 @@ func validateConnectionConfig(config *ConnectionConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration Options
|
func validateWriteTimeout(value time.Duration) error {
|
||||||
|
if value < 0 {
|
||||||
|
return errors.InvalidWriteTimeout
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateMaxRetries(value int) error {
|
||||||
|
if value < 0 {
|
||||||
|
return errors.InvalidRetryMaxRetries
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateInitialDelay(value time.Duration) error {
|
||||||
|
if value <= 0 {
|
||||||
|
return errors.InvalidRetryInitialDelay
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateMaxDelay(value time.Duration) error {
|
||||||
|
if value <= 0 {
|
||||||
|
return errors.InvalidRetryMaxDelay
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateJitterFactor(value float64) error {
|
||||||
|
if value < 0.0 || value > 1.0 {
|
||||||
|
return errors.InvalidRetryJitterFactor
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func WithCloseHandler(handler CloseHandler) ConnectionOption {
|
func WithCloseHandler(handler CloseHandler) ConnectionOption {
|
||||||
return func(c *ConnectionConfig) error {
|
return func(c *ConnectionConfig) error {
|
||||||
@@ -91,8 +225,9 @@ func WithCloseHandler(handler CloseHandler) ConnectionOption {
|
|||||||
// When WriteTimeout is set to zero, read timeouts are disabled.
|
// When WriteTimeout is set to zero, read timeouts are disabled.
|
||||||
func WithWriteTimeout(value time.Duration) ConnectionOption {
|
func WithWriteTimeout(value time.Duration) ConnectionOption {
|
||||||
return func(c *ConnectionConfig) error {
|
return func(c *ConnectionConfig) error {
|
||||||
if value < 0 {
|
err := validateWriteTimeout(value)
|
||||||
return errors.InvalidWriteTimeout
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
c.WriteTimeout = value
|
c.WriteTimeout = value
|
||||||
return nil
|
return nil
|
||||||
@@ -117,9 +252,12 @@ func WithRetryMaxRetries(value int) ConnectionOption {
|
|||||||
if c.Retry == nil {
|
if c.Retry == nil {
|
||||||
c.Retry = GetDefaultRetryConfig()
|
c.Retry = GetDefaultRetryConfig()
|
||||||
}
|
}
|
||||||
if value < 0 {
|
|
||||||
return errors.InvalidRetryMaxRetries
|
err := validateMaxRetries(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Retry.MaxRetries = value
|
c.Retry.MaxRetries = value
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -130,9 +268,12 @@ func WithRetryInitialDelay(value time.Duration) ConnectionOption {
|
|||||||
if c.Retry == nil {
|
if c.Retry == nil {
|
||||||
c.Retry = GetDefaultRetryConfig()
|
c.Retry = GetDefaultRetryConfig()
|
||||||
}
|
}
|
||||||
if value <= 0 {
|
|
||||||
return errors.InvalidRetryInitialDelay
|
err := validateInitialDelay(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Retry.InitialDelay = value
|
c.Retry.InitialDelay = value
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -143,9 +284,12 @@ func WithRetryMaxDelay(value time.Duration) ConnectionOption {
|
|||||||
if c.Retry == nil {
|
if c.Retry == nil {
|
||||||
c.Retry = GetDefaultRetryConfig()
|
c.Retry = GetDefaultRetryConfig()
|
||||||
}
|
}
|
||||||
if value <= 0 {
|
|
||||||
return errors.InvalidRetryMaxDelay
|
err := validateMaxDelay(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Retry.MaxDelay = value
|
c.Retry.MaxDelay = value
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -156,9 +300,12 @@ func WithRetryJitterFactor(value float64) ConnectionOption {
|
|||||||
if c.Retry == nil {
|
if c.Retry == nil {
|
||||||
c.Retry = GetDefaultRetryConfig()
|
c.Retry = GetDefaultRetryConfig()
|
||||||
}
|
}
|
||||||
if value < 0.0 || value > 1.0 {
|
|
||||||
return errors.InvalidRetryJitterFactor
|
err := validateJitterFactor(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Retry.JitterFactor = value
|
c.Retry.JitterFactor = value
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config Tests
|
// Connection Config Tests
|
||||||
|
|
||||||
func TestNewConfig(t *testing.T) {
|
func TestNewConnectionConfig(t *testing.T) {
|
||||||
conf, err := NewConnectionConfig()
|
conf, err := NewConnectionConfig()
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -27,9 +27,9 @@ func TestNewConfig(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default Config Tests
|
// Default Tests
|
||||||
|
|
||||||
func TestDefaultConfig(t *testing.T) {
|
func TestDefaultConnectionConfig(t *testing.T) {
|
||||||
conf := GetDefaultConnectionConfig()
|
conf := GetDefaultConnectionConfig()
|
||||||
|
|
||||||
assert.Equal(t, conf, &ConnectionConfig{
|
assert.Equal(t, conf, &ConnectionConfig{
|
||||||
@@ -39,7 +39,7 @@ func TestDefaultConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultRetryConfig(t *testing.T) {
|
func TestDefaultRetryConnectionConfig(t *testing.T) {
|
||||||
conf := GetDefaultRetryConfig()
|
conf := GetDefaultRetryConfig()
|
||||||
|
|
||||||
assert.Equal(t, conf, &RetryConfig{
|
assert.Equal(t, conf, &RetryConfig{
|
||||||
@@ -50,9 +50,9 @@ func TestDefaultRetryConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config Builder Tests
|
// Builder Tests
|
||||||
|
|
||||||
func TestSetConfig(t *testing.T) {
|
func TestApplyConnectionOptions(t *testing.T) {
|
||||||
conf := &ConnectionConfig{}
|
conf := &ConnectionConfig{}
|
||||||
err := applyConnectionOptions(
|
err := applyConnectionOptions(
|
||||||
conf,
|
conf,
|
||||||
@@ -75,7 +75,7 @@ func TestSetConfig(t *testing.T) {
|
|||||||
assert.ErrorIs(t, err, errors.InvalidRetryMaxRetries)
|
assert.ErrorIs(t, err, errors.InvalidRetryMaxRetries)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config Option Tests
|
// Option Tests
|
||||||
|
|
||||||
func TestWithCloseHandler(t *testing.T) {
|
func TestWithCloseHandler(t *testing.T) {
|
||||||
conf := &ConnectionConfig{}
|
conf := &ConnectionConfig{}
|
||||||
@@ -104,98 +104,100 @@ func TestWithWriteTimeout(t *testing.T) {
|
|||||||
opt = WithWriteTimeout(-30)
|
opt = WithWriteTimeout(-30)
|
||||||
err = applyConnectionOptions(conf, opt)
|
err = applyConnectionOptions(conf, opt)
|
||||||
assert.ErrorIs(t, err, errors.InvalidWriteTimeout)
|
assert.ErrorIs(t, err, errors.InvalidWriteTimeout)
|
||||||
assert.ErrorContains(t, err, "write timeout must be positive")
|
assert.ErrorContains(t, err, "write timeout cannot be negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithRetry(t *testing.T) {
|
func TestWithRetry(t *testing.T) {
|
||||||
conf := &ConnectionConfig{}
|
t.Run("default", func(t *testing.T) {
|
||||||
opt := WithRetry()
|
conf := &ConnectionConfig{}
|
||||||
err := applyConnectionOptions(conf, opt)
|
opt := WithRetry()
|
||||||
assert.NoError(t, err)
|
err := applyConnectionOptions(conf, opt)
|
||||||
assert.NotNil(t, conf.Retry)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, conf.Retry, GetDefaultRetryConfig())
|
assert.NotNil(t, conf.Retry)
|
||||||
|
assert.Equal(t, conf.Retry, GetDefaultRetryConfig())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with attempts", func(t *testing.T) {
|
||||||
|
conf := &ConnectionConfig{}
|
||||||
|
opt := WithRetryMaxRetries(3)
|
||||||
|
err := applyConnectionOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 3, conf.Retry.MaxRetries)
|
||||||
|
|
||||||
|
// zero allowed
|
||||||
|
opt = WithRetryMaxRetries(0)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// negative disallowed
|
||||||
|
opt = WithRetryMaxRetries(-10)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryMaxRetries)
|
||||||
|
assert.ErrorContains(t, err, "max retry count cannot be negative")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with initial delay", func(t *testing.T) {
|
||||||
|
conf := &ConnectionConfig{}
|
||||||
|
opt := WithRetryInitialDelay(10 * time.Second)
|
||||||
|
err := applyConnectionOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 10*time.Second, conf.Retry.InitialDelay)
|
||||||
|
|
||||||
|
// zero disallowed
|
||||||
|
opt = WithRetryInitialDelay(0 * time.Second)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryInitialDelay)
|
||||||
|
assert.ErrorContains(t, err, "initial delay must be positive")
|
||||||
|
|
||||||
|
// negative disallowed
|
||||||
|
opt = WithRetryInitialDelay(-10 * time.Second)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryInitialDelay)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with max delay", func(t *testing.T) {
|
||||||
|
conf := &ConnectionConfig{}
|
||||||
|
opt := WithRetryMaxDelay(10 * time.Second)
|
||||||
|
err := applyConnectionOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 10*time.Second, conf.Retry.MaxDelay)
|
||||||
|
|
||||||
|
// zero disallowed
|
||||||
|
opt = WithRetryMaxDelay(0 * time.Second)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryMaxDelay)
|
||||||
|
assert.ErrorContains(t, err, "max delay must be positive")
|
||||||
|
|
||||||
|
// negative disallowed
|
||||||
|
opt = WithRetryMaxDelay(-10 * time.Second)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryMaxDelay)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with jitter factor", func(t *testing.T) {
|
||||||
|
conf := &ConnectionConfig{}
|
||||||
|
|
||||||
|
opt := WithRetryJitterFactor(0.2)
|
||||||
|
err := applyConnectionOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 0.2, conf.Retry.JitterFactor)
|
||||||
|
|
||||||
|
// negative disallowed
|
||||||
|
opt = WithRetryJitterFactor(-1)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryJitterFactor)
|
||||||
|
assert.ErrorContains(t, err, "jitter factor must be between 0.0 and 1.0")
|
||||||
|
|
||||||
|
// >1 disallowed
|
||||||
|
opt = WithRetryJitterFactor(1.1)
|
||||||
|
err = applyConnectionOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidRetryJitterFactor)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithRetryAttempts(t *testing.T) {
|
// Validation Tests
|
||||||
conf := &ConnectionConfig{}
|
|
||||||
opt := WithRetryMaxRetries(3)
|
|
||||||
err := applyConnectionOptions(conf, opt)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 3, conf.Retry.MaxRetries)
|
|
||||||
|
|
||||||
// zero allowed
|
func TestValidateConnectionConfig(t *testing.T) {
|
||||||
opt = WithRetryMaxRetries(0)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// negative disallowed
|
|
||||||
opt = WithRetryMaxRetries(-10)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryMaxRetries)
|
|
||||||
assert.ErrorContains(t, err, "max retry count cannot be negative")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithRetryInitialDelay(t *testing.T) {
|
|
||||||
conf := &ConnectionConfig{}
|
|
||||||
opt := WithRetryInitialDelay(10 * time.Second)
|
|
||||||
err := applyConnectionOptions(conf, opt)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 10*time.Second, conf.Retry.InitialDelay)
|
|
||||||
|
|
||||||
// zero disallowed
|
|
||||||
opt = WithRetryInitialDelay(0 * time.Second)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryInitialDelay)
|
|
||||||
assert.ErrorContains(t, err, "initial delay must be positive")
|
|
||||||
|
|
||||||
// negative disallowed
|
|
||||||
opt = WithRetryInitialDelay(-10 * time.Second)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryInitialDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithRetryMaxDelay(t *testing.T) {
|
|
||||||
conf := &ConnectionConfig{}
|
|
||||||
opt := WithRetryMaxDelay(10 * time.Second)
|
|
||||||
err := applyConnectionOptions(conf, opt)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 10*time.Second, conf.Retry.MaxDelay)
|
|
||||||
|
|
||||||
// zero disallowed
|
|
||||||
opt = WithRetryMaxDelay(0 * time.Second)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryMaxDelay)
|
|
||||||
assert.ErrorContains(t, err, "max delay must be positive")
|
|
||||||
|
|
||||||
// negative disallowed
|
|
||||||
opt = WithRetryMaxDelay(-10 * time.Second)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryMaxDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithRetryJitterFactor(t *testing.T) {
|
|
||||||
conf := &ConnectionConfig{}
|
|
||||||
|
|
||||||
opt := WithRetryJitterFactor(0.2)
|
|
||||||
err := applyConnectionOptions(conf, opt)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 0.2, conf.Retry.JitterFactor)
|
|
||||||
|
|
||||||
// negative disallowed
|
|
||||||
opt = WithRetryJitterFactor(-1)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryJitterFactor)
|
|
||||||
assert.ErrorContains(t, err, "jitter factor must be between 0.0 and 1.0")
|
|
||||||
|
|
||||||
// >1 disallowed
|
|
||||||
opt = WithRetryJitterFactor(1.1)
|
|
||||||
err = applyConnectionOptions(conf, opt)
|
|
||||||
assert.ErrorIs(t, err, errors.InvalidRetryJitterFactor)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config Validation Tests
|
|
||||||
|
|
||||||
func TestValidateConfig(t *testing.T) {
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
conf ConnectionConfig
|
conf ConnectionConfig
|
||||||
145
config_pool_test.go
Normal file
145
config_pool_test.go
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
package honeybee
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.wisehodl.dev/jay/go-honeybee/errors"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewPoolConfig(t *testing.T) {
|
||||||
|
conf, err := NewPoolConfig()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, conf, &PoolConfig{
|
||||||
|
IdleTimeout: 20 * time.Second,
|
||||||
|
ConnectionConfig: nil,
|
||||||
|
})
|
||||||
|
|
||||||
|
// errors propagate
|
||||||
|
_, err = NewPoolConfig(WithIdleTimeout(-1))
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultPoolConfig(t *testing.T) {
|
||||||
|
conf := GetDefaultPoolConfig()
|
||||||
|
|
||||||
|
assert.Equal(t, conf, &PoolConfig{
|
||||||
|
IdleTimeout: 20 * time.Second,
|
||||||
|
ConnectionConfig: nil,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyPoolOptions(t *testing.T) {
|
||||||
|
conf := &PoolConfig{}
|
||||||
|
err := applyPoolOptions(
|
||||||
|
conf,
|
||||||
|
WithIdleTimeout(15),
|
||||||
|
WithConnectionConfig(&ConnectionConfig{}),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, time.Duration(15), conf.IdleTimeout)
|
||||||
|
assert.Equal(t, 0*time.Second, conf.ConnectionConfig.WriteTimeout)
|
||||||
|
|
||||||
|
// errors propagate
|
||||||
|
err = applyPoolOptions(
|
||||||
|
conf,
|
||||||
|
WithIdleTimeout(-1),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidIdleTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithIdleTimeout(t *testing.T) {
|
||||||
|
conf := &PoolConfig{}
|
||||||
|
opt := WithIdleTimeout(30)
|
||||||
|
err := applyPoolOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, conf.IdleTimeout, time.Duration(30))
|
||||||
|
|
||||||
|
// zero allowed
|
||||||
|
conf = &PoolConfig{}
|
||||||
|
opt = WithIdleTimeout(0)
|
||||||
|
err = applyPoolOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, conf.IdleTimeout, time.Duration(0))
|
||||||
|
|
||||||
|
// negative disallowed
|
||||||
|
conf = &PoolConfig{}
|
||||||
|
opt = WithIdleTimeout(-30)
|
||||||
|
err = applyPoolOptions(conf, opt)
|
||||||
|
assert.ErrorIs(t, err, errors.InvalidIdleTimeout)
|
||||||
|
assert.ErrorContains(t, err, "idle timeout cannot be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithConnectionConfig(t *testing.T) {
|
||||||
|
conf := &PoolConfig{}
|
||||||
|
opt := WithConnectionConfig(&ConnectionConfig{WriteTimeout: 1 * time.Second})
|
||||||
|
err := applyPoolOptions(conf, opt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, conf.ConnectionConfig)
|
||||||
|
assert.Equal(t, 1*time.Second, conf.ConnectionConfig.WriteTimeout)
|
||||||
|
|
||||||
|
// invalid config is rejected
|
||||||
|
conf = &PoolConfig{}
|
||||||
|
opt = WithConnectionConfig(&ConnectionConfig{WriteTimeout: -1 * time.Second})
|
||||||
|
err = applyPoolOptions(conf, opt)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidatePoolConfig(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
conf PoolConfig
|
||||||
|
wantErr error
|
||||||
|
wantErrText string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid empty",
|
||||||
|
conf: *&PoolConfig{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid defaults",
|
||||||
|
conf: *GetDefaultPoolConfig(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid complete",
|
||||||
|
conf: PoolConfig{
|
||||||
|
IdleTimeout: 15 * time.Second,
|
||||||
|
ConnectionConfig: &ConnectionConfig{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid connection config",
|
||||||
|
conf: PoolConfig{
|
||||||
|
ConnectionConfig: &ConnectionConfig{
|
||||||
|
Retry: &RetryConfig{
|
||||||
|
InitialDelay: 10 * time.Second,
|
||||||
|
MaxDelay: 1 * time.Second,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErrText: "initial delay may not exceed maximum delay",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := validatePoolConfig(&tc.conf)
|
||||||
|
|
||||||
|
if tc.wantErr != nil || tc.wantErrText != "" {
|
||||||
|
if tc.wantErr != nil {
|
||||||
|
assert.ErrorIs(t, err, tc.wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.wantErrText != "" {
|
||||||
|
assert.ErrorContains(t, err, tc.wantErrText)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,8 @@ var (
|
|||||||
InvalidProtocol = errors.New("URL must use ws:// or wss:// scheme")
|
InvalidProtocol = errors.New("URL must use ws:// or wss:// scheme")
|
||||||
|
|
||||||
// Configuration Errors
|
// Configuration Errors
|
||||||
InvalidReadTimeout = errors.New("read timeout must be positive")
|
InvalidIdleTimeout = errors.New("idle timeout cannot be negative")
|
||||||
InvalidWriteTimeout = errors.New("write timeout must be positive")
|
InvalidWriteTimeout = errors.New("write timeout cannot be negative")
|
||||||
InvalidRetryMaxRetries = errors.New("max retry count cannot be negative")
|
InvalidRetryMaxRetries = errors.New("max retry count cannot be negative")
|
||||||
InvalidRetryInitialDelay = errors.New("initial delay must be positive")
|
InvalidRetryInitialDelay = errors.New("initial delay must be positive")
|
||||||
InvalidRetryMaxDelay = errors.New("max delay must be positive")
|
InvalidRetryMaxDelay = errors.New("max delay must be positive")
|
||||||
|
|||||||
Reference in New Issue
Block a user