diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go new file mode 100644 index 00000000..dc7ac3b8 --- /dev/null +++ b/pkg/morph/event/listener_test.go @@ -0,0 +1,187 @@ +package event + +import ( + "context" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/subscriber" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "github.com/nspcc-dev/neo-go/pkg/core/block" + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +func TestEventHandling(t *testing.T) { + blockCh := make(chan *block.Block) + notificationCh := make(chan *state.ContainedNotificationEvent) + notaryRequestsCh := make(chan *result.NotaryRequestEvent) + + l, err := NewListener(ListenerParams{ + Logger: test.NewLogger(t, true), + Subscriber: &testSubscriber{ + blockCh: blockCh, + notificationCh: notificationCh, + notaryRequestsCh: notaryRequestsCh, + }, + WorkerPoolCapacity: 10, + }) + require.NoError(t, err, "failed to create listener") + + list := l.(*listener) + + blockHandled := make(chan bool) + handledBlocks := make([]*block.Block, 0) + l.RegisterBlockHandler(func(b *block.Block) { + handledBlocks = append(handledBlocks, b) + blockHandled <- true + }) + + key := scriptHashWithType{ + scriptHashValue: scriptHashValue{ + hash: util.Uint160{100}, + }, + typeValue: typeValue{ + typ: TypeFromString("notification type"), + }, + } + + l.SetNotificationParser(NotificationParserInfo{ + scriptHashWithType: key, + p: func(cne *state.ContainedNotificationEvent) (Event, error) { + return testNotificationEvent{source: cne}, nil + }, + }) + + notificationHandled := make(chan bool) + handledNotifications := make([]Event, 0) + l.RegisterNotificationHandler(NotificationHandlerInfo{ + scriptHashWithType: key, + h: func(e Event) { + handledNotifications = append(handledNotifications, e) + notificationHandled <- true + }, + }) + + go list.Listen(context.Background()) + + t.Run("handles block events", func(t *testing.T) { + block := &block.Block{} + + blockCh <- block + + <-blockHandled + + require.Equal(t, 1, len(handledBlocks), "invalid handled blocks length") + require.Equal(t, block, handledBlocks[0], "invalid handled block") + }) + + t.Run("handles notifications", func(t *testing.T) { + notification := &state.ContainedNotificationEvent{ + Container: util.Uint256{49}, + NotificationEvent: state.NotificationEvent{ + ScriptHash: util.Uint160{100}, + Name: "notification type", + }, + } + + notificationCh <- notification + + <-notificationHandled + require.EqualValues(t, []Event{testNotificationEvent{source: notification}}, handledNotifications, "invalid handled notifications") + }) +} + +func TestErrorPassing(t *testing.T) { + blockCh := make(chan *block.Block) + notificationCh := make(chan *state.ContainedNotificationEvent) + notaryRequestsCh := make(chan *result.NotaryRequestEvent) + + t.Run("notification error", func(t *testing.T) { + nErr := fmt.Errorf("notification error") + l, err := NewListener(ListenerParams{ + Logger: test.NewLogger(t, true), + Subscriber: &testSubscriber{ + blockCh: blockCh, + notificationCh: notificationCh, + notaryRequestsCh: notaryRequestsCh, + + notificationErr: nErr, + }, + WorkerPoolCapacity: 10, + }) + require.NoError(t, err, "failed to create listener") + + errCh := make(chan error) + + go l.ListenWithError(context.Background(), errCh) + + err = <-errCh + + require.ErrorIs(t, err, nErr, "invalid notification error") + }) + + t.Run("block error", func(t *testing.T) { + bErr := fmt.Errorf("notification error") + l, err := NewListener(ListenerParams{ + Logger: test.NewLogger(t, true), + Subscriber: &testSubscriber{ + blockCh: blockCh, + notificationCh: notificationCh, + notaryRequestsCh: notaryRequestsCh, + + blockErr: bErr, + }, + WorkerPoolCapacity: 10, + }) + require.NoError(t, err, "failed to create listener") + l.RegisterBlockHandler(func(b *block.Block) {}) + + errCh := make(chan error) + + go l.ListenWithError(context.Background(), errCh) + + err = <-errCh + + require.ErrorIs(t, err, bErr, "invalid block error") + }) + +} + +type testSubscriber struct { + blockCh chan *block.Block + notificationCh chan *state.ContainedNotificationEvent + notaryRequestsCh chan *result.NotaryRequestEvent + + blockErr error + notificationErr error +} + +func (s *testSubscriber) SubscribeForNotification(...util.Uint160) error { + return s.notificationErr +} +func (s *testSubscriber) UnsubscribeForNotification() {} +func (s *testSubscriber) BlockNotifications() error { + return s.blockErr +} +func (s *testSubscriber) SubscribeForNotaryRequests(mainTXSigner util.Uint160) error { + return nil +} + +func (s *testSubscriber) NotificationChannels() subscriber.NotificationChannels { + return subscriber.NotificationChannels{ + BlockCh: s.blockCh, + NotificationsCh: s.notificationCh, + NotaryRequestsCh: s.notaryRequestsCh, + } +} + +func (s *testSubscriber) Close() {} + +type testNotificationEvent struct { + source *state.ContainedNotificationEvent +} + +func (e testNotificationEvent) MorphEvent() {}