github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/events/event_manager_test.go (about)

     1  // Copyright © 2021 Kaleido, Inc.
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package events
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/kaleido-io/firefly/internal/config"
    25  	"github.com/kaleido-io/firefly/mocks/broadcastmocks"
    26  	"github.com/kaleido-io/firefly/mocks/databasemocks"
    27  	"github.com/kaleido-io/firefly/mocks/datamocks"
    28  	"github.com/kaleido-io/firefly/mocks/eventsmocks"
    29  	"github.com/kaleido-io/firefly/mocks/identitymocks"
    30  	"github.com/kaleido-io/firefly/mocks/privatemessagingmocks"
    31  	"github.com/kaleido-io/firefly/mocks/publicstoragemocks"
    32  	"github.com/kaleido-io/firefly/pkg/fftypes"
    33  	"github.com/stretchr/testify/assert"
    34  	"github.com/stretchr/testify/mock"
    35  )
    36  
    37  func newTestEventManager(t *testing.T) (*eventManager, func()) {
    38  	config.Reset()
    39  	ctx, cancel := context.WithCancel(context.Background())
    40  	mdi := &databasemocks.Plugin{}
    41  	mii := &identitymocks.Plugin{}
    42  	mpi := &publicstoragemocks.Plugin{}
    43  	met := &eventsmocks.Plugin{}
    44  	mbm := &broadcastmocks.Manager{}
    45  	mpm := &privatemessagingmocks.Manager{}
    46  	mdm := &datamocks.Manager{}
    47  	met.On("Name").Return("ut").Maybe()
    48  	em, err := NewEventManager(ctx, mpi, mdi, mii, mbm, mpm, mdm)
    49  	assert.NoError(t, err)
    50  	return em.(*eventManager), cancel
    51  }
    52  
    53  func TestStartStop(t *testing.T) {
    54  	em, cancel := newTestEventManager(t)
    55  	mdi := em.database.(*databasemocks.Plugin)
    56  	mdi.On("GetOffset", mock.Anything, fftypes.OffsetTypeAggregator, fftypes.SystemNamespace, aggregatorOffsetName).Return(&fftypes.Offset{
    57  		Type:      fftypes.OffsetTypeAggregator,
    58  		Namespace: fftypes.SystemNamespace,
    59  		Name:      aggregatorOffsetName,
    60  		Current:   12345,
    61  	}, nil)
    62  	mdi.On("GetPins", mock.Anything, mock.Anything, mock.Anything).Return([]*fftypes.Pin{}, nil)
    63  	mdi.On("GetSubscriptions", mock.Anything, mock.Anything, mock.Anything).Return([]*fftypes.Subscription{}, nil)
    64  	assert.NoError(t, em.Start())
    65  	em.NewEvents() <- 12345
    66  	em.NewPins() <- 12345
    67  	cancel()
    68  	em.WaitStop()
    69  }
    70  
    71  func TestStartStopBadDependencies(t *testing.T) {
    72  	_, err := NewEventManager(context.Background(), nil, nil, nil, nil, nil, nil)
    73  	assert.Regexp(t, "FF10128", err)
    74  
    75  }
    76  
    77  func TestStartStopBadTransports(t *testing.T) {
    78  	config.Set(config.EventTransportsEnabled, []string{"wrongun"})
    79  	defer config.Reset()
    80  	mdi := &databasemocks.Plugin{}
    81  	mii := &identitymocks.Plugin{}
    82  	mpi := &publicstoragemocks.Plugin{}
    83  	mbm := &broadcastmocks.Manager{}
    84  	mpm := &privatemessagingmocks.Manager{}
    85  	mdm := &datamocks.Manager{}
    86  	_, err := NewEventManager(context.Background(), mpi, mdi, mii, mbm, mpm, mdm)
    87  	assert.Regexp(t, "FF10172", err)
    88  
    89  }
    90  
    91  func TestEmitSubscriptionEventsNoops(t *testing.T) {
    92  	em, cancel := newTestEventManager(t)
    93  	mdi := em.database.(*databasemocks.Plugin)
    94  	mdi.On("GetOffset", mock.Anything, fftypes.OffsetTypeAggregator, fftypes.SystemNamespace, aggregatorOffsetName).Return(&fftypes.Offset{
    95  		Type:      fftypes.OffsetTypeAggregator,
    96  		Namespace: fftypes.SystemNamespace,
    97  		Name:      aggregatorOffsetName,
    98  		Current:   12345,
    99  	}, nil)
   100  	mdi.On("GetPins", mock.Anything, mock.Anything, mock.Anything).Return([]*fftypes.Pin{}, nil)
   101  	mdi.On("GetSubscriptions", mock.Anything, mock.Anything, mock.Anything).Return([]*fftypes.Subscription{}, nil)
   102  
   103  	getSubCallReady := make(chan bool, 1)
   104  	getSubCalled := make(chan bool)
   105  	getSub := mdi.On("GetSubscriptionByID", mock.Anything, mock.Anything).Return(nil, nil)
   106  	getSub.RunFn = func(a mock.Arguments) {
   107  		<-getSubCallReady
   108  		getSubCalled <- true
   109  	}
   110  
   111  	assert.NoError(t, em.Start())
   112  	defer cancel()
   113  
   114  	// Wait until the gets occur for these events, which will return nil
   115  	getSubCallReady <- true
   116  	em.NewSubscriptions() <- fftypes.NewUUID()
   117  	<-getSubCalled
   118  
   119  	getSubCallReady <- true
   120  	em.DeletedSubscriptions() <- fftypes.NewUUID()
   121  	<-getSubCalled
   122  
   123  	close(getSubCallReady)
   124  }
   125  
   126  func TestCreateDurableSubscriptionBadSub(t *testing.T) {
   127  	em, cancel := newTestEventManager(t)
   128  	defer cancel()
   129  	err := em.CreateDurableSubscription(em.ctx, &fftypes.Subscription{})
   130  	assert.Regexp(t, "FF10189", err)
   131  }
   132  
   133  func TestCreateDurableSubscriptionDupName(t *testing.T) {
   134  	em, cancel := newTestEventManager(t)
   135  	defer cancel()
   136  	mdi := em.database.(*databasemocks.Plugin)
   137  	sub := &fftypes.Subscription{
   138  		SubscriptionRef: fftypes.SubscriptionRef{
   139  			ID:        fftypes.NewUUID(),
   140  			Namespace: "ns1",
   141  			Name:      "sub1",
   142  		},
   143  	}
   144  	mdi.On("GetSubscriptionByName", mock.Anything, "ns1", "sub1").Return(sub, nil)
   145  	err := em.CreateDurableSubscription(em.ctx, sub)
   146  	assert.Regexp(t, "FF10193", err)
   147  }
   148  
   149  func TestCreateDurableSubscriptionDefaultSubCannotParse(t *testing.T) {
   150  	em, cancel := newTestEventManager(t)
   151  	defer cancel()
   152  	mdi := em.database.(*databasemocks.Plugin)
   153  	sub := &fftypes.Subscription{
   154  		SubscriptionRef: fftypes.SubscriptionRef{
   155  			ID:        fftypes.NewUUID(),
   156  			Namespace: "ns1",
   157  			Name:      "sub1",
   158  		},
   159  		Filter: fftypes.SubscriptionFilter{
   160  			Events: "![[[[[",
   161  		},
   162  	}
   163  	mdi.On("GetSubscriptionByName", mock.Anything, "ns1", "sub1").Return(nil, nil)
   164  	err := em.CreateDurableSubscription(em.ctx, sub)
   165  	assert.Regexp(t, "FF10171", err)
   166  }
   167  
   168  func TestCreateDurableSubscriptionBadFirstEvent(t *testing.T) {
   169  	em, cancel := newTestEventManager(t)
   170  	defer cancel()
   171  	mdi := em.database.(*databasemocks.Plugin)
   172  	wrongFirstEvent := fftypes.SubOptsFirstEvent("lobster")
   173  	sub := &fftypes.Subscription{
   174  		SubscriptionRef: fftypes.SubscriptionRef{
   175  			ID:        fftypes.NewUUID(),
   176  			Namespace: "ns1",
   177  			Name:      "sub1",
   178  		},
   179  		Options: fftypes.SubscriptionOptions{
   180  			FirstEvent: &wrongFirstEvent,
   181  		},
   182  	}
   183  	mdi.On("GetSubscriptionByName", mock.Anything, "ns1", "sub1").Return(nil, nil)
   184  	err := em.CreateDurableSubscription(em.ctx, sub)
   185  	assert.Regexp(t, "FF10191", err)
   186  }
   187  
   188  func TestCreateDurableSubscriptionNegativeFirstEvent(t *testing.T) {
   189  	em, cancel := newTestEventManager(t)
   190  	defer cancel()
   191  	wrongFirstEvent := fftypes.SubOptsFirstEvent("-12345")
   192  	mdi := em.database.(*databasemocks.Plugin)
   193  	sub := &fftypes.Subscription{
   194  		SubscriptionRef: fftypes.SubscriptionRef{
   195  			ID:        fftypes.NewUUID(),
   196  			Namespace: "ns1",
   197  			Name:      "sub1",
   198  		},
   199  		Options: fftypes.SubscriptionOptions{
   200  			FirstEvent: &wrongFirstEvent,
   201  		},
   202  	}
   203  	mdi.On("GetSubscriptionByName", mock.Anything, "ns1", "sub1").Return(nil, nil)
   204  	err := em.CreateDurableSubscription(em.ctx, sub)
   205  	assert.Regexp(t, "FF10192", err)
   206  }
   207  
   208  func TestCreateDurableSubscriptionGetHighestSequenceFailure(t *testing.T) {
   209  	em, cancel := newTestEventManager(t)
   210  	defer cancel()
   211  	mdi := em.database.(*databasemocks.Plugin)
   212  	sub := &fftypes.Subscription{
   213  		SubscriptionRef: fftypes.SubscriptionRef{
   214  			ID:        fftypes.NewUUID(),
   215  			Namespace: "ns1",
   216  			Name:      "sub1",
   217  		},
   218  	}
   219  	mdi.On("GetSubscriptionByName", mock.Anything, "ns1", "sub1").Return(nil, nil)
   220  	mdi.On("GetEvents", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop"))
   221  	err := em.CreateDurableSubscription(em.ctx, sub)
   222  	assert.EqualError(t, err, "pop")
   223  }
   224  
   225  func TestCreateDurableSubscriptionOk(t *testing.T) {
   226  	em, cancel := newTestEventManager(t)
   227  	defer cancel()
   228  	mdi := em.database.(*databasemocks.Plugin)
   229  	sub := &fftypes.Subscription{
   230  		SubscriptionRef: fftypes.SubscriptionRef{
   231  			ID:        fftypes.NewUUID(),
   232  			Namespace: "ns1",
   233  			Name:      "sub1",
   234  		},
   235  	}
   236  	mdi.On("GetSubscriptionByName", mock.Anything, "ns1", "sub1").Return(nil, nil)
   237  	mdi.On("GetEvents", mock.Anything, mock.Anything).Return([]*fftypes.Event{
   238  		{Sequence: 12345},
   239  	}, nil)
   240  	mdi.On("UpsertSubscription", mock.Anything, mock.Anything, false).Return(nil)
   241  	err := em.CreateDurableSubscription(em.ctx, sub)
   242  	assert.NoError(t, err)
   243  	// Check genreated fields
   244  	assert.NotNil(t, sub.ID)
   245  	assert.Equal(t, "websockets", sub.Transport)
   246  	assert.Equal(t, "12345", string(*sub.Options.FirstEvent))
   247  }
   248  
   249  func TestCreateDeleteDurableSubscriptionOk(t *testing.T) {
   250  	em, cancel := newTestEventManager(t)
   251  	defer cancel()
   252  	mdi := em.database.(*databasemocks.Plugin)
   253  	subId := fftypes.NewUUID()
   254  	sub := &fftypes.Subscription{SubscriptionRef: fftypes.SubscriptionRef{ID: subId, Namespace: "ns1"}}
   255  	mdi.On("GetSubscriptionByID", mock.Anything, subId).Return(sub, nil)
   256  	mdi.On("DeleteSubscriptionByID", mock.Anything, subId).Return(nil)
   257  	err := em.DeleteDurableSubscription(em.ctx, sub)
   258  	assert.NoError(t, err)
   259  }