diff --git a/client_test.go b/client_test.go index 2f288ab..b3522a2 100644 --- a/client_test.go +++ b/client_test.go @@ -1269,6 +1269,7 @@ func assertEqual(t *testing.T, got, want any, opts ...cmp.Option) { } func recoverThenFail(t *testing.T) { + t.Helper() if r := recover(); r != nil { fmt.Print(string(debug.Stack())) t.Fatal(r) diff --git a/lifecycle_test.go b/lifecycle_test.go index 7440c56..21ca565 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -195,3 +195,120 @@ func Test_LifecycleChainedHooksAreCalled(t *testing.T) { require.Equal(t, 1, lhState["hooks1-post-read-immediate"]) require.Equal(t, 1, lhState["hooks2-post-read-immediate"]) } + +// Test_LifecycleChainedNilPostReadImmediateInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNilPostReadImmediateInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PostReadImmediate = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + chained.PostReadImmediate(context.Background(), LifecyclePostReadImmediateMeta{}) +} + +// Test_LifecycleChainedNilPostReadInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNilPostReadInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PostRead = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + _, err := chained.PostRead(context.Background(), LifecyclePostReadMeta{}) + require.NoError(t, err) +} + +// Test_LifecycleChainedNilPreProcessingInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNilPreProcessingInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PreProcessing = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + _, err := chained.PreProcessing(context.Background(), LifecyclePreProcessingMeta{}) + require.NoError(t, err) +} + +// Test_LifecycleChainedNilPostProcessingInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNilPostProcessingInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PostProcessing = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + err := chained.PostProcessing(context.Background(), LifecyclePostProcessingMeta{}) + require.NoError(t, err) +} + +// Test_LifecycleChainedNiPostAckInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNiPostAckInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PostAck = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + err := chained.PostAck(context.Background(), LifecyclePostAckMeta{}) + require.NoError(t, err) +} + +// Test_LifecycleChainedNilPreWriteInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNilPreWriteInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PreWrite = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + _, err := chained.PreWrite(context.Background(), LifecyclePreWriteMeta{}) + require.NoError(t, err) +} + +// Test_LifecycleChainedNilPostFanoutInvocation confirms the invocation of a lifecycle hook method constructed +// via `ChainLifecycleHooks` which is nil doesn't panic. This in response to a bug where incorrect nil checks resulted +// in panicked invocations +func Test_LifecycleChainedNilPostFanoutInvocation(t *testing.T) { + defer recoverThenFail(t) + + h1 := noopLifecycleHooks() + h1.PostFanout = nil + h2 := LifecycleHooks{} + chained := ChainLifecycleHooks(h1, h2) + + chained.PostFanout(context.Background()) +} + +func noopLifecycleHooks() LifecycleHooks { + return LifecycleHooks{ + PostRead: func(ctx context.Context, meta LifecyclePostReadMeta) (context.Context, error) { return nil, nil }, + PostReadImmediate: func(ctx context.Context, meta LifecyclePostReadImmediateMeta) {}, + PreProcessing: func(ctx context.Context, meta LifecyclePreProcessingMeta) (context.Context, error) { return nil, nil }, + PostProcessing: func(ctx context.Context, meta LifecyclePostProcessingMeta) error { return nil }, + PostAck: func(ctx context.Context, meta LifecyclePostAckMeta) error { return nil }, + PreWrite: func(ctx context.Context, meta LifecyclePreWriteMeta) (LifecyclePreWriteResp, error) { + return LifecyclePreWriteResp{}, nil + }, + PostFanout: func(ctx context.Context) {}, + } +} diff --git a/message_test.go b/message_test.go index bad5441..9be627f 100644 --- a/message_test.go +++ b/message_test.go @@ -323,7 +323,7 @@ func TestMessage_Value(t *testing.T) { value: []byte(valueStr), } got := m.Value() - require.NotSame(t, m.value, got, "should not return the same reference") + require.NotSame(t, &m.value, &got, "should not return the same reference") require.Equal(t, valueStr, string(got), "should return the same string representation") }