lnd/chainio/consumer_test.go

202 lines
5.2 KiB
Go

package chainio
import (
"testing"
"time"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/stretchr/testify/require"
)
// TestNewBeatConsumer tests the NewBeatConsumer function.
func TestNewBeatConsumer(t *testing.T) {
t.Parallel()
quitChan := make(chan struct{})
name := "test"
// Test the NewBeatConsumer function.
b := NewBeatConsumer(quitChan, name)
// Assert the state.
require.Equal(t, quitChan, b.quit)
require.Equal(t, name, b.name)
require.NotNil(t, b.BlockbeatChan)
}
// TestProcessBlockSuccess tests when the block is processed successfully, no
// error is returned.
func TestProcessBlockSuccess(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan.
consumerErrChan := make(chan error, 1)
b.errChan = consumerErrChan
// Call the method under test.
resultChan := make(chan error, 1)
go func() {
resultChan <- b.ProcessBlock(mockBeat)
}()
// Assert the beat is sent to the blockbeat channel.
beat, err := fn.RecvOrTimeout(b.BlockbeatChan, time.Second)
require.NoError(t, err)
require.Equal(t, mockBeat, beat)
// Send nil to the consumer's error channel.
consumerErrChan <- nil
// Assert the result of ProcessBlock is nil.
result, err := fn.RecvOrTimeout(resultChan, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestProcessBlockConsumerQuitBeforeSend tests when the consumer is quit
// before sending the beat, the method returns immediately.
func TestProcessBlockConsumerQuitBeforeSend(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Call the method under test.
resultChan := make(chan error, 1)
go func() {
resultChan <- b.ProcessBlock(mockBeat)
}()
// Instead of reading the BlockbeatChan, close the quit channel.
close(quitChan)
// Assert ProcessBlock returned nil.
result, err := fn.RecvOrTimeout(resultChan, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestProcessBlockConsumerQuitAfterSend tests when the consumer is quit after
// sending the beat, the method returns immediately.
func TestProcessBlockConsumerQuitAfterSend(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan.
consumerErrChan := make(chan error, 1)
b.errChan = consumerErrChan
// Call the method under test.
resultChan := make(chan error, 1)
go func() {
resultChan <- b.ProcessBlock(mockBeat)
}()
// Assert the beat is sent to the blockbeat channel.
beat, err := fn.RecvOrTimeout(b.BlockbeatChan, time.Second)
require.NoError(t, err)
require.Equal(t, mockBeat, beat)
// Instead of sending nil to the consumer's error channel, close the
// quit chanel.
close(quitChan)
// Assert ProcessBlock returned nil.
result, err := fn.RecvOrTimeout(resultChan, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestNotifyBlockProcessedSendErr asserts the error can be sent and read by
// the beat via NotifyBlockProcessed.
func TestNotifyBlockProcessedSendErr(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan.
consumerErrChan := make(chan error, 1)
b.errChan = consumerErrChan
// Call the method under test.
done := make(chan error)
go func() {
defer close(done)
b.NotifyBlockProcessed(mockBeat, errDummy)
}()
// Assert the error is sent to the beat's err chan.
result, err := fn.RecvOrTimeout(consumerErrChan, time.Second)
require.NoError(t, err)
require.ErrorIs(t, result, errDummy)
// Assert the done channel is closed.
result, err = fn.RecvOrTimeout(done, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestNotifyBlockProcessedOnQuit asserts NotifyBlockProcessed exits
// immediately when the quit channel is closed.
func TestNotifyBlockProcessedOnQuit(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan - we don't buffer it so it will block
// on sending the error.
consumerErrChan := make(chan error)
b.errChan = consumerErrChan
// Call the method under test.
done := make(chan error)
go func() {
defer close(done)
b.NotifyBlockProcessed(mockBeat, errDummy)
}()
// Close the quit channel so the method will return.
close(b.quit)
// Assert the done channel is closed.
result, err := fn.RecvOrTimeout(done, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}