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)
+	}
+}