You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by da...@apache.org on 2017/08/14 20:39:10 UTC
[3/9] incubator-trafficcontrol git commit: added lib/pq to the vendor
dir and renamed the go-sqlmock to its version
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations.go
new file mode 100644
index 0000000..415759e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations.go
@@ -0,0 +1,344 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+)
+
+// an expectation interface
+type expectation interface {
+ fulfilled() bool
+ Lock()
+ Unlock()
+ String() string
+}
+
+// common expectation struct
+// satisfies the expectation interface
+type commonExpectation struct {
+ sync.Mutex
+ triggered bool
+ err error
+}
+
+func (e *commonExpectation) fulfilled() bool {
+ return e.triggered
+}
+
+// ExpectedClose is used to manage *sql.DB.Close expectation
+// returned by *Sqlmock.ExpectClose.
+type ExpectedClose struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.DB.Close action
+func (e *ExpectedClose) WillReturnError(err error) *ExpectedClose {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedClose) String() string {
+ msg := "ExpectedClose => expecting database Close"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedBegin is used to manage *sql.DB.Begin expectation
+// returned by *Sqlmock.ExpectBegin.
+type ExpectedBegin struct {
+ commonExpectation
+ delay time.Duration
+}
+
+// WillReturnError allows to set an error for *sql.DB.Begin action
+func (e *ExpectedBegin) WillReturnError(err error) *ExpectedBegin {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedBegin) String() string {
+ msg := "ExpectedBegin => expecting database transaction Begin"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedBegin) WillDelayFor(duration time.Duration) *ExpectedBegin {
+ e.delay = duration
+ return e
+}
+
+// ExpectedCommit is used to manage *sql.Tx.Commit expectation
+// returned by *Sqlmock.ExpectCommit.
+type ExpectedCommit struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.Tx.Close action
+func (e *ExpectedCommit) WillReturnError(err error) *ExpectedCommit {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedCommit) String() string {
+ msg := "ExpectedCommit => expecting transaction Commit"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedRollback is used to manage *sql.Tx.Rollback expectation
+// returned by *Sqlmock.ExpectRollback.
+type ExpectedRollback struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.Tx.Rollback action
+func (e *ExpectedRollback) WillReturnError(err error) *ExpectedRollback {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedRollback) String() string {
+ msg := "ExpectedRollback => expecting transaction Rollback"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedQuery is used to manage *sql.DB.Query, *dql.DB.QueryRow, *sql.Tx.Query,
+// *sql.Tx.QueryRow, *sql.Stmt.Query or *sql.Stmt.QueryRow expectations.
+// Returned by *Sqlmock.ExpectQuery.
+type ExpectedQuery struct {
+ queryBasedExpectation
+ rows driver.Rows
+ delay time.Duration
+}
+
+// WithArgs will match given expected args to actual database query arguments.
+// if at least one argument does not match, it will return an error. For specific
+// arguments an sqlmock.Argument interface can be used to match an argument.
+func (e *ExpectedQuery) WithArgs(args ...driver.Value) *ExpectedQuery {
+ e.args = args
+ return e
+}
+
+// WillReturnError allows to set an error for expected database query
+func (e *ExpectedQuery) WillReturnError(err error) *ExpectedQuery {
+ e.err = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedQuery) WillDelayFor(duration time.Duration) *ExpectedQuery {
+ e.delay = duration
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedQuery) String() string {
+ msg := "ExpectedQuery => expecting Query or QueryRow which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if len(e.args) == 0 {
+ msg += "\n - is without arguments"
+ } else {
+ msg += "\n - is with arguments:\n"
+ for i, arg := range e.args {
+ msg += fmt.Sprintf(" %d - %+v\n", i, arg)
+ }
+ msg = strings.TrimSpace(msg)
+ }
+
+ if e.rows != nil {
+ msg += fmt.Sprintf("\n - %s", e.rows)
+ }
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ return msg
+}
+
+// ExpectedExec is used to manage *sql.DB.Exec, *sql.Tx.Exec or *sql.Stmt.Exec expectations.
+// Returned by *Sqlmock.ExpectExec.
+type ExpectedExec struct {
+ queryBasedExpectation
+ result driver.Result
+ delay time.Duration
+}
+
+// WithArgs will match given expected args to actual database exec operation arguments.
+// if at least one argument does not match, it will return an error. For specific
+// arguments an sqlmock.Argument interface can be used to match an argument.
+func (e *ExpectedExec) WithArgs(args ...driver.Value) *ExpectedExec {
+ e.args = args
+ return e
+}
+
+// WillReturnError allows to set an error for expected database exec action
+func (e *ExpectedExec) WillReturnError(err error) *ExpectedExec {
+ e.err = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedExec) WillDelayFor(duration time.Duration) *ExpectedExec {
+ e.delay = duration
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedExec) String() string {
+ msg := "ExpectedExec => expecting Exec which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if len(e.args) == 0 {
+ msg += "\n - is without arguments"
+ } else {
+ msg += "\n - is with arguments:\n"
+ var margs []string
+ for i, arg := range e.args {
+ margs = append(margs, fmt.Sprintf(" %d - %+v", i, arg))
+ }
+ msg += strings.Join(margs, "\n")
+ }
+
+ if e.result != nil {
+ res, _ := e.result.(*result)
+ msg += "\n - should return Result having:"
+ msg += fmt.Sprintf("\n LastInsertId: %d", res.insertID)
+ msg += fmt.Sprintf("\n RowsAffected: %d", res.rowsAffected)
+ if res.err != nil {
+ msg += fmt.Sprintf("\n Error: %s", res.err)
+ }
+ }
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ return msg
+}
+
+// WillReturnResult arranges for an expected Exec() to return a particular
+// result, there is sqlmock.NewResult(lastInsertID int64, affectedRows int64) method
+// to build a corresponding result. Or if actions needs to be tested against errors
+// sqlmock.NewErrorResult(err error) to return a given error.
+func (e *ExpectedExec) WillReturnResult(result driver.Result) *ExpectedExec {
+ e.result = result
+ return e
+}
+
+// ExpectedPrepare is used to manage *sql.DB.Prepare or *sql.Tx.Prepare expectations.
+// Returned by *Sqlmock.ExpectPrepare.
+type ExpectedPrepare struct {
+ commonExpectation
+ mock *sqlmock
+ sqlRegex *regexp.Regexp
+ statement driver.Stmt
+ closeErr error
+ delay time.Duration
+}
+
+// WillReturnError allows to set an error for the expected *sql.DB.Prepare or *sql.Tx.Prepare action.
+func (e *ExpectedPrepare) WillReturnError(err error) *ExpectedPrepare {
+ e.err = err
+ return e
+}
+
+// WillReturnCloseError allows to set an error for this prapared statement Close action
+func (e *ExpectedPrepare) WillReturnCloseError(err error) *ExpectedPrepare {
+ e.closeErr = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedPrepare) WillDelayFor(duration time.Duration) *ExpectedPrepare {
+ e.delay = duration
+ return e
+}
+
+// ExpectQuery allows to expect Query() or QueryRow() on this prepared statement.
+// this method is convenient in order to prevent duplicating sql query string matching.
+func (e *ExpectedPrepare) ExpectQuery() *ExpectedQuery {
+ eq := &ExpectedQuery{}
+ eq.sqlRegex = e.sqlRegex
+ e.mock.expected = append(e.mock.expected, eq)
+ return eq
+}
+
+// ExpectExec allows to expect Exec() on this prepared statement.
+// this method is convenient in order to prevent duplicating sql query string matching.
+func (e *ExpectedPrepare) ExpectExec() *ExpectedExec {
+ eq := &ExpectedExec{}
+ eq.sqlRegex = e.sqlRegex
+ e.mock.expected = append(e.mock.expected, eq)
+ return eq
+}
+
+// String returns string representation
+func (e *ExpectedPrepare) String() string {
+ msg := "ExpectedPrepare => expecting Prepare statement which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ if e.closeErr != nil {
+ msg += fmt.Sprintf("\n - should return error on Close: %s", e.closeErr)
+ }
+
+ return msg
+}
+
+// query based expectation
+// adds a query matching logic
+type queryBasedExpectation struct {
+ commonExpectation
+ sqlRegex *regexp.Regexp
+ args []driver.Value
+}
+
+func (e *queryBasedExpectation) attemptMatch(sql string, args []namedValue) (err error) {
+ if !e.queryMatches(sql) {
+ return fmt.Errorf(`could not match sql: "%s" with expected regexp "%s"`, sql, e.sqlRegex.String())
+ }
+
+ // catch panic
+ defer func() {
+ if e := recover(); e != nil {
+ _, ok := e.(error)
+ if !ok {
+ err = fmt.Errorf(e.(string))
+ }
+ }
+ }()
+
+ err = e.argsMatches(args)
+ return
+}
+
+func (e *queryBasedExpectation) queryMatches(sql string) bool {
+ return e.sqlRegex.MatchString(sql)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_before_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_before_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_before_go18.go
new file mode 100644
index 0000000..146f240
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_before_go18.go
@@ -0,0 +1,52 @@
+// +build !go1.8
+
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "reflect"
+)
+
+// WillReturnRows specifies the set of resulting rows that will be returned
+// by the triggered query
+func (e *ExpectedQuery) WillReturnRows(rows *Rows) *ExpectedQuery {
+ e.rows = &rowSets{sets: []*Rows{rows}}
+ return e
+}
+
+func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
+ if nil == e.args {
+ return nil
+ }
+ if len(args) != len(e.args) {
+ return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
+ }
+ for k, v := range args {
+ // custom argument matcher
+ matcher, ok := e.args[k].(Argument)
+ if ok {
+ // @TODO: does it make sense to pass value instead of named value?
+ if !matcher.Match(v.Value) {
+ return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
+ }
+ continue
+ }
+
+ dval := e.args[k]
+ // convert to driver converter
+ darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
+ if err != nil {
+ return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
+ }
+
+ if !driver.IsValue(darg) {
+ return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
+ }
+
+ if !reflect.DeepEqual(darg, v.Value) {
+ return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
+ }
+ }
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18.go
new file mode 100644
index 0000000..2b4b44e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18.go
@@ -0,0 +1,66 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "reflect"
+)
+
+// WillReturnRows specifies the set of resulting rows that will be returned
+// by the triggered query
+func (e *ExpectedQuery) WillReturnRows(rows ...*Rows) *ExpectedQuery {
+ sets := make([]*Rows, len(rows))
+ for i, r := range rows {
+ sets[i] = r
+ }
+ e.rows = &rowSets{sets: sets}
+ return e
+}
+
+func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
+ if nil == e.args {
+ return nil
+ }
+ if len(args) != len(e.args) {
+ return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
+ }
+ // @TODO should we assert either all args are named or ordinal?
+ for k, v := range args {
+ // custom argument matcher
+ matcher, ok := e.args[k].(Argument)
+ if ok {
+ if !matcher.Match(v.Value) {
+ return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
+ }
+ continue
+ }
+
+ dval := e.args[k]
+ if named, isNamed := dval.(sql.NamedArg); isNamed {
+ dval = named.Value
+ if v.Name != named.Name {
+ return fmt.Errorf("named argument %d: name: \"%s\" does not match expected: \"%s\"", k, v.Name, named.Name)
+ }
+ } else if k+1 != v.Ordinal {
+ return fmt.Errorf("argument %d: ordinal position: %d does not match expected: %d", k, k+1, v.Ordinal)
+ }
+
+ // convert to driver converter
+ darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
+ if err != nil {
+ return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
+ }
+
+ if !driver.IsValue(darg) {
+ return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
+ }
+
+ if !reflect.DeepEqual(darg, v.Value) {
+ return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
+ }
+ }
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18_test.go
new file mode 100644
index 0000000..5f30d2f
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18_test.go
@@ -0,0 +1,64 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "testing"
+)
+
+func TestQueryExpectationNamedArgComparison(t *testing.T) {
+ e := &queryBasedExpectation{}
+ against := []namedValue{{Value: int64(5), Name: "id"}}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
+ }
+
+ e.args = []driver.Value{
+ sql.Named("id", 5),
+ sql.Named("s", "str"),
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the size is not the same")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Name: "id"},
+ {Value: "str", Name: "s"},
+ }
+
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should have matched, but it did not: %v", err)
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Name: "id"},
+ {Value: "str", Name: "username"},
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments matched, but it should have not due to Name")
+ }
+
+ e.args = []driver.Value{int64(5), "str"}
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 0},
+ {Value: "str", Ordinal: 1},
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments matched, but it should have not due to wrong Ordinal position")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should have matched, but it did not: %v", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_test.go
new file mode 100644
index 0000000..2e3c097
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_test.go
@@ -0,0 +1,154 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "testing"
+ "time"
+)
+
+func TestQueryExpectationArgComparison(t *testing.T) {
+ e := &queryBasedExpectation{}
+ against := []namedValue{{Value: int64(5), Ordinal: 1}}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
+ }
+
+ e.args = []driver.Value{5, "str"}
+
+ against = []namedValue{{Value: int64(5), Ordinal: 1}}
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the size is not the same")
+ }
+
+ against = []namedValue{
+ {Value: int64(3), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the first argument (int value) is different")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "st", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the second argument (string value) is different")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, but it did not: %s", err)
+ }
+
+ const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+ tm, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
+ e.args = []driver.Value{5, tm}
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: tm, Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, but it did not")
+ }
+
+ e.args = []driver.Value{5, AnyArg()}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, but it did not: %s", err)
+ }
+}
+
+func TestQueryExpectationArgComparisonBool(t *testing.T) {
+ var e *queryBasedExpectation
+
+ e = &queryBasedExpectation{args: []driver.Value{true}}
+ against := []namedValue{
+ {Value: true, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, since arguments are the same")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{false}}
+ against = []namedValue{
+ {Value: false, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, since argument are the same")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{true}}
+ against = []namedValue{
+ {Value: false, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since argument is different")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{false}}
+ against = []namedValue{
+ {Value: true, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since argument is different")
+ }
+}
+
+func TestQueryExpectationSqlMatch(t *testing.T) {
+ e := &ExpectedExec{}
+
+ e.sqlRegex = regexp.MustCompile("SELECT x FROM")
+ if !e.queryMatches("SELECT x FROM someting") {
+ t.Errorf("Sql must have matched the query")
+ }
+
+ e.sqlRegex = regexp.MustCompile("SELECT COUNT\\(x\\) FROM")
+ if !e.queryMatches("SELECT COUNT(x) FROM someting") {
+ t.Errorf("Sql must have matched the query")
+ }
+}
+
+func ExampleExpectedExec() {
+ db, mock, _ := New()
+ result := NewErrorResult(fmt.Errorf("some error"))
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ res, _ := db.Exec("INSERT something")
+ _, err := res.LastInsertId()
+ fmt.Println(err)
+ // Output: some error
+}
+
+func TestBuildQuery(t *testing.T) {
+ db, mock, _ := New()
+ query := `
+ SELECT
+ name,
+ email,
+ address,
+ anotherfield
+ FROM user
+ where
+ name = 'John'
+ and
+ address = 'Jakarta'
+
+ `
+
+ mock.ExpectQuery(query)
+ mock.ExpectExec(query)
+ mock.ExpectPrepare(query)
+
+ db.QueryRow(query)
+ db.Exec(query)
+ db.Prepare(query)
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Error(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result.go
new file mode 100644
index 0000000..a63e72b
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result.go
@@ -0,0 +1,39 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+)
+
+// Result satisfies sql driver Result, which
+// holds last insert id and rows affected
+// by Exec queries
+type result struct {
+ insertID int64
+ rowsAffected int64
+ err error
+}
+
+// NewResult creates a new sql driver Result
+// for Exec based query mocks.
+func NewResult(lastInsertID int64, rowsAffected int64) driver.Result {
+ return &result{
+ insertID: lastInsertID,
+ rowsAffected: rowsAffected,
+ }
+}
+
+// NewErrorResult creates a new sql driver Result
+// which returns an error given for both interface methods
+func NewErrorResult(err error) driver.Result {
+ return &result{
+ err: err,
+ }
+}
+
+func (r *result) LastInsertId() (int64, error) {
+ return r.insertID, r.err
+}
+
+func (r *result) RowsAffected() (int64, error) {
+ return r.rowsAffected, r.err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result_test.go
new file mode 100644
index 0000000..08d47c9
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result_test.go
@@ -0,0 +1,62 @@
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+// used for examples
+var mock = &sqlmock{}
+
+func ExampleNewErrorResult() {
+ db, mock, _ := New()
+ result := NewErrorResult(fmt.Errorf("some error"))
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ res, _ := db.Exec("INSERT something")
+ _, err := res.LastInsertId()
+ fmt.Println(err)
+ // Output: some error
+}
+
+func ExampleNewResult() {
+ var lastInsertID, affected int64
+ result := NewResult(lastInsertID, affected)
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ fmt.Println(mock.ExpectationsWereMet())
+ // Output: there is a remaining expectation which was not matched: ExpectedExec => expecting Exec which:
+ // - matches sql: '^INSERT (.+)'
+ // - is without arguments
+ // - should return Result having:
+ // LastInsertId: 0
+ // RowsAffected: 0
+}
+
+func TestShouldReturnValidSqlDriverResult(t *testing.T) {
+ result := NewResult(1, 2)
+ id, err := result.LastInsertId()
+ if 1 != id {
+ t.Errorf("Expected last insert id to be 1, but got: %d", id)
+ }
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ affected, err := result.RowsAffected()
+ if 2 != affected {
+ t.Errorf("Expected affected rows to be 2, but got: %d", affected)
+ }
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+}
+
+func TestShouldReturnErroeSqlDriverResult(t *testing.T) {
+ result := NewErrorResult(fmt.Errorf("some error"))
+ _, err := result.LastInsertId()
+ if err == nil {
+ t.Error("expected error, but got none")
+ }
+ _, err = result.RowsAffected()
+ if err == nil {
+ t.Error("expected error, but got none")
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go
new file mode 100644
index 0000000..39f9f83
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go
@@ -0,0 +1,144 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "encoding/csv"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// CSVColumnParser is a function which converts trimmed csv
+// column string to a []byte representation. currently
+// transforms NULL to nil
+var CSVColumnParser = func(s string) []byte {
+ switch {
+ case strings.ToLower(s) == "null":
+ return nil
+ }
+ return []byte(s)
+}
+
+type rowSets struct {
+ sets []*Rows
+ pos int
+}
+
+func (rs *rowSets) Columns() []string {
+ return rs.sets[rs.pos].cols
+}
+
+func (rs *rowSets) Close() error {
+ return rs.sets[rs.pos].closeErr
+}
+
+// advances to next row
+func (rs *rowSets) Next(dest []driver.Value) error {
+ r := rs.sets[rs.pos]
+ r.pos++
+ if r.pos > len(r.rows) {
+ return io.EOF // per interface spec
+ }
+
+ for i, col := range r.rows[r.pos-1] {
+ dest[i] = col
+ }
+
+ return r.nextErr[r.pos-1]
+}
+
+// transforms to debuggable printable string
+func (rs *rowSets) String() string {
+ msg := "should return rows:\n"
+ if len(rs.sets) == 1 {
+ for n, row := range rs.sets[0].rows {
+ msg += fmt.Sprintf(" row %d - %+v\n", n, row)
+ }
+ return strings.TrimSpace(msg)
+ }
+ for i, set := range rs.sets {
+ msg += fmt.Sprintf(" result set: %d\n", i)
+ for n, row := range set.rows {
+ msg += fmt.Sprintf(" row %d - %+v\n", n, row)
+ }
+ }
+ return strings.TrimSpace(msg)
+}
+
+// Rows is a mocked collection of rows to
+// return for Query result
+type Rows struct {
+ cols []string
+ rows [][]driver.Value
+ pos int
+ nextErr map[int]error
+ closeErr error
+}
+
+// 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 NewRows(columns []string) *Rows {
+ return &Rows{cols: columns, nextErr: make(map[int]error)}
+}
+
+// CloseError allows to set an error
+// which will be returned by rows.Close
+// function.
+//
+// The close error will be triggered only in cases
+// when rows.Next() EOF was not yet reached, that is
+// a default sql library behavior
+func (r *Rows) CloseError(err error) *Rows {
+ r.closeErr = err
+ return r
+}
+
+// RowError allows to set an error
+// which will be returned when a given
+// row number is read
+func (r *Rows) RowError(row int, err error) *Rows {
+ r.nextErr[row] = err
+ return r
+}
+
+// AddRow composed from database driver.Value slice
+// return the same instance to perform subsequent actions.
+// Note that the number of values must match the number
+// of columns
+func (r *Rows) AddRow(values ...driver.Value) *Rows {
+ if len(values) != len(r.cols) {
+ panic("Expected number of values to match number of columns")
+ }
+
+ row := make([]driver.Value, len(r.cols))
+ for i, v := range values {
+ row[i] = v
+ }
+
+ r.rows = append(r.rows, row)
+ return r
+}
+
+// FromCSVString build rows from csv string.
+// return the same instance to perform subsequent actions.
+// Note that the number of values must match the number
+// of columns
+func (r *Rows) FromCSVString(s string) *Rows {
+ res := strings.NewReader(strings.TrimSpace(s))
+ csvReader := csv.NewReader(res)
+
+ for {
+ res, err := csvReader.Read()
+ if err != nil || res == nil {
+ break
+ }
+
+ row := make([]driver.Value, len(r.cols))
+ for i, v := range res {
+ row[i] = CSVColumnParser(strings.TrimSpace(v))
+ }
+ r.rows = append(r.rows, row)
+ }
+ return r
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18.go
new file mode 100644
index 0000000..4ecf84e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18.go
@@ -0,0 +1,20 @@
+// +build go1.8
+
+package sqlmock
+
+import "io"
+
+// Implement the "RowsNextResultSet" interface
+func (rs *rowSets) HasNextResultSet() bool {
+ return rs.pos+1 < len(rs.sets)
+}
+
+// Implement the "RowsNextResultSet" interface
+func (rs *rowSets) NextResultSet() error {
+ if !rs.HasNextResultSet() {
+ return io.EOF
+ }
+
+ rs.pos++
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18_test.go
new file mode 100644
index 0000000..297e7c0
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18_test.go
@@ -0,0 +1,92 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestQueryMultiRows(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs1 := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+ rs2 := NewRows([]string{"name"}).AddRow("gopher").AddRow("john").AddRow("jane").RowError(2, fmt.Errorf("error"))
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = \\?;SELECT name FROM users").
+ WithArgs(5).
+ WillReturnRows(rs1, rs2)
+
+ rows, err := db.Query("SELECT id, title FROM articles WHERE id = ?;SELECT name FROM users", 5)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+ defer rows.Close()
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in first result set")
+ }
+
+ var id int
+ var name string
+
+ err = rows.Scan(&id, &name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if id != 5 || name != "hello world" {
+ t.Errorf("unexpected row values id: %v name: %v", id, name)
+ }
+
+ if rows.Next() {
+ t.Error("was not expecting next row in first result set")
+ }
+
+ if !rows.NextResultSet() {
+ t.Error("had to have next result set")
+ }
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in second result set")
+ }
+
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if name != "gopher" {
+ t.Errorf("unexpected row name: %v", name)
+ }
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in second result set")
+ }
+
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if name != "john" {
+ t.Errorf("unexpected row name: %v", name)
+ }
+
+ if rows.Next() {
+ t.Error("expected next row to produce error")
+ }
+
+ if rows.Err() == nil {
+ t.Error("expected an error, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_test.go
new file mode 100644
index 0000000..56e834e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_test.go
@@ -0,0 +1,265 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "fmt"
+ "testing"
+)
+
+func ExampleRows() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(1, "one").
+ AddRow(2, "two")
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+ defer rs.Close()
+
+ for rs.Next() {
+ var id int
+ var title string
+ rs.Scan(&id, &title)
+ fmt.Println("scanned id:", id, "and title:", title)
+ }
+
+ if rs.Err() != nil {
+ fmt.Println("got rows error:", rs.Err())
+ }
+ // Output: scanned id: 1 and title: one
+ // scanned id: 2 and title: two
+}
+
+func ExampleRows_rowError() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(0, "one").
+ AddRow(1, "two").
+ RowError(1, fmt.Errorf("row error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+ defer rs.Close()
+
+ for rs.Next() {
+ var id int
+ var title string
+ rs.Scan(&id, &title)
+ fmt.Println("scanned id:", id, "and title:", title)
+ }
+
+ if rs.Err() != nil {
+ fmt.Println("got rows error:", rs.Err())
+ }
+ // Output: scanned id: 0 and title: one
+ // got rows error: row error
+}
+
+func ExampleRows_closeError() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).CloseError(fmt.Errorf("close error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+
+ // Note: that close will return error only before rows EOF
+ // that is a default sql package behavior. If you run rs.Next()
+ // it will handle the error internally and return nil bellow
+ if err := rs.Close(); err != nil {
+ fmt.Println("got error:", err)
+ }
+
+ // Output: got error: close error
+}
+
+func TestAllowsToSetRowsErrors(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(0, "one").
+ AddRow(1, "two").
+ RowError(1, fmt.Errorf("error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rs.Close()
+
+ if !rs.Next() {
+ t.Fatal("expected the first row to be available")
+ }
+ if rs.Err() != nil {
+ t.Fatalf("unexpected error: %s", rs.Err())
+ }
+
+ if rs.Next() {
+ t.Fatal("was not expecting the second row, since there should be an error")
+ }
+ if rs.Err() == nil {
+ t.Fatal("expected an error, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestRowsCloseError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id"}).CloseError(fmt.Errorf("close error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if err := rs.Close(); err == nil {
+ t.Fatal("expected a close error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestQuerySingleRow(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id"}).
+ AddRow(1).
+ AddRow(2)
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ var id int
+ if err := db.QueryRow("SELECT").Scan(&id); err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"id"}))
+ if err := db.QueryRow("SELECT").Scan(&id); err != sql.ErrNoRows {
+ t.Fatal("expected sql no rows error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestRowsScanError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ r := NewRows([]string{"col1", "col2"}).AddRow("one", "two").AddRow("one", nil)
+ mock.ExpectQuery("SELECT").WillReturnRows(r)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rs.Close()
+
+ var one, two string
+ if !rs.Next() || rs.Err() != nil || rs.Scan(&one, &two) != nil {
+ t.Fatal("unexpected error on first row scan")
+ }
+
+ if !rs.Next() || rs.Err() != nil {
+ t.Fatal("unexpected error on second row read")
+ }
+
+ err = rs.Scan(&one, &two)
+ if err == nil {
+ t.Fatal("expected an error for scan, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCSVRowParser(t *testing.T) {
+ t.Parallel()
+ rs := NewRows([]string{"col1", "col2"}).FromCSVString("a,NULL")
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rs)
+
+ rw, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rw.Close()
+ var col1 string
+ var col2 []byte
+
+ rw.Next()
+ if err = rw.Scan(&col1, &col2); err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if col1 != "a" {
+ t.Fatalf("expected col1 to be 'a', but got [%T]:%+v", col1, col1)
+ }
+ if col2 != nil {
+ t.Fatalf("expected col2 to be nil, but got [%T]:%+v", col2, col2)
+ }
+}
+
+func TestWrongNumberOfValues(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ defer func() {
+ recover()
+ }()
+ mock.ExpectQuery("SELECT ID FROM TABLE").WithArgs(101).WillReturnRows(NewRows([]string{"ID"}).AddRow(101, "Hello"))
+ db.Query("SELECT ID FROM TABLE", 101)
+ // shouldn't reach here
+ t.Error("expected panic from query")
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go
new file mode 100644
index 0000000..b906a3f
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go
@@ -0,0 +1,525 @@
+/*
+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.
+
+It does not require any modifications to your source code in order to test
+and mock database operations. Supports concurrency and multiple database mocking.
+
+The driver allows to mock any sql driver method behavior.
+*/
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "time"
+)
+
+// 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
+
+ // ExpectPrepare expects Prepare() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedPrepare allows to mock database response.
+ // Note that you may expect Query() or Exec() on the *ExpectedPrepare
+ // statement to prevent repeating sqlRegexStr
+ ExpectPrepare(sqlRegexStr string) *ExpectedPrepare
+
+ // ExpectQuery expects Query() or QueryRow() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedQuery allows to mock database response.
+ ExpectQuery(sqlRegexStr string) *ExpectedQuery
+
+ // ExpectExec expects Exec() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedExec allows to mock database response
+ ExpectExec(sqlRegexStr string) *ExpectedExec
+
+ // 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
+
+ // 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.
+ //
+ // 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
+ MatchExpectationsInOrder(bool)
+}
+
+type sqlmock struct {
+ ordered bool
+ dsn string
+ opened int
+ drv *mockDriver
+
+ expected []expectation
+}
+
+func (c *sqlmock) open() (*sql.DB, Sqlmock, error) {
+ db, err := sql.Open("sqlmock", c.dsn)
+ if err != nil {
+ return db, c, err
+ }
+ return db, c, db.Ping()
+}
+
+func (c *sqlmock) ExpectClose() *ExpectedClose {
+ e := &ExpectedClose{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) MatchExpectationsInOrder(b bool) {
+ c.ordered = b
+}
+
+// Close a mock database driver connection. It may or may not
+// be called depending on the sircumstances, but if it is called
+// there must be an *ExpectedClose expectation satisfied.
+// meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Close() error {
+ c.drv.Lock()
+ defer c.drv.Unlock()
+
+ c.opened--
+ if c.opened == 0 {
+ delete(c.drv.conns, c.dsn)
+ }
+
+ var expected *ExpectedClose
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedClose); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to database Close, was not expected, next expectation is: %s", next)
+ }
+ }
+
+ if expected == nil {
+ msg := "call to database Close was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
+
+func (c *sqlmock) ExpectationsWereMet() error {
+ for _, e := range c.expected {
+ if !e.fulfilled() {
+ return fmt.Errorf("there is a remaining expectation which was not matched: %s", e)
+ }
+ }
+ return nil
+}
+
+// Begin meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Begin() (driver.Tx, error) {
+ ex, err := c.begin()
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return c, nil
+}
+
+func (c *sqlmock) begin() (*ExpectedBegin, error) {
+ var expected *ExpectedBegin
+ var ok bool
+ var fulfilled int
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedBegin); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return nil, fmt.Errorf("call to database transaction Begin, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ 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)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+
+ return expected, expected.err
+}
+
+func (c *sqlmock) ExpectBegin() *ExpectedBegin {
+ e := &ExpectedBegin{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Exec meets http://golang.org/pkg/database/sql/driver/#Execer
+func (c *sqlmock) Exec(query string, args []driver.Value) (driver.Result, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, v := range args {
+ namedArgs[i] = namedValue{
+ Ordinal: i + 1,
+ Value: v,
+ }
+ }
+
+ ex, err := c.exec(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return ex.result, nil
+}
+
+func (c *sqlmock) exec(query string, args []namedValue) (*ExpectedExec, error) {
+ query = stripQuery(query)
+ var expected *ExpectedExec
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if c.ordered {
+ if expected, ok = next.(*ExpectedExec); ok {
+ break
+ }
+ next.Unlock()
+ return nil, fmt.Errorf("call to exec query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
+ }
+ if exec, ok := next.(*ExpectedExec); ok {
+ if err := exec.attemptMatch(query, args); err == nil {
+ expected = exec
+ break
+ }
+ }
+ next.Unlock()
+ }
+ if expected == nil {
+ msg := "call to exec '%s' query with args %+v was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query, args)
+ }
+ defer expected.Unlock()
+
+ if !expected.queryMatches(query) {
+ return nil, fmt.Errorf("exec query '%s', does not match regex '%s'", query, expected.sqlRegex.String())
+ }
+
+ if err := expected.argsMatches(args); err != nil {
+ return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
+ }
+
+ expected.triggered = true
+ if expected.err != nil {
+ return nil, expected.err // mocked to return error
+ }
+
+ if expected.result == nil {
+ return nil, fmt.Errorf("exec query '%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)
+ }
+
+ return expected, nil
+}
+
+func (c *sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec {
+ e := &ExpectedExec{}
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e.sqlRegex = regexp.MustCompile(sqlRegexStr)
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Prepare meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Prepare(query string) (driver.Stmt, error) {
+ ex, err := c.prepare(query)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return &statement{c, query, ex.closeErr}, nil
+}
+
+func (c *sqlmock) prepare(query string) (*ExpectedPrepare, error) {
+ var expected *ExpectedPrepare
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedPrepare); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return nil, fmt.Errorf("call to Prepare statement with query '%s', was not expected, next expectation is: %s", query, next)
+ }
+ }
+
+ query = stripQuery(query)
+ if expected == nil {
+ 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)
+ }
+ defer expected.Unlock()
+ if !expected.sqlRegex.MatchString(query) {
+ return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
+ }
+
+ expected.triggered = true
+ return expected, expected.err
+}
+
+func (c *sqlmock) ExpectPrepare(sqlRegexStr string) *ExpectedPrepare {
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e := &ExpectedPrepare{sqlRegex: regexp.MustCompile(sqlRegexStr), mock: c}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+type namedValue struct {
+ Name string
+ Ordinal int
+ Value driver.Value
+}
+
+// Query meets http://golang.org/pkg/database/sql/driver/#Queryer
+func (c *sqlmock) Query(query string, args []driver.Value) (driver.Rows, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, v := range args {
+ namedArgs[i] = namedValue{
+ Ordinal: i + 1,
+ Value: v,
+ }
+ }
+
+ ex, err := c.query(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return ex.rows, nil
+}
+
+func (c *sqlmock) query(query string, args []namedValue) (*ExpectedQuery, error) {
+ query = stripQuery(query)
+ var expected *ExpectedQuery
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if c.ordered {
+ if expected, ok = next.(*ExpectedQuery); ok {
+ break
+ }
+ next.Unlock()
+ return nil, fmt.Errorf("call to query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
+ }
+ if qr, ok := next.(*ExpectedQuery); ok {
+ if err := qr.attemptMatch(query, args); err == nil {
+ expected = qr
+ break
+ }
+ }
+ next.Unlock()
+ }
+
+ if expected == nil {
+ msg := "call to query '%s' with args %+v was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query, args)
+ }
+
+ defer expected.Unlock()
+
+ if !expected.queryMatches(query) {
+ return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
+ }
+
+ if err := expected.argsMatches(args); err != nil {
+ return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
+ }
+
+ expected.triggered = true
+ if expected.err != nil {
+ return nil, expected.err // mocked to return error
+ }
+
+ if expected.rows == nil {
+ 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)
+ }
+ return expected, nil
+}
+
+func (c *sqlmock) ExpectQuery(sqlRegexStr string) *ExpectedQuery {
+ e := &ExpectedQuery{}
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e.sqlRegex = regexp.MustCompile(sqlRegexStr)
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) ExpectCommit() *ExpectedCommit {
+ e := &ExpectedCommit{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) ExpectRollback() *ExpectedRollback {
+ e := &ExpectedRollback{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Commit meets http://golang.org/pkg/database/sql/driver/#Tx
+func (c *sqlmock) Commit() error {
+ var expected *ExpectedCommit
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedCommit); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to commit transaction, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to commit transaction was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
+
+// Rollback meets http://golang.org/pkg/database/sql/driver/#Tx
+func (c *sqlmock) Rollback() error {
+ var expected *ExpectedRollback
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedRollback); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to rollback transaction, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to rollback transaction was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18.go
new file mode 100644
index 0000000..c49429c
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18.go
@@ -0,0 +1,101 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "context"
+ "database/sql/driver"
+ "errors"
+ "time"
+)
+
+var ErrCancelled = errors.New("canceling query due to user request")
+
+// Implement the "QueryerContext" interface
+func (c *sqlmock) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, nv := range args {
+ namedArgs[i] = namedValue(nv)
+ }
+
+ ex, err := c.query(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return ex.rows, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ExecerContext" interface
+func (c *sqlmock) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, nv := range args {
+ namedArgs[i] = namedValue(nv)
+ }
+
+ ex, err := c.exec(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return ex.result, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ConnBeginTx" interface
+func (c *sqlmock) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
+ ex, err := c.begin()
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return c, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ConnPrepareContext" interface
+func (c *sqlmock) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
+ ex, err := c.prepare(query)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return &statement{c, query, ex.closeErr}, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "Pinger" interface
+// for now we do not have a Ping expectation
+// may be something for the future
+func (c *sqlmock) Ping(ctx context.Context) error {
+ return nil
+}
+
+// Implement the "StmtExecContext" interface
+func (stmt *statement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
+ return stmt.conn.ExecContext(ctx, stmt.query, args)
+}
+
+// Implement the "StmtQueryContext" interface
+func (stmt *statement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
+ return stmt.conn.QueryContext(ctx, stmt.query, args)
+}
+
+// @TODO maybe add ExpectedBegin.WithOptions(driver.TxOptions)
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18_test.go
new file mode 100644
index 0000000..9eadcb5
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18_test.go
@@ -0,0 +1,426 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "context"
+ "database/sql"
+ "testing"
+ "time"
+)
+
+func TestContextExecCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users")
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users")
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedStatementContextExecCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("DELETE FROM users").
+ ExpectExec().
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.Prepare("DELETE FROM users")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ _, err = stmt.ExecContext(ctx)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = stmt.ExecContext(ctx)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextExecWithNamedArg(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WithArgs(sql.Named("id", 5)).
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextExec(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ res, err := db.ExecContext(ctx, "DELETE FROM users")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ affected, err := res.RowsAffected()
+ if affected != 1 {
+ t.Errorf("expected affected rows 1, but got %v", affected)
+ }
+
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextQueryCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillDelayFor(time.Second).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedStatementContextQueryCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
+ ExpectQuery().
+ WithArgs(5).
+ WillDelayFor(time.Second).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ _, err = stmt.QueryContext(ctx, 5)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = stmt.QueryContext(ctx, 5)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextQuery(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id =").
+ WithArgs(sql.Named("id", 5)).
+ WillDelayFor(time.Millisecond * 3).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ rows, err := db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = :id", sql.Named("id", 5))
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if !rows.Next() {
+ t.Error("expected one row, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextBeginCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin().WillDelayFor(time.Second)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.BeginTx(ctx, nil)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.BeginTx(ctx, nil)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextBegin(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin().WillDelayFor(time.Millisecond * 3)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if tx == nil {
+ t.Error("expected tx, but there was nil")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextPrepareCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT").WillDelayFor(time.Second)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.PrepareContext(ctx, "SELECT")
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.PrepareContext(ctx, "SELECT")
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextPrepare(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT").WillDelayFor(time.Millisecond * 3)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.PrepareContext(ctx, "SELECT")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if stmt == nil {
+ t.Error("expected stmt, but there was nil")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}