/*
Package sqlmock provides sql driver mock connecection, which allows to test database,
create expectations and ensure the correct execution flow of any database operations.
It hooks into Go standard library's database/sql package.

The package provides convenient methods to mock database queries, transactions and
expect the right execution flow, compare query arguments or even return error instead
to simulate failures. See the example bellow, which illustrates how convenient it is
to work with:


    package main

    import (
        "database/sql"
        "github.com/DATA-DOG/go-sqlmock"
        "testing"
        "fmt"
    )

    // will test that order with a different status, cannot be cancelled
    func TestShouldNotCancelOrderWithNonPendingStatus(t *testing.T) {
        // open database stub
        db, err := sql.Open("mock", "")
        if err != nil {
            t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
        }

        // columns to be used for result
        columns := []string{"id", "status"}
        // expect transaction begin
        sqlmock.ExpectBegin()
        // expect query to fetch order, match it with regexp
        sqlmock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
            WithArgs(1).
            WillReturnRows(sqlmock.NewRows(columns).FromCSVString("1,1"))
        // expect transaction rollback, since order status is "cancelled"
        sqlmock.ExpectRollback()

        // run the cancel order function
        someOrderId := 1
        // call a function which executes expected database operations
        err = cancelOrder(someOrderId, db)
        if err != nil {
            t.Errorf("Expected no error, but got %s instead", err)
        }
        // db.Close() ensures that all expectations have been met
        if err = db.Close(); err != nil {
            t.Errorf("Error '%s' was not expected while closing the database", err)
        }
    }

*/
package sqlmock

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
	"regexp"
)

var mock *mockDriver

// Mock interface defines a mock which is returned
// by any expectation and can be detailed further
// with the methods this interface provides
type Mock interface {
	WithArgs(...driver.Value) Mock
	WillReturnError(error) Mock
	WillReturnRows(driver.Rows) Mock
	WillReturnResult(driver.Result) Mock
}

type mockDriver struct {
	conn *conn
}

func (d *mockDriver) Open(dsn string) (driver.Conn, error) {
	return mock.conn, nil
}

func init() {
	mock = &mockDriver{&conn{}}
	sql.Register("mock", mock)
}

// New creates sqlmock database connection
// and pings it so that all expectations could be
// asserted on Close.
func New() (db *sql.DB, err error) {
	db, err = sql.Open("mock", "")
	if err != nil {
		return
	}
	// ensure open connection, otherwise Close does not assert expectations
	db.Ping()
	return
}

// ExpectBegin expects transaction to be started
func ExpectBegin() Mock {
	e := &expectedBegin{}
	mock.conn.expectations = append(mock.conn.expectations, e)
	mock.conn.active = e
	return mock.conn
}

// ExpectCommit expects transaction to be commited
func ExpectCommit() Mock {
	e := &expectedCommit{}
	mock.conn.expectations = append(mock.conn.expectations, e)
	mock.conn.active = e
	return mock.conn
}

// ExpectRollback expects transaction to be rolled back
func ExpectRollback() Mock {
	e := &expectedRollback{}
	mock.conn.expectations = append(mock.conn.expectations, e)
	mock.conn.active = e
	return mock.conn
}

// ExpectPrepare expects Query to be prepared
func ExpectPrepare() Mock {
	e := &expectedPrepare{}
	mock.conn.expectations = append(mock.conn.expectations, e)
	mock.conn.active = e
	return mock.conn
}

// WillReturnError the expectation will return an error
func (c *conn) WillReturnError(err error) Mock {
	c.active.setError(err)
	return c
}

// ExpectExec expects database Exec to be triggered, which will match
// the given query string as a regular expression
func ExpectExec(sqlRegexStr string) Mock {
	e := &expectedExec{}
	e.sqlRegex = regexp.MustCompile(sqlRegexStr)
	mock.conn.expectations = append(mock.conn.expectations, e)
	mock.conn.active = e
	return mock.conn
}

// ExpectQuery database Query to be triggered, which will match
// the given query string as a regular expression
func ExpectQuery(sqlRegexStr string) Mock {
	e := &expectedQuery{}
	e.sqlRegex = regexp.MustCompile(sqlRegexStr)

	mock.conn.expectations = append(mock.conn.expectations, e)
	mock.conn.active = e
	return mock.conn
}

// WithArgs expectation should be called with given arguments.
// Works with Exec and Query expectations
func (c *conn) WithArgs(args ...driver.Value) Mock {
	eq, ok := c.active.(*expectedQuery)
	if !ok {
		ee, ok := c.active.(*expectedExec)
		if !ok {
			panic(fmt.Sprintf("arguments may be expected only with query based expectations, current is %T", c.active))
		}
		ee.args = args
	} else {
		eq.args = args
	}
	return c
}

// WillReturnResult expectation will return a Result.
// Works only with Exec expectations
func (c *conn) WillReturnResult(result driver.Result) Mock {
	eq, ok := c.active.(*expectedExec)
	if !ok {
		panic(fmt.Sprintf("driver.result may be returned only by exec expectations, current is %T", c.active))
	}
	eq.result = result
	return c
}

// WillReturnRows expectation will return Rows.
// Works only with Query expectations
func (c *conn) WillReturnRows(rows driver.Rows) Mock {
	eq, ok := c.active.(*expectedQuery)
	if !ok {
		panic(fmt.Sprintf("driver.rows may be returned only by query expectations, current is %T", c.active))
	}
	eq.rows = rows
	return c
}
