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  }