github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/event_sql_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 sqlcommon 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 "testing" 24 25 "github.com/DATA-DOG/go-sqlmock" 26 "github.com/kaleido-io/firefly/pkg/database" 27 "github.com/kaleido-io/firefly/pkg/fftypes" 28 "github.com/stretchr/testify/assert" 29 "github.com/stretchr/testify/mock" 30 ) 31 32 func TestEventE2EWithDB(t *testing.T) { 33 34 s := newQLTestProvider(t) 35 defer s.Close() 36 ctx := context.Background() 37 38 s.callbacks.On("EventCreated", mock.Anything).Return() 39 40 // Create a new event entry 41 eventID := fftypes.NewUUID() 42 event := &fftypes.Event{ 43 ID: eventID, 44 Namespace: "ns1", 45 Type: fftypes.EventTypeMessageConfirmed, 46 Reference: fftypes.NewUUID(), 47 Created: fftypes.Now(), 48 } 49 err := s.UpsertEvent(ctx, event, true) 50 assert.NoError(t, err) 51 52 // Check we get the exact same event back 53 eventRead, err := s.GetEventByID(ctx, eventID) 54 // The generated sequence will have been added 55 event.Sequence = eventRead.Sequence 56 assert.NoError(t, err) 57 assert.NotNil(t, eventRead) 58 eventJson, _ := json.Marshal(&event) 59 eventReadJson, _ := json.Marshal(&eventRead) 60 assert.Equal(t, string(eventJson), string(eventReadJson)) 61 62 // Update the event (this is testing what's possible at the database layer, 63 // and does not account for the verification that happens at the higher level) 64 eventUpdated := &fftypes.Event{ 65 ID: eventID, 66 Namespace: "ns1", 67 Type: fftypes.EventTypeMessageConfirmed, 68 Reference: fftypes.NewUUID(), 69 Group: fftypes.NewRandB32(), 70 Created: fftypes.Now(), 71 } 72 err = s.UpsertEvent(context.Background(), eventUpdated, true) 73 assert.NoError(t, err) 74 75 // Check we get the exact same message back - note the removal of one of the event elements 76 eventRead, err = s.GetEventByID(ctx, eventID) 77 assert.NoError(t, err) 78 // The generated sequence will have been added 79 eventUpdated.Sequence = event.Sequence 80 eventJson, _ = json.Marshal(&eventUpdated) 81 eventReadJson, _ = json.Marshal(&eventRead) 82 assert.Equal(t, string(eventJson), string(eventReadJson)) 83 84 // Query back the event 85 fb := database.EventQueryFactory.NewFilter(ctx) 86 filter := fb.And( 87 fb.Eq("id", eventUpdated.ID.String()), 88 fb.Eq("reference", eventUpdated.Reference.String()), 89 ) 90 events, err := s.GetEvents(ctx, filter) 91 assert.NoError(t, err) 92 assert.Equal(t, 1, len(events)) 93 eventReadJson, _ = json.Marshal(events[0]) 94 assert.Equal(t, string(eventJson), string(eventReadJson)) 95 96 // Negative test on filter 97 filter = fb.And( 98 fb.Eq("id", eventUpdated.ID.String()), 99 fb.Eq("reference", fftypes.NewUUID().String()), 100 ) 101 events, err = s.GetEvents(ctx, filter) 102 assert.NoError(t, err) 103 assert.Equal(t, 0, len(events)) 104 105 // Update 106 newUUID := fftypes.NewUUID() 107 up := database.EventQueryFactory.NewUpdate(ctx). 108 Set("reference", newUUID) 109 err = s.UpdateEvent(ctx, eventUpdated.ID, up) 110 assert.NoError(t, err) 111 112 // Test find updated value 113 filter = fb.And( 114 fb.Eq("id", eventUpdated.ID.String()), 115 fb.Eq("reference", newUUID), 116 ) 117 events, err = s.GetEvents(ctx, filter) 118 assert.NoError(t, err) 119 assert.Equal(t, 1, len(events)) 120 121 s.callbacks.AssertExpectations(t) 122 } 123 124 func TestUpsertEventFailBegin(t *testing.T) { 125 s, mock := newMockProvider().init() 126 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 127 err := s.UpsertEvent(context.Background(), &fftypes.Event{}, true) 128 assert.Regexp(t, "FF10114", err) 129 assert.NoError(t, mock.ExpectationsWereMet()) 130 } 131 132 func TestUpsertEventFailSelect(t *testing.T) { 133 s, mock := newMockProvider().init() 134 mock.ExpectBegin() 135 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 136 mock.ExpectRollback() 137 eventID := fftypes.NewUUID() 138 err := s.UpsertEvent(context.Background(), &fftypes.Event{ID: eventID}, true) 139 assert.Regexp(t, "FF10115", err) 140 assert.NoError(t, mock.ExpectationsWereMet()) 141 } 142 143 func TestUpsertEventFailInsert(t *testing.T) { 144 s, mock := newMockProvider().init() 145 mock.ExpectBegin() 146 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{})) 147 mock.ExpectExec("INSERT .*").WillReturnError(fmt.Errorf("pop")) 148 mock.ExpectRollback() 149 eventID := fftypes.NewUUID() 150 err := s.UpsertEvent(context.Background(), &fftypes.Event{ID: eventID}, true) 151 assert.Regexp(t, "FF10116", err) 152 assert.NoError(t, mock.ExpectationsWereMet()) 153 } 154 155 func TestUpsertEventFailUpdate(t *testing.T) { 156 s, mock := newMockProvider().init() 157 eventID := fftypes.NewUUID() 158 mock.ExpectBegin() 159 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(eventID.String())) 160 mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop")) 161 mock.ExpectRollback() 162 err := s.UpsertEvent(context.Background(), &fftypes.Event{ID: eventID}, true) 163 assert.Regexp(t, "FF10117", err) 164 assert.NoError(t, mock.ExpectationsWereMet()) 165 } 166 167 func TestUpsertEventFailCommit(t *testing.T) { 168 s, mock := newMockProvider().init() 169 eventID := fftypes.NewUUID() 170 mock.ExpectBegin() 171 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"})) 172 mock.ExpectExec("INSERT .*").WillReturnResult(sqlmock.NewResult(1, 1)) 173 mock.ExpectCommit().WillReturnError(fmt.Errorf("pop")) 174 err := s.UpsertEvent(context.Background(), &fftypes.Event{ID: eventID}, true) 175 assert.Regexp(t, "FF10119", err) 176 assert.NoError(t, mock.ExpectationsWereMet()) 177 } 178 179 func TestGetEventByIDSelectFail(t *testing.T) { 180 s, mock := newMockProvider().init() 181 eventID := fftypes.NewUUID() 182 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 183 _, err := s.GetEventByID(context.Background(), eventID) 184 assert.Regexp(t, "FF10115", err) 185 assert.NoError(t, mock.ExpectationsWereMet()) 186 } 187 188 func TestGetEventByIDNotFound(t *testing.T) { 189 s, mock := newMockProvider().init() 190 eventID := fftypes.NewUUID() 191 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"})) 192 msg, err := s.GetEventByID(context.Background(), eventID) 193 assert.NoError(t, err) 194 assert.Nil(t, msg) 195 assert.NoError(t, mock.ExpectationsWereMet()) 196 } 197 198 func TestGetEventByIDScanFail(t *testing.T) { 199 s, mock := newMockProvider().init() 200 eventID := fftypes.NewUUID() 201 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow("only one")) 202 _, err := s.GetEventByID(context.Background(), eventID) 203 assert.Regexp(t, "FF10121", err) 204 assert.NoError(t, mock.ExpectationsWereMet()) 205 } 206 207 func TestGetEventsQueryFail(t *testing.T) { 208 s, mock := newMockProvider().init() 209 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 210 f := database.EventQueryFactory.NewFilter(context.Background()).Eq("id", "") 211 _, err := s.GetEvents(context.Background(), f) 212 assert.Regexp(t, "FF10115", err) 213 assert.NoError(t, mock.ExpectationsWereMet()) 214 } 215 216 func TestGetEventsBuildQueryFail(t *testing.T) { 217 s, _ := newMockProvider().init() 218 f := database.EventQueryFactory.NewFilter(context.Background()).Eq("id", map[bool]bool{true: false}) 219 _, err := s.GetEvents(context.Background(), f) 220 assert.Regexp(t, "FF10149.*id", err) 221 } 222 223 func TestGettEventsReadMessageFail(t *testing.T) { 224 s, mock := newMockProvider().init() 225 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow("only one")) 226 f := database.EventQueryFactory.NewFilter(context.Background()).Eq("id", "") 227 _, err := s.GetEvents(context.Background(), f) 228 assert.Regexp(t, "FF10121", err) 229 assert.NoError(t, mock.ExpectationsWereMet()) 230 } 231 232 func TestEventUpdateBeginFail(t *testing.T) { 233 s, mock := newMockProvider().init() 234 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 235 u := database.EventQueryFactory.NewUpdate(context.Background()).Set("id", "anything") 236 err := s.UpdateEvent(context.Background(), fftypes.NewUUID(), u) 237 assert.Regexp(t, "FF10114", err) 238 } 239 240 func TestEventUpdateBuildQueryFail(t *testing.T) { 241 s, mock := newMockProvider().init() 242 mock.ExpectBegin() 243 u := database.EventQueryFactory.NewUpdate(context.Background()).Set("id", map[bool]bool{true: false}) 244 err := s.UpdateEvent(context.Background(), fftypes.NewUUID(), u) 245 assert.Regexp(t, "FF10149.*id", err) 246 } 247 248 func TestEventUpdateFail(t *testing.T) { 249 s, mock := newMockProvider().init() 250 mock.ExpectBegin() 251 mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop")) 252 mock.ExpectRollback() 253 u := database.EventQueryFactory.NewUpdate(context.Background()).Set("id", fftypes.NewUUID()) 254 err := s.UpdateEvent(context.Background(), fftypes.NewUUID(), u) 255 assert.Regexp(t, "FF10117", err) 256 }