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 }