github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/nonce_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 TestNoncesE2EWithDB(t *testing.T) { 33 log.SetLevel("trace") 34 35 s := newQLTestProvider(t) 36 defer s.Close() 37 ctx := context.Background() 38 39 // Create a new nonce entry 40 nonceZero := &fftypes.Nonce{ 41 Context: fftypes.NewRandB32(), 42 Group: fftypes.NewRandB32(), 43 Topic: "topic12345", 44 } 45 err := s.UpsertNonceNext(ctx, nonceZero) 46 assert.NoError(t, err) 47 48 // Check we get the exact same nonce back 49 nonceRead, err := s.GetNonce(ctx, nonceZero.Context) 50 assert.NoError(t, err) 51 assert.NotNil(t, nonceRead) 52 nonceJson, _ := json.Marshal(&nonceZero) 53 nonceReadJson, _ := json.Marshal(&nonceRead) 54 assert.Equal(t, string(nonceJson), string(nonceReadJson)) 55 56 // Update the nonce (this is testing what's possible at the database layer, 57 // and does not account for the verification that happens at the higher level) 58 var nonceUpdated fftypes.Nonce 59 nonceUpdated = *nonceZero 60 61 // Increment a couple of times 62 err = s.UpsertNonceNext(context.Background(), &nonceUpdated) 63 assert.NoError(t, err) 64 assert.Equal(t, int64(1), nonceUpdated.Nonce) 65 err = s.UpsertNonceNext(context.Background(), &nonceUpdated) 66 assert.NoError(t, err) 67 assert.Equal(t, int64(2), nonceUpdated.Nonce) 68 69 // Check we get the exact same data back 70 nonceRead, err = s.GetNonce(ctx, nonceUpdated.Context) 71 assert.NoError(t, err) 72 nonceJson, _ = json.Marshal(&nonceUpdated) 73 nonceReadJson, _ = json.Marshal(&nonceRead) 74 assert.Equal(t, string(nonceJson), string(nonceReadJson)) 75 76 // Query back the nonce 77 fb := database.NonceQueryFactory.NewFilter(ctx) 78 filter := fb.And( 79 fb.Eq("context", nonceUpdated.Context), 80 fb.Eq("nonce", nonceUpdated.Nonce), 81 fb.Eq("group", nonceUpdated.Group), 82 fb.Eq("topic", nonceUpdated.Topic), 83 ) 84 nonceRes, err := s.GetNonces(ctx, filter) 85 assert.NoError(t, err) 86 assert.Equal(t, 1, len(nonceRes)) 87 nonceReadJson, _ = json.Marshal(nonceRes[0]) 88 assert.Equal(t, string(nonceJson), string(nonceReadJson)) 89 90 // Test delete 91 err = s.DeleteNonce(ctx, nonceUpdated.Context) 92 assert.NoError(t, err) 93 nonces, err := s.GetNonces(ctx, filter) 94 assert.NoError(t, err) 95 assert.Equal(t, 0, len(nonces)) 96 97 } 98 99 func TestUpsertNonceFailBegin(t *testing.T) { 100 s, mock := newMockProvider().init() 101 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 102 err := s.UpsertNonceNext(context.Background(), &fftypes.Nonce{}) 103 assert.Regexp(t, "FF10114", err) 104 assert.NoError(t, mock.ExpectationsWereMet()) 105 } 106 107 func TestUpsertNonceFailSelect(t *testing.T) { 108 s, mock := newMockProvider().init() 109 mock.ExpectBegin() 110 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 111 mock.ExpectRollback() 112 err := s.UpsertNonceNext(context.Background(), &fftypes.Nonce{Context: fftypes.NewRandB32()}) 113 assert.Regexp(t, "FF10115", err) 114 assert.NoError(t, mock.ExpectationsWereMet()) 115 } 116 117 func TestUpsertNonceFailInsert(t *testing.T) { 118 s, mock := newMockProvider().init() 119 mock.ExpectBegin() 120 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{})) 121 mock.ExpectExec("INSERT .*").WillReturnError(fmt.Errorf("pop")) 122 mock.ExpectRollback() 123 err := s.UpsertNonceNext(context.Background(), &fftypes.Nonce{Context: fftypes.NewRandB32()}) 124 assert.Regexp(t, "FF10116", err) 125 assert.NoError(t, mock.ExpectationsWereMet()) 126 } 127 128 func TestUpsertNonceFailScan(t *testing.T) { 129 s, mock := newMockProvider().init() 130 mock.ExpectBegin() 131 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{}).AddRow()) 132 mock.ExpectRollback() 133 err := s.UpsertNonceNext(context.Background(), &fftypes.Nonce{Context: fftypes.NewRandB32()}) 134 assert.Regexp(t, "FF10121", err) 135 assert.NoError(t, mock.ExpectationsWereMet()) 136 } 137 138 func TestUpsertNonceFailUpdate(t *testing.T) { 139 s, mock := newMockProvider().init() 140 mock.ExpectBegin() 141 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"nonce", "sequence"}).AddRow(int64(12345), int64(11111))) 142 mock.ExpectExec("UPDATE .*").WillReturnError(fmt.Errorf("pop")) 143 mock.ExpectRollback() 144 err := s.UpsertNonceNext(context.Background(), &fftypes.Nonce{Context: fftypes.NewRandB32()}) 145 assert.Regexp(t, "FF10117", err) 146 assert.NoError(t, mock.ExpectationsWereMet()) 147 } 148 149 func TestGetNonceSelectFail(t *testing.T) { 150 s, mock := newMockProvider().init() 151 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 152 _, err := s.GetNonce(context.Background(), fftypes.NewRandB32()) 153 assert.Regexp(t, "FF10115", err) 154 assert.NoError(t, mock.ExpectationsWereMet()) 155 } 156 157 func TestGetNonceNotFound(t *testing.T) { 158 s, mock := newMockProvider().init() 159 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context", "nonce", "group_hash", "topic"})) 160 msg, err := s.GetNonce(context.Background(), fftypes.NewRandB32()) 161 assert.NoError(t, err) 162 assert.Nil(t, msg) 163 assert.NoError(t, mock.ExpectationsWereMet()) 164 } 165 166 func TestGetNonceScanFail(t *testing.T) { 167 s, mock := newMockProvider().init() 168 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context"}).AddRow("only one")) 169 _, err := s.GetNonce(context.Background(), fftypes.NewRandB32()) 170 assert.Regexp(t, "FF10121", err) 171 assert.NoError(t, mock.ExpectationsWereMet()) 172 } 173 174 func TestGetNonceQueryFail(t *testing.T) { 175 s, mock := newMockProvider().init() 176 mock.ExpectQuery("SELECT .*").WillReturnError(fmt.Errorf("pop")) 177 f := database.NonceQueryFactory.NewFilter(context.Background()).Eq("context", "") 178 _, err := s.GetNonces(context.Background(), f) 179 assert.Regexp(t, "FF10115", err) 180 assert.NoError(t, mock.ExpectationsWereMet()) 181 } 182 183 func TestGetNonceBuildQueryFail(t *testing.T) { 184 s, _ := newMockProvider().init() 185 f := database.NonceQueryFactory.NewFilter(context.Background()).Eq("context", map[bool]bool{true: false}) 186 _, err := s.GetNonces(context.Background(), f) 187 assert.Regexp(t, "FF10149.*context", err) 188 } 189 190 func TestGetNonceReadMessageFail(t *testing.T) { 191 s, mock := newMockProvider().init() 192 mock.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"context"}).AddRow("only one")) 193 f := database.NonceQueryFactory.NewFilter(context.Background()).Eq("topic", "") 194 _, err := s.GetNonces(context.Background(), f) 195 assert.Regexp(t, "FF10121", err) 196 assert.NoError(t, mock.ExpectationsWereMet()) 197 } 198 199 func TestNonceDeleteBeginFail(t *testing.T) { 200 s, mock := newMockProvider().init() 201 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 202 err := s.DeleteNonce(context.Background(), fftypes.NewRandB32()) 203 assert.Regexp(t, "FF10114", err) 204 } 205 206 func TestNonceDeleteFail(t *testing.T) { 207 s, mock := newMockProvider().init() 208 mock.ExpectBegin() 209 mock.ExpectExec("DELETE .*").WillReturnError(fmt.Errorf("pop")) 210 mock.ExpectRollback() 211 err := s.DeleteNonce(context.Background(), fftypes.NewRandB32()) 212 assert.Regexp(t, "FF10118", err) 213 }