github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/sqlcommon_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 "database/sql/driver" 22 "fmt" 23 "testing" 24 25 "github.com/DATA-DOG/go-sqlmock" 26 sq "github.com/Masterminds/squirrel" 27 "github.com/stretchr/testify/assert" 28 ) 29 30 func TestInitSQLCommon(t *testing.T) { 31 s := newQLTestProvider(t) 32 defer s.Close() 33 assert.NotNil(t, s.Capabilities()) 34 assert.NotNil(t, s.DB()) 35 } 36 37 func TestInitSQLCommonMissingOptions(t *testing.T) { 38 s := &SQLCommon{} 39 err := s.Init(context.Background(), nil, nil, nil, nil) 40 assert.Regexp(t, "FF10112", err) 41 } 42 43 func TestInitSQLCommonOpenFailed(t *testing.T) { 44 mp := newMockProvider() 45 mp.openError = fmt.Errorf("pop") 46 err := mp.SQLCommon.Init(context.Background(), mp, mp.prefix, mp.callbacks, mp.capabilities) 47 assert.Regexp(t, "FF10112.*pop", err) 48 } 49 50 func TestInitSQLCommonMigrationOpenFailed(t *testing.T) { 51 mp := newMockProvider() 52 mp.prefix.Set(SQLConfMigrationsAuto, true) 53 mp.getMigrationDriverError = fmt.Errorf("pop") 54 err := mp.SQLCommon.Init(context.Background(), mp, mp.prefix, mp.callbacks, mp.capabilities) 55 assert.Regexp(t, "FF10163.*pop", err) 56 } 57 58 func TestQueryTxBadSQL(t *testing.T) { 59 tp := newQLTestProvider(t) 60 _, err := tp.queryTx(context.Background(), nil, sq.SelectBuilder{}) 61 assert.Regexp(t, "FF10113", err) 62 } 63 64 func TestInsertTxPostgreSQLReturnedSyntax(t *testing.T) { 65 s, mdb := newMockProvider().init() 66 mdb.ExpectBegin() 67 mdb.ExpectQuery("INSERT.*").WillReturnRows(sqlmock.NewRows([]string{"seq"}).AddRow(12345)) 68 ctx, tx, _, err := s.beginOrUseTx(context.Background()) 69 assert.NoError(t, err) 70 s.fakePSQLInsert = true 71 sb := sq.Insert("table").Columns("col1").Values(("val1")) 72 sequence, err := s.insertTx(ctx, tx, sb) 73 assert.NoError(t, err) 74 assert.Equal(t, int64(12345), sequence) 75 } 76 77 func TestInsertTxPostgreSQLReturnedSyntaxFail(t *testing.T) { 78 s, mdb := newMockProvider().init() 79 mdb.ExpectBegin() 80 mdb.ExpectQuery("INSERT.*").WillReturnError(fmt.Errorf("pop")) 81 ctx, tx, _, err := s.beginOrUseTx(context.Background()) 82 assert.NoError(t, err) 83 s.fakePSQLInsert = true 84 sb := sq.Insert("table").Columns("col1").Values(("val1")) 85 _, err = s.insertTx(ctx, tx, sb) 86 assert.Regexp(t, "FF10116", err) 87 } 88 89 func TestInsertTxBadSQL(t *testing.T) { 90 s, _ := newMockProvider().init() 91 _, err := s.insertTx(context.Background(), nil, sq.InsertBuilder{}) 92 assert.Regexp(t, "FF10113", err) 93 } 94 95 func TestUpdateTxBadSQL(t *testing.T) { 96 s, _ := newMockProvider().init() 97 err := s.updateTx(context.Background(), nil, sq.UpdateBuilder{}) 98 assert.Regexp(t, "FF10113", err) 99 } 100 101 func TestDeleteTxBadSQL(t *testing.T) { 102 s, _ := newMockProvider().init() 103 err := s.deleteTx(context.Background(), nil, sq.DeleteBuilder{}) 104 assert.Regexp(t, "FF10113", err) 105 } 106 107 func TestDeleteTxZeroRowsAffected(t *testing.T) { 108 s, mdb := newMockProvider().init() 109 mdb.ExpectBegin() 110 mdb.ExpectExec("DELETE.*").WillReturnResult(driver.ResultNoRows) 111 ctx, tx, _, err := s.beginOrUseTx(context.Background()) 112 assert.NoError(t, err) 113 s.fakePSQLInsert = true 114 sb := sq.Delete("table") 115 err = s.deleteTx(ctx, tx, sb) 116 assert.Regexp(t, "FF10109", err) 117 } 118 119 func TestRunAsGroup(t *testing.T) { 120 s, mock := newMockProvider().init() 121 mock.ExpectBegin() 122 mock.ExpectExec("INSERT.*").WillReturnResult(driver.ResultNoRows) 123 mock.ExpectExec("INSERT.*").WillReturnResult(driver.ResultNoRows) 124 mock.ExpectQuery("SELECT.*").WillReturnRows(sqlmock.NewRows([]string{"id"})) 125 mock.ExpectCommit() 126 127 err := s.RunAsGroup(context.Background(), func(ctx context.Context) (err error) { 128 // First insert 129 ctx, tx, ac, err := s.beginOrUseTx(ctx) 130 assert.NoError(t, err) 131 _, err = s.insertTx(ctx, tx, sq.Insert("test").Columns("test").Values("test")) 132 assert.NoError(t, err) 133 err = s.commitTx(ctx, tx, ac) 134 assert.NoError(t, err) 135 136 // Second insert 137 ctx, tx, ac, err = s.beginOrUseTx(ctx) 138 assert.NoError(t, err) 139 _, err = s.insertTx(ctx, tx, sq.Insert("test").Columns("test").Values("test")) 140 assert.NoError(t, err) 141 err = s.commitTx(ctx, tx, ac) 142 assert.NoError(t, err) 143 144 // Query, not specifying a transaction 145 _, err = s.query(ctx, sq.Select("test").From("test")) 146 assert.NoError(t, err) 147 return 148 }) 149 150 assert.NoError(t, mock.ExpectationsWereMet()) 151 assert.NoError(t, err) 152 } 153 154 func TestRunAsGroupBeginFail(t *testing.T) { 155 s, mock := newMockProvider().init() 156 mock.ExpectBegin().WillReturnError(fmt.Errorf("pop")) 157 err := s.RunAsGroup(context.Background(), func(ctx context.Context) (err error) { 158 return 159 }) 160 assert.NoError(t, mock.ExpectationsWereMet()) 161 assert.Regexp(t, "FF10114", err) 162 } 163 164 func TestRunAsGroupFunctionFails(t *testing.T) { 165 s, mock := newMockProvider().init() 166 mock.ExpectBegin() 167 mock.ExpectExec("INSERT.*").WillReturnResult(driver.ResultNoRows) 168 mock.ExpectRollback() 169 err := s.RunAsGroup(context.Background(), func(ctx context.Context) (err error) { 170 ctx, tx, ac, err := s.beginOrUseTx(ctx) 171 assert.NoError(t, err) 172 _, err = s.insertTx(ctx, tx, sq.Insert("test").Columns("test").Values("test")) 173 assert.NoError(t, err) 174 s.rollbackTx(ctx, tx, ac) // won't actually rollback 175 assert.NoError(t, err) 176 177 return fmt.Errorf("pop") 178 }) 179 assert.NoError(t, mock.ExpectationsWereMet()) 180 assert.Regexp(t, "pop", err) 181 } 182 183 func TestRunAsGroupCommitFail(t *testing.T) { 184 s, mock := newMockProvider().init() 185 mock.ExpectBegin() 186 mock.ExpectCommit().WillReturnError(fmt.Errorf("pop")) 187 err := s.RunAsGroup(context.Background(), func(ctx context.Context) (err error) { 188 return 189 }) 190 assert.NoError(t, mock.ExpectationsWereMet()) 191 assert.Regexp(t, "FF10119", err) 192 } 193 194 func TestRollbackFail(t *testing.T) { 195 s, mock := newMockProvider().init() 196 mock.ExpectBegin() 197 tx, _ := s.db.Begin() 198 mock.ExpectRollback().WillReturnError(fmt.Errorf("pop")) 199 s.rollbackTx(context.Background(), &txWrapper{sqlTX: tx}, false) 200 assert.NoError(t, mock.ExpectationsWereMet()) 201 }