github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/nextpin_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/internal/log" 27 "github.com/kaleido-io/firefly/pkg/database" 28 "github.com/kaleido-io/firefly/pkg/fftypes" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 func TestNextPinsE2EWithDB(t *testing.T) { 33 log.SetLevel("debug") 34 35 s := newQLTestProvider(t) 36 defer s.Close() 37 ctx := context.Background() 38 39 // Create a new nextpin entry 40 nextpin := &fftypes.NextPin{ 41 Context: fftypes.NewRandB32(), 42 Identity: "0x12345", 43 Hash: fftypes.NewRandB32(), 44 Nonce: int64(12345), 45 } 46 err := s.InsertNextPin(ctx, nextpin) 47 assert.NoError(t, err) 48 49 // Check we get the exact same nextpin back 50 nextpinRead, err := s.GetNextPinByContextAndIdentity(ctx, nextpin.Context, nextpin.Identity) 51 assert.NoError(t, err) 52 assert.NotNil(t, nextpinRead) 53 nextpinJson, _ := json.Marshal(&nextpin) 54 nextpinReadJson, _ := json.Marshal(&nextpinRead) 55 assert.Equal(t, string(nextpinJson), string(nextpinReadJson)) 56 57 // Attempt with wrong ID 58 var nextpinUpdated fftypes.NextPin 59 nextpinUpdated = *nextpin 60 nextpinUpdated.Nonce = 1111111 61 nextpinUpdated.Hash = fftypes.NewRandB32() 62 err = s.UpdateNextPin(context.Background(), nextpin.Sequence, database.NextPinQueryFactory.NewUpdate(ctx). 63 Set("hash", nextpinUpdated.Hash). 64 Set("nonce", nextpinUpdated.Nonce), 65 ) 66 67 // Check we get the exact same data back - note the removal of one of the nextpin elements 68 nextpinRead, err = s.GetNextPinByHash(ctx, nextpinUpdated.Hash) 69 assert.NoError(t, err) 70 nextpinJson, _ = json.Marshal(&nextpinUpdated) 71 nextpinReadJson, _ = json.Marshal(&nextpinRead) 72 assert.Equal(t, string(nextpinJson), string(nextpinReadJson)) 73 74 // Query back the nextpin 75 fb := database.NextPinQueryFactory.NewFilter(ctx) 76 filter := fb.And( 77 fb.Eq("context", nextpinUpdated.Context), 78 fb.Eq("hash", nextpinUpdated.Hash), 79 fb.Eq("identity", nextpinUpdated.Identity), 80 fb.Eq("nonce", nextpinUpdated.Nonce), 81 ) 82 nextpinRes, err := s.GetNextPins(ctx, filter) 83 assert.NoError(t, err) 84 assert.Equal(t, 1, len(nextpinRes)) 85 nextpinReadJson, _ = json.Marshal(nextpinRes[0]) 86 assert.Equal(t, string(nextpinJson), string(nextpinReadJson)) 87 88 // Test delete 89 err = s.DeleteNextPin(ctx, nextpinUpdated.Sequence) 90 assert.NoError(t, err) 91 nextpins, err := s.GetNextPins(ctx, filter) 92 assert.NoError(t, err) 93 assert.Equal(t, 0, len(nextpins)) 94 95 } 96 97 func TestUpsertNextPinFailBegin(t *testing.T) { 98 s, mock := newMockProvider().init() 99 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 100 err := s.InsertNextPin(context.Background(), &fftypes.NextPin{}) 101 assert.Regexp(t, "FF10114", err) 102 assert.NoError(t, mock.ExpectationsWereMet()) 103 } 104 105 func TestUpsertNextPinFailInsert(t *testing.T) { 106 s, mock := newMockProvider().init() 107 mock.ExpectBegin() 108 mock.ExpectExec("INSERT .*").WillReturnError(fmt.Errorf("pop")) 109 mock.ExpectRollback() 110 err := s.InsertNextPin(context.Background(), &fftypes.NextPin{Context: fftypes.NewRandB32()}) 111 assert.Regexp(t, "FF10116", err) 112 assert.NoError(t, mock.ExpectationsWereMet()) 113 } 114 115 func TestUpsertNextPinFailCommit(t *testing.T) { 116 s, mock := newMockProvider().init() 117 mock.ExpectBegin() 118 mock.ExpectExec("INSERT .*").WillReturnResult(sqlmock.NewResult(1, 1)) 119 mock.ExpectCommit().WillReturnError(fmt.Errorf("pop")) 120 err := s.InsertNextPin(context.Background(), &fftypes.NextPin{Context: fftypes.NewRandB32()}) 121 assert.Regexp(t, "FF10119", err) 122 assert.NoError(t, mock.ExpectationsWereMet()) 123 } 124 125 func TestGetNextPinByIDSelectFail(t *testing.T) { 126 s, mock := newMockProvider().init() 127 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 128 _, err := s.GetNextPinByContextAndIdentity(context.Background(), fftypes.NewRandB32(), "0x12345") 129 assert.Regexp(t, "FF10115", err) 130 assert.NoError(t, mock.ExpectationsWereMet()) 131 } 132 133 func TestGetNextPinByIDNotFound(t *testing.T) { 134 s, mock := newMockProvider().init() 135 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{})) 136 msg, err := s.GetNextPinByContextAndIdentity(context.Background(), fftypes.NewRandB32(), "0x12345") 137 assert.NoError(t, err) 138 assert.Nil(t, msg) 139 assert.NoError(t, mock.ExpectationsWereMet()) 140 } 141 142 func TestGetNextPinByIDScanFail(t *testing.T) { 143 s, mock := newMockProvider().init() 144 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context"}).AddRow("only one")) 145 _, err := s.GetNextPinByContextAndIdentity(context.Background(), fftypes.NewRandB32(), "0x12345") 146 assert.Regexp(t, "FF10121", err) 147 assert.NoError(t, mock.ExpectationsWereMet()) 148 } 149 150 func TestGetNextPinQueryFail(t *testing.T) { 151 s, mock := newMockProvider().init() 152 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 153 f := database.NextPinQueryFactory.NewFilter(context.Background()).Eq("context", "") 154 _, err := s.GetNextPins(context.Background(), f) 155 assert.Regexp(t, "FF10115", err) 156 assert.NoError(t, mock.ExpectationsWereMet()) 157 } 158 159 func TestGetNextPinBuildQueryFail(t *testing.T) { 160 s, _ := newMockProvider().init() 161 f := database.NextPinQueryFactory.NewFilter(context.Background()).Eq("context", map[bool]bool{true: false}) 162 _, err := s.GetNextPins(context.Background(), f) 163 assert.Regexp(t, "FF10149.*type", err) 164 } 165 166 func TestGetNextPinReadMessageFail(t *testing.T) { 167 s, mock := newMockProvider().init() 168 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context"}).AddRow("only one")) 169 f := database.NextPinQueryFactory.NewFilter(context.Background()).Eq("context", "") 170 _, err := s.GetNextPins(context.Background(), f) 171 assert.Regexp(t, "FF10121", err) 172 assert.NoError(t, mock.ExpectationsWereMet()) 173 } 174 175 func TestNextPinUpdateBeginFail(t *testing.T) { 176 s, mock := newMockProvider().init() 177 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 178 u := database.NextPinQueryFactory.NewUpdate(context.Background()).Set("context", "anything") 179 err := s.UpdateNextPin(context.Background(), 12345, u) 180 assert.Regexp(t, "FF10114", err) 181 } 182 183 func TestNextPinUpdateBuildQueryFail(t *testing.T) { 184 s, mock := newMockProvider().init() 185 mock.ExpectBegin() 186 u := database.NextPinQueryFactory.NewUpdate(context.Background()).Set("context", map[bool]bool{true: false}) 187 err := s.UpdateNextPin(context.Background(), 12345, u) 188 assert.Regexp(t, "FF10149.*context", err) 189 } 190 191 func TestNextPinUpdateFail(t *testing.T) { 192 s, mock := newMockProvider().init() 193 mock.ExpectBegin() 194 mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop")) 195 mock.ExpectRollback() 196 u := database.NextPinQueryFactory.NewUpdate(context.Background()).Set("context", fftypes.NewUUID()) 197 err := s.UpdateNextPin(context.Background(), 12345, u) 198 assert.Regexp(t, "FF10117", err) 199 } 200 201 func TestNextPinDeleteBeginFail(t *testing.T) { 202 s, mock := newMockProvider().init() 203 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 204 err := s.DeleteNextPin(context.Background(), 12345) 205 assert.Regexp(t, "FF10114", err) 206 } 207 208 func TestNextPinDeleteFail(t *testing.T) { 209 s, mock := newMockProvider().init() 210 mock.ExpectBegin() 211 mock.ExpectExec("DELETE .*").WillReturnError(fmt.Errorf("pop")) 212 mock.ExpectRollback() 213 err := s.DeleteNextPin(context.Background(), 12345) 214 assert.Regexp(t, "FF10118", err) 215 }