Files
micro-broker-kgo/hook_event_test.go
pugnack cced3b84c1
Some checks failed
coverage / build (push) Failing after 1m50s
test / test (push) Failing after 19m17s
sync / sync (push) Successful in 7s
remove noisy logs from event hooks and add tests (#193)
2025-07-10 12:51:26 +03:00

472 lines
13 KiB
Go

package kgo
import (
"context"
"errors"
"io"
"net"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/twmb/franz-go/pkg/kgo"
"go.unistack.org/micro/v4/logger"
)
func TestHookEvent_OnGroupManageError(t *testing.T) {
tests := []struct {
name string
inputErr error
fatalOnError bool
expectedErrorIsCalled bool
expectedErrorMsg string
expectedFatalIsCalled bool
expectedFatalMsg string
}{
{
name: "error is nil",
inputErr: nil,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context canceled",
inputErr: context.Canceled,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context deadline exceeded",
inputErr: context.DeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: deadline exceeded (os package)",
inputErr: os.ErrDeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: EOF (io package)",
inputErr: io.EOF,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: closed network connection (net package)",
inputErr: net.ErrClosed,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "some error (non-fatal)",
inputErr: errors.New("some error"),
fatalOnError: false,
expectedErrorIsCalled: true,
expectedErrorMsg: "kgo.OnGroupManageError",
expectedFatalIsCalled: false,
},
{
name: "some error (fatal)",
inputErr: errors.New("some error"),
fatalOnError: true,
expectedErrorIsCalled: false,
expectedFatalIsCalled: true,
expectedFatalMsg: "kgo.OnGroupManageError",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
log := &mockLogger{}
he := &hookEvent{log: log, fatalOnError: tt.fatalOnError}
he.OnGroupManageError(tt.inputErr)
require.Equal(t, tt.expectedErrorIsCalled, log.errorIsCalled)
require.Equal(t, tt.expectedErrorMsg, log.errorMsg)
require.Equal(t, tt.expectedFatalIsCalled, log.fatalIsCalled)
require.Equal(t, tt.expectedFatalMsg, log.fatalMsg)
})
}
}
func TestHookEvent_OnBrokerConnect(t *testing.T) {
tests := []struct {
name string
inputErr error
fatalOnError bool
expectedErrorIsCalled bool
expectedErrorMsg string
expectedFatalIsCalled bool
expectedFatalMsg string
}{
{
name: "error is nil",
inputErr: nil,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context canceled",
inputErr: context.Canceled,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context deadline exceeded",
inputErr: context.DeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: deadline exceeded (os package)",
inputErr: os.ErrDeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: EOF (io package)",
inputErr: io.EOF,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: closed network connection (net package)",
inputErr: net.ErrClosed,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "some error (non-fatal)",
inputErr: errors.New("some error"),
fatalOnError: false,
expectedErrorIsCalled: true,
expectedErrorMsg: "kgo.OnBrokerConnect",
expectedFatalIsCalled: false,
},
{
name: "some error (fatal)",
inputErr: errors.New("some error"),
fatalOnError: true,
expectedErrorIsCalled: false,
expectedFatalIsCalled: true,
expectedFatalMsg: "kgo.OnBrokerConnect",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
log := &mockLogger{}
he := &hookEvent{log: log, fatalOnError: tt.fatalOnError}
he.OnBrokerConnect(kgo.BrokerMetadata{}, 0, nil, tt.inputErr)
require.Equal(t, tt.expectedErrorIsCalled, log.errorIsCalled)
require.Equal(t, tt.expectedErrorMsg, log.errorMsg)
require.Equal(t, tt.expectedFatalIsCalled, log.fatalIsCalled)
require.Equal(t, tt.expectedFatalMsg, log.fatalMsg)
})
}
}
func TestHookEvent_OnBrokerWrite(t *testing.T) {
tests := []struct {
name string
inputErr error
fatalOnError bool
expectedErrorIsCalled bool
expectedErrorMsg string
expectedFatalIsCalled bool
expectedFatalMsg string
}{
{
name: "error is nil",
inputErr: nil,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context canceled",
inputErr: context.Canceled,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context deadline exceeded",
inputErr: context.DeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: deadline exceeded (os package)",
inputErr: os.ErrDeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: EOF (io package)",
inputErr: io.EOF,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: closed network connection (net package)",
inputErr: net.ErrClosed,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "some error (non-fatal)",
inputErr: errors.New("some error"),
fatalOnError: false,
expectedErrorIsCalled: true,
expectedErrorMsg: "kgo.OnBrokerWrite",
expectedFatalIsCalled: false,
},
{
name: "some error (fatal)",
inputErr: errors.New("some error"),
fatalOnError: true,
expectedErrorIsCalled: false,
expectedFatalIsCalled: true,
expectedFatalMsg: "kgo.OnBrokerWrite",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
log := &mockLogger{}
he := &hookEvent{log: log, fatalOnError: tt.fatalOnError}
he.OnBrokerWrite(kgo.BrokerMetadata{}, 0, 0, 0, 0, tt.inputErr)
require.Equal(t, tt.expectedErrorIsCalled, log.errorIsCalled)
require.Equal(t, tt.expectedErrorMsg, log.errorMsg)
require.Equal(t, tt.expectedFatalIsCalled, log.fatalIsCalled)
require.Equal(t, tt.expectedFatalMsg, log.fatalMsg)
})
}
}
func TestHookEvent_OnBrokerRead(t *testing.T) {
tests := []struct {
name string
inputErr error
fatalOnError bool
expectedErrorIsCalled bool
expectedErrorMsg string
expectedFatalIsCalled bool
expectedFatalMsg string
}{
{
name: "error is nil",
inputErr: nil,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context canceled",
inputErr: context.Canceled,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context deadline exceeded",
inputErr: context.DeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: deadline exceeded (os package)",
inputErr: os.ErrDeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: EOF (io package)",
inputErr: io.EOF,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: closed network connection (net package)",
inputErr: net.ErrClosed,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "some error (non-fatal)",
inputErr: errors.New("some error"),
fatalOnError: false,
expectedErrorIsCalled: true,
expectedErrorMsg: "kgo.OnBrokerRead",
expectedFatalIsCalled: false,
},
{
name: "some error (fatal)",
inputErr: errors.New("some error"),
fatalOnError: true,
expectedErrorIsCalled: false,
expectedFatalIsCalled: true,
expectedFatalMsg: "kgo.OnBrokerRead",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
log := &mockLogger{}
he := &hookEvent{log: log, fatalOnError: tt.fatalOnError}
he.OnBrokerRead(kgo.BrokerMetadata{}, 0, 0, 0, 0, tt.inputErr)
require.Equal(t, tt.expectedErrorIsCalled, log.errorIsCalled)
require.Equal(t, tt.expectedErrorMsg, log.errorMsg)
require.Equal(t, tt.expectedFatalIsCalled, log.fatalIsCalled)
require.Equal(t, tt.expectedFatalMsg, log.fatalMsg)
})
}
}
func TestHookEvent_OnProduceRecordUnbuffered(t *testing.T) {
tests := []struct {
name string
inputErr error
fatalOnError bool
expectedErrorIsCalled bool
expectedErrorMsg string
expectedFatalIsCalled bool
expectedFatalMsg string
}{
{
name: "error is nil",
inputErr: nil,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context canceled",
inputErr: context.Canceled,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "context deadline exceeded",
inputErr: context.DeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: deadline exceeded (os package)",
inputErr: os.ErrDeadlineExceeded,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: EOF (io package)",
inputErr: io.EOF,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "retryable error: closed network connection (net package)",
inputErr: net.ErrClosed,
expectedErrorIsCalled: false,
expectedFatalIsCalled: false,
},
{
name: "some error (non-fatal)",
inputErr: errors.New("some error"),
fatalOnError: false,
expectedErrorIsCalled: true,
expectedErrorMsg: "kgo.OnProduceRecordUnbuffered",
expectedFatalIsCalled: false,
},
{
name: "some error (fatal)",
inputErr: errors.New("some error"),
fatalOnError: true,
expectedErrorIsCalled: false,
expectedFatalIsCalled: true,
expectedFatalMsg: "kgo.OnProduceRecordUnbuffered",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
log := &mockLogger{}
he := &hookEvent{log: log, fatalOnError: tt.fatalOnError}
he.OnProduceRecordUnbuffered(&kgo.Record{}, tt.inputErr)
require.Equal(t, tt.expectedErrorIsCalled, log.errorIsCalled)
require.Equal(t, tt.expectedErrorMsg, log.errorMsg)
require.Equal(t, tt.expectedFatalIsCalled, log.fatalIsCalled)
require.Equal(t, tt.expectedFatalMsg, log.fatalMsg)
})
}
}
// Mocks
type mockLogger struct {
errorIsCalled bool
errorMsg string
fatalIsCalled bool
fatalMsg string
}
func (m *mockLogger) Init(...logger.Option) error {
panic("implement me")
}
func (m *mockLogger) Clone(...logger.Option) logger.Logger {
panic("implement me")
}
func (m *mockLogger) V(logger.Level) bool {
panic("implement me")
}
func (m *mockLogger) Level(logger.Level) {
panic("implement me")
}
func (m *mockLogger) Options() logger.Options {
panic("implement me")
}
func (m *mockLogger) Fields(...interface{}) logger.Logger {
panic("implement me")
}
func (m *mockLogger) Info(context.Context, string, ...interface{}) {
panic("implement me")
}
func (m *mockLogger) Trace(context.Context, string, ...interface{}) {
panic("implement me")
}
func (m *mockLogger) Debug(context.Context, string, ...interface{}) {
panic("implement me")
}
func (m *mockLogger) Warn(context.Context, string, ...interface{}) {
panic("implement me")
}
func (m *mockLogger) Error(ctx context.Context, msg string, args ...interface{}) {
m.errorIsCalled = true
m.errorMsg = msg
}
func (m *mockLogger) Fatal(ctx context.Context, msg string, args ...interface{}) {
m.fatalIsCalled = true
m.fatalMsg = msg
}
func (m *mockLogger) Log(context.Context, logger.Level, string, ...interface{}) {
panic("implement me")
}
func (m *mockLogger) Name() string {
panic("implement me")
}
func (m *mockLogger) String() string {
panic("implement me")
}