2014-02-07 11:44:41 +03:00
/ *
2016-01-21 21:09:44 +02:00
Package sqlmock is a mock library implementing sql driver . Which has one and only
purpose - to simulate any sql driver behavior in tests , without needing a real
database connection . It helps to maintain correct * * TDD * * workflow .
2015-08-26 15:59:28 +02:00
It does not require any modifications to your source code in order to test
2016-01-21 21:09:44 +02:00
and mock database operations . Supports concurrency and multiple database mocking .
2015-08-26 15:59:28 +02:00
2016-01-21 21:09:44 +02:00
The driver allows to mock any sql driver method behavior .
2014-02-07 11:44:41 +03:00
* /
2014-02-05 17:21:07 +03:00
package sqlmock
import (
2015-09-10 20:31:35 +02:00
"database/sql"
2014-02-05 17:21:07 +03:00
"database/sql/driver"
"fmt"
2017-02-06 14:38:57 +02:00
"time"
2014-02-05 17:21:07 +03:00
)
2015-08-28 10:06:14 +02:00
// Sqlmock interface serves to create expectations
// for any kind of database action in order to mock
// and test real database behavior.
type Sqlmock interface {
// ExpectClose queues an expectation for this database
// action to be triggered. the *ExpectedClose allows
// to mock database response
ExpectClose ( ) * ExpectedClose
// ExpectationsWereMet checks whether all queued expectations
// were met in order. If any of them was not met - an error is returned.
ExpectationsWereMet ( ) error
2018-12-11 14:56:33 +02:00
// ExpectPrepare expects Prepare() to be called with expectedSQL query.
2015-08-28 10:06:14 +02:00
// the *ExpectedPrepare allows to mock database response.
// Note that you may expect Query() or Exec() on the *ExpectedPrepare
2018-12-11 14:56:33 +02:00
// statement to prevent repeating expectedSQL
ExpectPrepare ( expectedSQL string ) * ExpectedPrepare
2015-08-28 10:06:14 +02:00
2018-12-11 14:56:33 +02:00
// ExpectQuery expects Query() or QueryRow() to be called with expectedSQL query.
2015-08-28 10:06:14 +02:00
// the *ExpectedQuery allows to mock database response.
2018-12-11 14:56:33 +02:00
ExpectQuery ( expectedSQL string ) * ExpectedQuery
2015-08-28 10:06:14 +02:00
2018-12-11 14:56:33 +02:00
// ExpectExec expects Exec() to be called with expectedSQL query.
2015-08-28 10:06:14 +02:00
// the *ExpectedExec allows to mock database response
2018-12-11 14:56:33 +02:00
ExpectExec ( expectedSQL string ) * ExpectedExec
2015-08-28 10:06:14 +02:00
// ExpectBegin expects *sql.DB.Begin to be called.
// the *ExpectedBegin allows to mock database response
ExpectBegin ( ) * ExpectedBegin
// ExpectCommit expects *sql.Tx.Commit to be called.
// the *ExpectedCommit allows to mock database response
ExpectCommit ( ) * ExpectedCommit
// ExpectRollback expects *sql.Tx.Rollback to be called.
// the *ExpectedRollback allows to mock database response
ExpectRollback ( ) * ExpectedRollback
2015-08-26 13:28:01 +02:00
2019-11-04 20:02:04 +02:00
// ExpectPing expected *sql.DB.Ping to be called.
// the *ExpectedPing allows to mock database response
//
// Ping support only exists in the SQL library in Go 1.8 and above.
// ExpectPing in Go <=1.7 will return an ExpectedPing but not register
// any expectations.
//
// You must enable pings using MonitorPingsOption for this to register
// any expectations.
ExpectPing ( ) * ExpectedPing
2015-08-26 13:28:01 +02:00
// MatchExpectationsInOrder gives an option whether to match all
// expectations in the order they were set or not.
//
// By default it is set to - true. But if you use goroutines
// to parallelize your query executation, that option may
// be handy.
2017-02-08 15:09:40 +02:00
//
// This option may be turned on anytime during tests. As soon
// as it is switched to false, expectations will be matched
// in any order. Or otherwise if switched to true, any unmatched
// expectations will be expected in order
2015-08-28 10:06:14 +02:00
MatchExpectationsInOrder ( bool )
2018-08-06 22:29:24 +02:00
// NewRows allows Rows to be created from a
// sql driver.Value slice or from the CSV string and
// to be used as sql driver.Rows.
NewRows ( columns [ ] string ) * Rows
2015-08-28 10:06:14 +02:00
}
2015-08-26 13:28:01 +02:00
2015-08-28 10:06:14 +02:00
type sqlmock struct {
2018-12-11 14:22:16 +02:00
ordered bool
dsn string
opened int
drv * mockDriver
converter driver . ValueConverter
queryMatcher QueryMatcher
2019-11-04 20:02:04 +02:00
monitorPings bool
2014-02-05 17:21:07 +03:00
2015-07-17 12:14:30 +02:00
expected [ ] expectation
2014-02-05 17:21:07 +03:00
}
2018-08-06 22:29:24 +02:00
func ( c * sqlmock ) open ( options [ ] func ( * sqlmock ) error ) ( * sql . DB , Sqlmock , error ) {
2016-01-21 21:09:44 +02:00
db , err := sql . Open ( "sqlmock" , c . dsn )
2015-09-10 20:31:35 +02:00
if err != nil {
2016-01-21 21:09:44 +02:00
return db , c , err
2015-09-10 20:31:35 +02:00
}
2018-08-06 22:29:24 +02:00
for _ , option := range options {
err := option ( c )
if err != nil {
return db , c , err
}
}
if c . converter == nil {
c . converter = driver . DefaultParameterConverter
}
2018-12-11 14:22:16 +02:00
if c . queryMatcher == nil {
c . queryMatcher = QueryMatcherRegexp
}
2019-11-04 20:02:04 +02:00
if c . monitorPings {
// We call Ping on the driver shortly to verify startup assertions by
// driving internal behaviour of the sql standard library. We don't
// want this call to ping to be monitored for expectation purposes so
// temporarily disable.
c . monitorPings = false
defer func ( ) { c . monitorPings = true } ( )
}
2016-01-21 21:09:44 +02:00
return db , c , db . Ping ( )
2015-09-10 20:31:35 +02:00
}
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) ExpectClose ( ) * ExpectedClose {
2015-07-17 12:14:30 +02:00
e := & ExpectedClose { }
c . expected = append ( c . expected , e )
return e
2014-02-05 17:21:07 +03:00
}
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) MatchExpectationsInOrder ( b bool ) {
c . ordered = b
}
2015-07-17 12:14:30 +02:00
// Close a mock database driver connection. It may or may not
2019-02-27 21:44:03 +02:00
// be called depending on the circumstances, but if it is called
2015-07-17 12:14:30 +02:00
// there must be an *ExpectedClose expectation satisfied.
// meets http://golang.org/pkg/database/sql/driver/#Conn interface
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) Close ( ) error {
2015-07-17 12:14:30 +02:00
c . drv . Lock ( )
defer c . drv . Unlock ( )
c . opened --
if c . opened == 0 {
delete ( c . drv . conns , c . dsn )
}
2015-08-26 13:28:01 +02:00
var expected * ExpectedClose
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
var ok bool
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
if expected , ok = next . ( * ExpectedClose ) ; ok {
break
}
next . Unlock ( )
2015-08-28 10:06:14 +02:00
if c . ordered {
2015-08-26 15:59:28 +02:00
return fmt . Errorf ( "call to database Close, was not expected, next expectation is: %s" , next )
2015-08-26 13:28:01 +02:00
}
}
2015-08-26 15:59:28 +02:00
2015-08-26 13:28:01 +02:00
if expected == nil {
2015-08-26 15:59:28 +02:00
msg := "call to database Close was not expected"
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return fmt . Errorf ( msg )
2015-07-17 12:14:30 +02:00
}
2015-08-26 13:28:01 +02:00
expected . triggered = true
expected . Unlock ( )
return expected . err
2014-02-05 17:21:07 +03:00
}
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) ExpectationsWereMet ( ) error {
2015-07-17 12:14:30 +02:00
for _ , e := range c . expected {
2018-12-20 20:00:51 +02:00
e . Lock ( )
fulfilled := e . fulfilled ( )
e . Unlock ( )
if ! fulfilled {
2015-08-26 15:59:28 +02:00
return fmt . Errorf ( "there is a remaining expectation which was not matched: %s" , e )
2015-07-17 12:14:30 +02:00
}
2017-09-01 09:24:02 +02:00
// for expected prepared statement check whether it was closed if expected
if prep , ok := e . ( * ExpectedPrepare ) ; ok {
if prep . mustBeClosed && ! prep . wasClosed {
return fmt . Errorf ( "expected prepared statement to be closed, but it was not: %s" , prep )
}
}
2018-12-11 17:38:12 +02:00
// must check whether all expected queried rows are closed
if query , ok := e . ( * ExpectedQuery ) ; ok {
if query . rowsMustBeClosed && ! query . rowsWereClosed {
return fmt . Errorf ( "expected query rows to be closed, but it was not: %s" , query )
}
}
2014-04-21 18:21:28 +03:00
}
2015-07-17 12:14:30 +02:00
return nil
2014-04-21 18:21:28 +03:00
}
2015-07-17 12:14:30 +02:00
// Begin meets http://golang.org/pkg/database/sql/driver/#Conn interface
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) Begin ( ) ( driver . Tx , error ) {
2017-02-07 15:03:05 +02:00
ex , err := c . begin ( )
2018-02-21 02:30:20 +02:00
if ex != nil {
time . Sleep ( ex . delay )
}
2017-02-07 12:20:08 +02:00
if err != nil {
return nil , err
}
return c , nil
}
2017-02-07 15:03:05 +02:00
func ( c * sqlmock ) begin ( ) ( * ExpectedBegin , error ) {
2015-08-26 13:28:01 +02:00
var expected * ExpectedBegin
var ok bool
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
if expected , ok = next . ( * ExpectedBegin ) ; ok {
break
}
next . Unlock ( )
2015-08-28 10:06:14 +02:00
if c . ordered {
2015-08-26 15:59:28 +02:00
return nil , fmt . Errorf ( "call to database transaction Begin, was not expected, next expectation is: %s" , next )
2015-08-26 13:28:01 +02:00
}
}
if expected == nil {
2015-08-26 15:59:28 +02:00
msg := "call to database transaction Begin was not expected"
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return nil , fmt . Errorf ( msg )
2015-07-17 12:14:30 +02:00
}
2015-08-26 13:28:01 +02:00
expected . triggered = true
expected . Unlock ( )
2017-02-07 12:20:08 +02:00
return expected , expected . err
2014-02-05 17:21:07 +03:00
}
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) ExpectBegin ( ) * ExpectedBegin {
2015-07-17 12:14:30 +02:00
e := & ExpectedBegin { }
c . expected = append ( c . expected , e )
return e
2014-02-05 17:21:07 +03:00
}
2015-07-17 12:14:30 +02:00
// Exec meets http://golang.org/pkg/database/sql/driver/#Execer
2017-02-06 14:38:57 +02:00
func ( c * sqlmock ) Exec ( query string , args [ ] driver . Value ) ( driver . Result , error ) {
2019-11-28 12:51:27 +02:00
namedArgs := make ( [ ] driver . NamedValue , len ( args ) )
2017-02-06 14:38:57 +02:00
for i , v := range args {
2019-11-28 12:51:27 +02:00
namedArgs [ i ] = driver . NamedValue {
2017-02-06 14:38:57 +02:00
Ordinal : i + 1 ,
Value : v ,
}
}
2017-02-07 12:20:08 +02:00
2017-02-07 15:03:05 +02:00
ex , err := c . exec ( query , namedArgs )
2018-02-21 02:30:20 +02:00
if ex != nil {
time . Sleep ( ex . delay )
}
2017-02-07 12:20:08 +02:00
if err != nil {
return nil , err
}
2017-02-07 15:03:05 +02:00
return ex . result , nil
2017-02-06 14:38:57 +02:00
}
2019-11-28 12:51:27 +02:00
func ( c * sqlmock ) exec ( query string , args [ ] driver . NamedValue ) ( * ExpectedExec , error ) {
2015-08-26 13:28:01 +02:00
var expected * ExpectedExec
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
var ok bool
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
2015-08-28 10:06:14 +02:00
if c . ordered {
2015-08-26 13:28:01 +02:00
if expected , ok = next . ( * ExpectedExec ) ; ok {
break
}
next . Unlock ( )
2017-04-26 08:56:02 +02:00
return nil , fmt . Errorf ( "call to ExecQuery '%s' with args %+v, was not expected, next expectation is: %s" , query , args , next )
2015-08-26 13:28:01 +02:00
}
if exec , ok := next . ( * ExpectedExec ) ; ok {
2018-12-11 14:56:33 +02:00
if err := c . queryMatcher . Match ( exec . expectSQL , query ) ; err != nil {
next . Unlock ( )
continue
}
if err := exec . attemptArgMatch ( args ) ; err == nil {
2015-08-26 13:28:01 +02:00
expected = exec
break
}
}
next . Unlock ( )
}
if expected == nil {
2017-04-26 08:56:02 +02:00
msg := "call to ExecQuery '%s' with args %+v was not expected"
2015-08-26 15:59:28 +02:00
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return nil , fmt . Errorf ( msg , query , args )
2015-07-17 12:14:30 +02:00
}
2017-02-07 12:20:08 +02:00
defer expected . Unlock ( )
2015-07-17 12:14:30 +02:00
2018-12-11 14:56:33 +02:00
if err := c . queryMatcher . Match ( expected . expectSQL , query ) ; err != nil {
return nil , fmt . Errorf ( "ExecQuery: %v" , err )
2015-07-17 12:14:30 +02:00
}
2016-02-23 11:14:34 +02:00
if err := expected . argsMatches ( args ) ; err != nil {
2017-04-26 08:56:02 +02:00
return nil , fmt . Errorf ( "ExecQuery '%s', arguments do not match: %s" , query , err )
2015-07-17 12:14:30 +02:00
}
2016-02-26 18:07:19 +02:00
expected . triggered = true
2015-08-26 13:28:01 +02:00
if expected . err != nil {
2018-02-21 02:30:20 +02:00
return expected , expected . err // mocked to return error
2015-07-17 12:14:30 +02:00
}
2015-08-26 13:28:01 +02:00
if expected . result == nil {
2017-04-26 08:56:02 +02:00
return nil , fmt . Errorf ( "ExecQuery '%s' with args %+v, must return a database/sql/driver.Result, but it was not set for expectation %T as %+v" , query , args , expected , expected )
2015-07-17 12:14:30 +02:00
}
2016-02-26 18:07:19 +02:00
2017-02-07 12:20:08 +02:00
return expected , nil
}
2018-12-11 14:56:33 +02:00
func ( c * sqlmock ) ExpectExec ( expectedSQL string ) * ExpectedExec {
2015-07-17 12:14:30 +02:00
e := & ExpectedExec { }
2018-12-11 14:56:33 +02:00
e . expectSQL = expectedSQL
2018-08-06 22:29:24 +02:00
e . converter = c . converter
2015-07-17 12:14:30 +02:00
c . expected = append ( c . expected , e )
return e
2014-09-24 00:38:15 +03:00
}
2015-07-17 12:14:30 +02:00
// Prepare meets http://golang.org/pkg/database/sql/driver/#Conn interface
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) Prepare ( query string ) ( driver . Stmt , error ) {
2017-02-07 15:03:05 +02:00
ex , err := c . prepare ( query )
2018-02-21 02:30:20 +02:00
if ex != nil {
time . Sleep ( ex . delay )
}
2017-02-07 12:20:08 +02:00
if err != nil {
return nil , err
}
2017-09-01 09:24:02 +02:00
return & statement { c , ex , query } , nil
2017-02-07 12:20:08 +02:00
}
2017-02-07 15:03:05 +02:00
func ( c * sqlmock ) prepare ( query string ) ( * ExpectedPrepare , error ) {
2015-08-26 13:28:01 +02:00
var expected * ExpectedPrepare
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
var ok bool
2017-05-31 22:54:14 +02:00
2015-08-26 13:28:01 +02:00
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
2015-07-17 12:14:30 +02:00
2015-08-28 10:06:14 +02:00
if c . ordered {
2017-05-30 21:44:56 +02:00
if expected , ok = next . ( * ExpectedPrepare ) ; ok {
break
}
next . Unlock ( )
2016-04-13 21:19:21 +02:00
return nil , fmt . Errorf ( "call to Prepare statement with query '%s', was not expected, next expectation is: %s" , query , next )
2015-08-26 13:28:01 +02:00
}
2017-05-31 22:54:14 +02:00
2017-05-30 21:44:56 +02:00
if pr , ok := next . ( * ExpectedPrepare ) ; ok {
2018-12-11 14:56:33 +02:00
if err := c . queryMatcher . Match ( pr . expectSQL , query ) ; err == nil {
2017-05-30 21:44:56 +02:00
expected = pr
break
}
}
next . Unlock ( )
2015-07-17 12:14:30 +02:00
}
2015-08-26 13:28:01 +02:00
if expected == nil {
2015-08-26 15:59:28 +02:00
msg := "call to Prepare '%s' query was not expected"
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return nil , fmt . Errorf ( msg , query )
2015-07-17 12:14:30 +02:00
}
2017-02-07 12:20:08 +02:00
defer expected . Unlock ( )
2018-12-11 14:56:33 +02:00
if err := c . queryMatcher . Match ( expected . expectSQL , query ) ; err != nil {
return nil , fmt . Errorf ( "Prepare: %v" , err )
2016-11-02 14:49:59 +02:00
}
2015-07-17 12:14:30 +02:00
2015-08-26 13:28:01 +02:00
expected . triggered = true
2017-02-07 12:20:08 +02:00
return expected , expected . err
}
2018-12-11 14:56:33 +02:00
func ( c * sqlmock ) ExpectPrepare ( expectedSQL string ) * ExpectedPrepare {
e := & ExpectedPrepare { expectSQL : expectedSQL , mock : c }
2015-07-17 12:14:30 +02:00
c . expected = append ( c . expected , e )
return e
2014-02-05 17:21:07 +03:00
}
2015-07-17 12:14:30 +02:00
// Query meets http://golang.org/pkg/database/sql/driver/#Queryer
2017-02-07 12:20:08 +02:00
func ( c * sqlmock ) Query ( query string , args [ ] driver . Value ) ( driver . Rows , error ) {
2019-11-28 12:51:27 +02:00
namedArgs := make ( [ ] driver . NamedValue , len ( args ) )
2017-02-06 14:38:57 +02:00
for i , v := range args {
2019-11-28 12:51:27 +02:00
namedArgs [ i ] = driver . NamedValue {
2017-02-06 14:38:57 +02:00
Ordinal : i + 1 ,
Value : v ,
}
}
2017-02-07 12:20:08 +02:00
2017-02-07 15:03:05 +02:00
ex , err := c . query ( query , namedArgs )
2018-02-21 02:30:20 +02:00
if ex != nil {
time . Sleep ( ex . delay )
}
2017-02-07 12:20:08 +02:00
if err != nil {
return nil , err
}
2017-02-07 15:03:05 +02:00
return ex . rows , nil
2017-02-06 14:38:57 +02:00
}
2019-11-28 12:51:27 +02:00
func ( c * sqlmock ) query ( query string , args [ ] driver . NamedValue ) ( * ExpectedQuery , error ) {
2015-08-26 13:28:01 +02:00
var expected * ExpectedQuery
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
var ok bool
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
2015-08-28 10:06:14 +02:00
if c . ordered {
2015-08-26 13:28:01 +02:00
if expected , ok = next . ( * ExpectedQuery ) ; ok {
break
}
next . Unlock ( )
2017-04-26 08:56:02 +02:00
return nil , fmt . Errorf ( "call to Query '%s' with args %+v, was not expected, next expectation is: %s" , query , args , next )
2015-08-26 13:28:01 +02:00
}
if qr , ok := next . ( * ExpectedQuery ) ; ok {
2018-12-11 14:56:33 +02:00
if err := c . queryMatcher . Match ( qr . expectSQL , query ) ; err != nil {
next . Unlock ( )
continue
}
if err := qr . attemptArgMatch ( args ) ; err == nil {
2015-08-26 13:28:01 +02:00
expected = qr
break
}
}
next . Unlock ( )
}
2015-08-26 15:59:28 +02:00
2015-08-26 13:28:01 +02:00
if expected == nil {
2017-04-26 08:56:02 +02:00
msg := "call to Query '%s' with args %+v was not expected"
2015-08-26 15:59:28 +02:00
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return nil , fmt . Errorf ( msg , query , args )
2015-07-17 12:14:30 +02:00
}
2017-02-07 12:20:08 +02:00
defer expected . Unlock ( )
2018-12-11 14:56:33 +02:00
if err := c . queryMatcher . Match ( expected . expectSQL , query ) ; err != nil {
return nil , fmt . Errorf ( "Query: %v" , err )
2015-07-17 12:14:30 +02:00
}
2016-02-23 11:14:34 +02:00
if err := expected . argsMatches ( args ) ; err != nil {
2017-04-26 08:56:02 +02:00
return nil , fmt . Errorf ( "Query '%s', arguments do not match: %s" , query , err )
2015-07-17 12:14:30 +02:00
}
2016-02-26 18:07:19 +02:00
expected . triggered = true
2015-08-26 13:28:01 +02:00
if expected . err != nil {
2018-02-21 02:30:20 +02:00
return expected , expected . err // mocked to return error
2015-07-17 12:14:30 +02:00
}
2015-08-26 13:28:01 +02:00
if expected . rows == nil {
2017-04-26 08:56:02 +02:00
return nil , fmt . Errorf ( "Query '%s' with args %+v, must return a database/sql/driver.Rows, but it was not set for expectation %T as %+v" , query , args , expected , expected )
2015-07-17 12:14:30 +02:00
}
2017-02-07 12:20:08 +02:00
return expected , nil
}
2018-12-11 14:56:33 +02:00
func ( c * sqlmock ) ExpectQuery ( expectedSQL string ) * ExpectedQuery {
2015-07-17 12:14:30 +02:00
e := & ExpectedQuery { }
2018-12-11 14:56:33 +02:00
e . expectSQL = expectedSQL
2018-08-06 22:29:24 +02:00
e . converter = c . converter
2015-07-17 12:14:30 +02:00
c . expected = append ( c . expected , e )
return e
}
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) ExpectCommit ( ) * ExpectedCommit {
2015-07-17 12:14:30 +02:00
e := & ExpectedCommit { }
c . expected = append ( c . expected , e )
return e
}
2014-02-05 17:21:07 +03:00
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) ExpectRollback ( ) * ExpectedRollback {
2015-07-17 12:14:30 +02:00
e := & ExpectedRollback { }
c . expected = append ( c . expected , e )
return e
2014-02-05 17:21:07 +03:00
}
2015-07-17 12:14:30 +02:00
// Commit meets http://golang.org/pkg/database/sql/driver/#Tx
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) Commit ( ) error {
2015-08-26 13:28:01 +02:00
var expected * ExpectedCommit
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
var ok bool
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
if expected , ok = next . ( * ExpectedCommit ) ; ok {
break
}
next . Unlock ( )
2015-08-28 10:06:14 +02:00
if c . ordered {
2017-04-26 08:56:02 +02:00
return fmt . Errorf ( "call to Commit transaction, was not expected, next expectation is: %s" , next )
2015-08-26 13:28:01 +02:00
}
}
if expected == nil {
2017-04-26 08:56:02 +02:00
msg := "call to Commit transaction was not expected"
2015-08-26 15:59:28 +02:00
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return fmt . Errorf ( msg )
2015-07-17 12:14:30 +02:00
}
2015-08-26 13:28:01 +02:00
expected . triggered = true
expected . Unlock ( )
return expected . err
2014-02-05 17:21:07 +03:00
}
2015-07-17 12:14:30 +02:00
// Rollback meets http://golang.org/pkg/database/sql/driver/#Tx
2015-08-28 10:06:14 +02:00
func ( c * sqlmock ) Rollback ( ) error {
2015-08-26 13:28:01 +02:00
var expected * ExpectedRollback
2015-08-26 15:59:28 +02:00
var fulfilled int
2015-08-26 13:28:01 +02:00
var ok bool
for _ , next := range c . expected {
next . Lock ( )
if next . fulfilled ( ) {
next . Unlock ( )
2015-08-26 15:59:28 +02:00
fulfilled ++
2015-08-26 13:28:01 +02:00
continue
}
2015-07-17 12:14:30 +02:00
2015-08-26 13:28:01 +02:00
if expected , ok = next . ( * ExpectedRollback ) ; ok {
break
}
2014-02-05 17:21:07 +03:00
2015-08-26 13:28:01 +02:00
next . Unlock ( )
2015-08-28 10:06:14 +02:00
if c . ordered {
2017-04-26 08:56:02 +02:00
return fmt . Errorf ( "call to Rollback transaction, was not expected, next expectation is: %s" , next )
2015-07-17 12:14:30 +02:00
}
2014-02-05 17:21:07 +03:00
}
2015-08-26 13:28:01 +02:00
if expected == nil {
2017-04-26 08:56:02 +02:00
msg := "call to Rollback transaction was not expected"
2015-08-26 15:59:28 +02:00
if fulfilled == len ( c . expected ) {
msg = "all expectations were already fulfilled, " + msg
}
return fmt . Errorf ( msg )
2015-08-26 13:28:01 +02:00
}
expected . triggered = true
expected . Unlock ( )
return expected . err
2014-02-05 17:21:07 +03:00
}
2018-08-06 22:29:24 +02:00
// NewRows allows Rows to be created from a
// sql driver.Value slice or from the CSV string and
// to be used as sql driver.Rows.
func ( c * sqlmock ) NewRows ( columns [ ] string ) * Rows {
r := NewRows ( columns )
r . converter = c . converter
return r
}