http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
new file mode 100644
index 0000000..a63e72b
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
new file mode 100644
index 0000000..39f9f83
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
new file mode 100644
index 0000000..b906a3f
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/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/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)
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
new file mode 100644
index 0000000..fe4924b
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
@@ -0,0 +1,998 @@
+package sqlmock
+
+import (
+       "database/sql"
+       "fmt"
+       "strconv"
+       "sync"
+       "testing"
+       "time"
+)
+
+func cancelOrder(db *sql.DB, orderID int) error {
+       tx, _ := db.Begin()
+       _, _ = tx.Query("SELECT * FROM orders {0} FOR UPDATE", orderID)
+       err := tx.Rollback()
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func Example() {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       // columns to be used for result
+       columns := []string{"id", "status"}
+       // expect transaction begin
+       mock.ExpectBegin()
+       // expect query to fetch order, match it with regexp
+       mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
+               WithArgs(1).
+               WillReturnRows(NewRows(columns).AddRow(1, 1))
+       // expect transaction rollback, since order status is "cancelled"
+       mock.ExpectRollback()
+
+       // run the cancel order function
+       someOrderID := 1
+       // call a function which executes expected database operations
+       err = cancelOrder(db, someOrderID)
+       if err != nil {
+               fmt.Printf("unexpected error: %s", err)
+               return
+       }
+
+       // ensure all expectations have been met
+       if err = mock.ExpectationsWereMet(); err != nil {
+               fmt.Printf("unmet expectation error: %s", err)
+       }
+       // Output:
+}
+
+func TestIssue14EscapeSQL(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("INSERT INTO mytable\\(a, b\\)").
+               WithArgs("A", "B").
+               WillReturnResult(NewResult(1, 1))
+
+       _, err = db.Exec("INSERT INTO mytable(a, b) VALUES (?, ?)", "A", "B")
+       if err != nil {
+               t.Errorf("error '%s' was not expected, while inserting a row", 
err)
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+// test the case when db is not triggered and expectations
+// are not asserted on close
+func TestIssue4(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.ExpectQuery("some sql query which will not be called").
+               WillReturnRows(NewRows([]string{"id"}))
+
+       if err := mock.ExpectationsWereMet(); err == nil {
+               t.Errorf("was expecting an error since query was not triggered")
+       }
+}
+
+func TestMockQuery(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"}).FromCSVString("5,hello world")
+
+       mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+               WithArgs(5).
+               WillReturnRows(rs)
+
+       rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while retrieving mock 
rows", err)
+       }
+
+       defer func() {
+               if er := rows.Close(); er != nil {
+                       t.Error("Unexpected error while trying to close rows")
+               }
+       }()
+
+       if !rows.Next() {
+               t.Error("it must have had one row as result, but got empty 
result set instead")
+       }
+
+       var id int
+       var title string
+
+       err = rows.Scan(&id, &title)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while trying to scan 
row", err)
+       }
+
+       if id != 5 {
+               t.Errorf("expected mocked id to be 5, but got %d instead", id)
+       }
+
+       if title != "hello world" {
+               t.Errorf("expected mocked title to be 'hello world', but got 
'%s' instead", title)
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestMockQueryTypes(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()
+
+       columns := []string{"id", "timestamp", "sold"}
+
+       timestamp := time.Now()
+       rs := NewRows(columns)
+       rs.AddRow(5, timestamp, true)
+
+       mock.ExpectQuery("SELECT (.+) FROM sales WHERE id = ?").
+               WithArgs(5).
+               WillReturnRows(rs)
+
+       rows, err := db.Query("SELECT (.+) FROM sales WHERE id = ?", 5)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while retrieving mock 
rows", err)
+       }
+       defer func() {
+               if er := rows.Close(); er != nil {
+                       t.Error("Unexpected error while trying to close rows")
+               }
+       }()
+       if !rows.Next() {
+               t.Error("it must have had one row as result, but got empty 
result set instead")
+       }
+
+       var id int
+       var time time.Time
+       var sold bool
+
+       err = rows.Scan(&id, &time, &sold)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while trying to scan 
row", err)
+       }
+
+       if id != 5 {
+               t.Errorf("expected mocked id to be 5, but got %d instead", id)
+       }
+
+       if time != timestamp {
+               t.Errorf("expected mocked time to be %s, but got '%s' instead", 
timestamp, time)
+       }
+
+       if sold != true {
+               t.Errorf("expected mocked boolean to be true, but got %v 
instead", sold)
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestTransactionExpectations(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()
+
+       // begin and commit
+       mock.ExpectBegin()
+       mock.ExpectCommit()
+
+       tx, err := db.Begin()
+       if err != nil {
+               t.Errorf("an error '%s' was not expected when beginning a 
transaction", err)
+       }
+
+       err = tx.Commit()
+       if err != nil {
+               t.Errorf("an error '%s' was not expected when committing a 
transaction", err)
+       }
+
+       // begin and rollback
+       mock.ExpectBegin()
+       mock.ExpectRollback()
+
+       tx, err = db.Begin()
+       if err != nil {
+               t.Errorf("an error '%s' was not expected when beginning a 
transaction", err)
+       }
+
+       err = tx.Rollback()
+       if err != nil {
+               t.Errorf("an error '%s' was not expected when rolling back a 
transaction", err)
+       }
+
+       // begin with an error
+       mock.ExpectBegin().WillReturnError(fmt.Errorf("some err"))
+
+       tx, err = db.Begin()
+       if err == nil {
+               t.Error("an error was expected when beginning a transaction, 
but got none")
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestPrepareExpectations(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 (.+) FROM articles WHERE id = ?")
+
+       stmt, err := db.Prepare("SELECT (.+) FROM articles WHERE id = ?")
+       if err != nil {
+               t.Errorf("error '%s' was not expected while creating a prepared 
statement", err)
+       }
+       if stmt == nil {
+               t.Errorf("stmt was expected while creating a prepared 
statement")
+       }
+
+       // expect something else, w/o ExpectPrepare()
+       var id int
+       var title string
+       rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+
+       mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+               WithArgs(5).
+               WillReturnRows(rs)
+
+       err = stmt.QueryRow(5).Scan(&id, &title)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while retrieving mock 
rows", err)
+       }
+
+       mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
+               WillReturnError(fmt.Errorf("Some DB error occurred"))
+
+       stmt, err = db.Prepare("SELECT id FROM articles WHERE id = ?")
+       if err == nil {
+               t.Error("error was expected while creating a prepared 
statement")
+       }
+       if stmt != nil {
+               t.Errorf("stmt was not expected while creating a prepared 
statement returning error")
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestPreparedQueryExecutions(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 (.+) FROM articles WHERE id = ?")
+
+       rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+       mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+               WithArgs(5).
+               WillReturnRows(rs1)
+
+       rs2 := NewRows([]string{"id", "title"}).FromCSVString("2,whoop")
+       mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+               WithArgs(2).
+               WillReturnRows(rs2)
+
+       stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+       if err != nil {
+               t.Errorf("error '%s' was not expected while creating a prepared 
statement", err)
+       }
+
+       var id int
+       var title string
+       err = stmt.QueryRow(5).Scan(&id, &title)
+       if err != nil {
+               t.Errorf("error '%s' was not expected querying row from 
statement and scanning", err)
+       }
+
+       if id != 5 {
+               t.Errorf("expected mocked id to be 5, but got %d instead", id)
+       }
+
+       if title != "hello world" {
+               t.Errorf("expected mocked title to be 'hello world', but got 
'%s' instead", title)
+       }
+
+       err = stmt.QueryRow(2).Scan(&id, &title)
+       if err != nil {
+               t.Errorf("error '%s' was not expected querying row from 
statement and scanning", err)
+       }
+
+       if id != 2 {
+               t.Errorf("expected mocked id to be 2, but got %d instead", id)
+       }
+
+       if title != "whoop" {
+               t.Errorf("expected mocked title to be 'whoop', but got '%s' 
instead", title)
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestUnexpectedOperations(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 (.+) FROM articles WHERE id = ?")
+       stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+       if err != nil {
+               t.Errorf("error '%s' was not expected while creating a prepared 
statement", err)
+       }
+
+       var id int
+       var title string
+
+       err = stmt.QueryRow(5).Scan(&id, &title)
+       if err == nil {
+               t.Error("error was expected querying row, since there was no 
such expectation")
+       }
+
+       mock.ExpectRollback()
+
+       if err := mock.ExpectationsWereMet(); err == nil {
+               t.Errorf("was expecting an error since query was not triggered")
+       }
+}
+
+func TestWrongExpectations(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()
+
+       rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+       mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+               WithArgs(5).
+               WillReturnRows(rs1)
+
+       mock.ExpectCommit().WillReturnError(fmt.Errorf("deadlock occurred"))
+       mock.ExpectRollback() // won't be triggered
+
+       var id int
+       var title string
+
+       err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR 
UPDATE", 5).Scan(&id, &title)
+       if err == nil {
+               t.Error("error was expected while querying row, since there 
begin transaction expectation is not fulfilled")
+       }
+
+       // lets go around and start transaction
+       tx, err := db.Begin()
+       if err != nil {
+               t.Errorf("an error '%s' was not expected when beginning a 
transaction", err)
+       }
+
+       err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR 
UPDATE", 5).Scan(&id, &title)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while querying row, since 
transaction was started", err)
+       }
+
+       err = tx.Commit()
+       if err == nil {
+               t.Error("a deadlock error was expected when committing a 
transaction", err)
+       }
+
+       if err := mock.ExpectationsWereMet(); err == nil {
+               t.Errorf("was expecting an error since query was not triggered")
+       }
+}
+
+func TestExecExpectations(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()
+
+       result := NewResult(1, 1)
+       mock.ExpectExec("^INSERT INTO articles").
+               WithArgs("hello").
+               WillReturnResult(result)
+
+       res, err := db.Exec("INSERT INTO articles (title) VALUES (?)", "hello")
+       if err != nil {
+               t.Errorf("error '%s' was not expected, while inserting a row", 
err)
+       }
+
+       id, err := res.LastInsertId()
+       if err != nil {
+               t.Errorf("error '%s' was not expected, while getting a last 
insert id", err)
+       }
+
+       affected, err := res.RowsAffected()
+       if err != nil {
+               t.Errorf("error '%s' was not expected, while getting affected 
rows", err)
+       }
+
+       if id != 1 {
+               t.Errorf("expected last insert id to be 1, but got %d instead", 
id)
+       }
+
+       if affected != 1 {
+               t.Errorf("expected affected rows to be 1, but got %d instead", 
affected)
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestRowBuilderAndNilTypes(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", "active", "created", "status"}).
+               AddRow(1, true, time.Now(), 5).
+               AddRow(2, false, nil, nil)
+
+       mock.ExpectQuery("SELECT (.+) FROM sales").WillReturnRows(rs)
+
+       rows, err := db.Query("SELECT * FROM sales")
+       if err != nil {
+               t.Errorf("error '%s' was not expected while retrieving mock 
rows", err)
+       }
+       defer func() {
+               if er := rows.Close(); er != nil {
+                       t.Error("Unexpected error while trying to close rows")
+               }
+       }()
+
+       // NullTime and NullInt are used from stubs_test.go
+       var (
+               id      int
+               active  bool
+               created NullTime
+               status  NullInt
+       )
+
+       if !rows.Next() {
+               t.Error("it must have had row in rows, but got empty result set 
instead")
+       }
+
+       err = rows.Scan(&id, &active, &created, &status)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while trying to scan 
row", err)
+       }
+
+       if id != 1 {
+               t.Errorf("expected mocked id to be 1, but got %d instead", id)
+       }
+
+       if !active {
+               t.Errorf("expected 'active' to be 'true', but got '%v' 
instead", active)
+       }
+
+       if !created.Valid {
+               t.Errorf("expected 'created' to be valid, but it %+v is not", 
created)
+       }
+
+       if !status.Valid {
+               t.Errorf("expected 'status' to be valid, but it %+v is not", 
status)
+       }
+
+       if status.Integer != 5 {
+               t.Errorf("expected 'status' to be '5', but got '%d'", 
status.Integer)
+       }
+
+       // test second row
+       if !rows.Next() {
+               t.Error("it must have had row in rows, but got empty result set 
instead")
+       }
+
+       err = rows.Scan(&id, &active, &created, &status)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while trying to scan 
row", err)
+       }
+
+       if id != 2 {
+               t.Errorf("expected mocked id to be 2, but got %d instead", id)
+       }
+
+       if active {
+               t.Errorf("expected 'active' to be 'false', but got '%v' 
instead", active)
+       }
+
+       if created.Valid {
+               t.Errorf("expected 'created' to be invalid, but it %+v is not", 
created)
+       }
+
+       if status.Valid {
+               t.Errorf("expected 'status' to be invalid, but it %+v is not", 
status)
+       }
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestArgumentReflectValueTypeError(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"}).AddRow(1)
+
+       mock.ExpectQuery("SELECT (.+) FROM 
sales").WithArgs(5.5).WillReturnRows(rs)
+
+       _, err = db.Query("SELECT * FROM sales WHERE x = ?", 5)
+       if err == nil {
+               t.Error("Expected error, but got none")
+       }
+}
+
+func TestGoroutineExecutionWithUnorderedExpectationMatching(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()
+
+       // note this line is important for unordered expectation matching
+       mock.MatchExpectationsInOrder(false)
+
+       result := NewResult(1, 1)
+
+       mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
+       mock.ExpectExec("^UPDATE two").WithArgs("one", 
"two").WillReturnResult(result)
+       mock.ExpectExec("^UPDATE three").WithArgs("one", "two", 
"three").WillReturnResult(result)
+
+       var wg sync.WaitGroup
+       queries := map[string][]interface{}{
+               "one":   []interface{}{"one"},
+               "two":   []interface{}{"one", "two"},
+               "three": []interface{}{"one", "two", "three"},
+       }
+
+       wg.Add(len(queries))
+       for table, args := range queries {
+               go func(tbl string, a []interface{}) {
+                       if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
+                               t.Errorf("error was not expected: %s", err)
+                       }
+                       wg.Done()
+               }(table, args)
+       }
+
+       wg.Wait()
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func ExampleSqlmock_goroutines() {
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("failed to open sqlmock database:", err)
+       }
+       defer db.Close()
+
+       // note this line is important for unordered expectation matching
+       mock.MatchExpectationsInOrder(false)
+
+       result := NewResult(1, 1)
+
+       mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
+       mock.ExpectExec("^UPDATE two").WithArgs("one", 
"two").WillReturnResult(result)
+       mock.ExpectExec("^UPDATE three").WithArgs("one", "two", 
"three").WillReturnResult(result)
+
+       var wg sync.WaitGroup
+       queries := map[string][]interface{}{
+               "one":   []interface{}{"one"},
+               "two":   []interface{}{"one", "two"},
+               "three": []interface{}{"one", "two", "three"},
+       }
+
+       wg.Add(len(queries))
+       for table, args := range queries {
+               go func(tbl string, a []interface{}) {
+                       if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
+                               fmt.Println("error was not expected:", err)
+                       }
+                       wg.Done()
+               }(table, args)
+       }
+
+       wg.Wait()
+
+       if err := mock.ExpectationsWereMet(); err != nil {
+               fmt.Println("there were unfulfilled expections:", err)
+       }
+       // Output:
+}
+
+// False Positive - passes despite mismatched Exec
+// see #37 issue
+func TestRunExecsWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
+       db, dbmock, _ := New()
+       dbmock.ExpectExec("THE FIRST EXEC")
+       dbmock.ExpectExec("THE SECOND EXEC")
+
+       _, _ = db.Exec("THE FIRST EXEC")
+       _, _ = db.Exec("THE WRONG EXEC")
+
+       err := dbmock.ExpectationsWereMet()
+       if err == nil {
+               t.Fatal("was expecting an error, but there wasn't any")
+       }
+}
+
+// False Positive - passes despite mismatched Exec
+// see #37 issue
+func TestRunQueriesWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
+       db, dbmock, _ := New()
+       dbmock.ExpectQuery("THE FIRST QUERY")
+       dbmock.ExpectQuery("THE SECOND QUERY")
+
+       _, _ = db.Query("THE FIRST QUERY")
+       _, _ = db.Query("THE WRONG QUERY")
+
+       err := dbmock.ExpectationsWereMet()
+       if err == nil {
+               t.Fatal("was expecting an error, but there wasn't any")
+       }
+}
+
+func TestRunExecsWithExpectedErrorMeetsExpectations(t *testing.T) {
+       db, dbmock, _ := New()
+       dbmock.ExpectExec("THE FIRST EXEC").WillReturnError(fmt.Errorf("big bad 
bug"))
+       dbmock.ExpectExec("THE SECOND EXEC").WillReturnResult(NewResult(0, 0))
+
+       _, _ = db.Exec("THE FIRST EXEC")
+       _, _ = db.Exec("THE SECOND EXEC")
+
+       err := dbmock.ExpectationsWereMet()
+       if err != nil {
+               t.Fatalf("all expectations should be met: %s", err)
+       }
+}
+
+func TestRunQueryWithExpectedErrorMeetsExpectations(t *testing.T) {
+       db, dbmock, _ := New()
+       dbmock.ExpectQuery("THE FIRST QUERY").WillReturnError(fmt.Errorf("big 
bad bug"))
+       dbmock.ExpectQuery("THE SECOND 
QUERY").WillReturnRows(NewRows([]string{"col"}).AddRow(1))
+
+       _, _ = db.Query("THE FIRST QUERY")
+       _, _ = db.Query("THE SECOND QUERY")
+
+       err := dbmock.ExpectationsWereMet()
+       if err != nil {
+               t.Fatalf("all expectations should be met: %s", err)
+       }
+}
+
+func TestEmptyRowSet(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"})
+
+       mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+               WithArgs(5).
+               WillReturnRows(rs)
+
+       rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
+       if err != nil {
+               t.Errorf("error '%s' was not expected while retrieving mock 
rows", err)
+       }
+
+       defer func() {
+               if er := rows.Close(); er != nil {
+                       t.Error("Unexpected error while trying to close rows")
+               }
+       }()
+
+       if rows.Next() {
+               t.Error("expected no rows but got one")
+       }
+
+       err = mock.ExpectationsWereMet()
+       if err != nil {
+               t.Fatalf("all expectations should be met: %s", err)
+       }
+}
+
+// Based on issue #50
+func TestPrepareExpectationNotFulfilled(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("^BADSELECT$")
+
+       if _, err := db.Prepare("SELECT"); err == nil {
+               t.Fatal("prepare should not match expected query string")
+       }
+
+       if err := mock.ExpectationsWereMet(); err == nil {
+               t.Errorf("was expecting an error, since prepared statement 
query does not match, but there was none")
+       }
+}
+
+func TestRollbackThrow(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       // columns to be used for result
+       columns := []string{"id", "status"}
+       // expect transaction begin
+       mock.ExpectBegin()
+       // expect query to fetch order, match it with regexp
+       mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
+               WithArgs(1).
+               WillReturnRows(NewRows(columns).AddRow(1, 1))
+       // expect transaction rollback, since order status is "cancelled"
+       mock.ExpectRollback().WillReturnError(fmt.Errorf("rollback failed"))
+
+       // run the cancel order function
+       someOrderID := 1
+       // call a function which executes expected database operations
+       err = cancelOrder(db, someOrderID)
+       if err == nil {
+               t.Error("an error was expected when rolling back transaction, 
but got none")
+       }
+
+       // ensure all expectations have been met
+       if err = mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("unmet expectation error: %s", err)
+       }
+       // Output:
+}
+
+func TestUnexpectedCommit(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectBegin()
+       tx, _ := db.Begin()
+       if err := tx.Commit(); err == nil {
+               t.Error("an error was expected when calling commit, but got 
none")
+       }
+}
+
+func TestUnexpectedCommitOrder(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectBegin()
+       mock.ExpectRollback().WillReturnError(fmt.Errorf("Rollback failed"))
+       tx, _ := db.Begin()
+       if err := tx.Commit(); err == nil {
+               t.Error("an error was expected when calling commit, but got 
none")
+       }
+}
+
+func TestExpectedCommitOrder(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectCommit().WillReturnError(fmt.Errorf("Commit failed"))
+       if _, err := db.Begin(); err == nil {
+               t.Error("an error was expected when calling begin, but got 
none")
+       }
+}
+
+func TestUnexpectedRollback(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectBegin()
+       tx, _ := db.Begin()
+       if err := tx.Rollback(); err == nil {
+               t.Error("an error was expected when calling rollback, but got 
none")
+       }
+}
+
+func TestUnexpectedRollbackOrder(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectBegin()
+
+       tx, _ := db.Begin()
+       if err := tx.Rollback(); err == nil {
+               t.Error("an error was expected when calling rollback, but got 
none")
+       }
+}
+
+func TestPrepareExec(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       defer db.Close()
+       mock.ExpectBegin()
+       ep := mock.ExpectPrepare("INSERT INTO ORDERS\\(ID, STATUS\\) VALUES 
\\(\\?, \\?\\)")
+       for i := 0; i < 3; i++ {
+               ep.ExpectExec().WillReturnResult(NewResult(1, 1))
+       }
+       mock.ExpectCommit()
+       tx, _ := db.Begin()
+       stmt, err := tx.Prepare("INSERT INTO ORDERS(ID, STATUS) VALUES (?, ?)")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer stmt.Close()
+       for i := 0; i < 3; i++ {
+               _, err := stmt.Exec(i, "Hello"+strconv.Itoa(i))
+               if err != nil {
+                       t.Fatal(err)
+               }
+       }
+       tx.Commit()
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestPrepareQuery(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       defer db.Close()
+       mock.ExpectBegin()
+       ep := mock.ExpectPrepare("SELECT ID, STATUS FROM ORDERS WHERE ID = \\?")
+       ep.ExpectQuery().WithArgs(101).WillReturnRows(NewRows([]string{"ID", 
"STATUS"}).AddRow(101, "Hello"))
+       mock.ExpectCommit()
+       tx, _ := db.Begin()
+       stmt, err := tx.Prepare("SELECT ID, STATUS FROM ORDERS WHERE ID = ?")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer stmt.Close()
+       rows, err := stmt.Query(101)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer rows.Close()
+       for rows.Next() {
+               var (
+                       id     int
+                       status string
+               )
+               if rows.Scan(&id, &status); id != 101 || status != "Hello" {
+                       t.Fatal("wrong query results")
+               }
+
+       }
+       tx.Commit()
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestExpectedCloseError(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
+       if err := db.Close(); err == nil {
+               t.Error("an error was expected when calling close, but got 
none")
+       }
+       if err := mock.ExpectationsWereMet(); err != nil {
+               t.Errorf("there were unfulfilled expections: %s", err)
+       }
+}
+
+func TestExpectedCloseOrder(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       defer db.Close()
+       mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
+       db.Begin()
+       if err := mock.ExpectationsWereMet(); err == nil {
+               t.Error("expected error on ExpectationsWereMet")
+       }
+}
+
+func TestExpectedBeginOrder(t *testing.T) {
+       // Open new mock database
+       db, mock, err := New()
+       if err != nil {
+               fmt.Println("error creating mock database")
+               return
+       }
+       mock.ExpectBegin().WillReturnError(fmt.Errorf("Begin failed"))
+       if err := db.Close(); err == nil {
+               t.Error("an error was expected when calling close, but got 
none")
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
new file mode 100644
index 0000000..df73740
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
@@ -0,0 +1,27 @@
+package sqlmock
+
+import (
+       "database/sql/driver"
+)
+
+type statement struct {
+       conn  *sqlmock
+       query string
+       err   error
+}
+
+func (stmt *statement) Close() error {
+       return stmt.err
+}
+
+func (stmt *statement) NumInput() int {
+       return -1
+}
+
+func (stmt *statement) Exec(args []driver.Value) (driver.Result, error) {
+       return stmt.conn.Exec(stmt.query, args)
+}
+
+func (stmt *statement) Query(args []driver.Value) (driver.Rows, error) {
+       return stmt.conn.Query(stmt.query, args)
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
new file mode 100644
index 0000000..f951f63
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
@@ -0,0 +1,33 @@
+// +build go1.6
+
+package sqlmock
+
+import (
+       "errors"
+       "testing"
+)
+
+func TestExpectedPreparedStatemtCloseError(t *testing.T) {
+       conn, mock, err := New()
+       if err != nil {
+               t.Fatal("failed to open sqlmock database:", err)
+       }
+
+       mock.ExpectBegin()
+       want := errors.New("STMT ERROR")
+       mock.ExpectPrepare("SELECT").WillReturnCloseError(want)
+
+       txn, err := conn.Begin()
+       if err != nil {
+               t.Fatal("unexpected error while opening transaction:", err)
+       }
+
+       stmt, err := txn.Prepare("SELECT")
+       if err != nil {
+               t.Fatal("unexpected error while preparing a statement:", err)
+       }
+
+       if err := stmt.Close(); err != want {
+               t.Fatalf("Got = %v, want = %v", err, want)
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
new file mode 100644
index 0000000..d3c6003
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
@@ -0,0 +1,76 @@
+package sqlmock
+
+import (
+       "database/sql/driver"
+       "fmt"
+       "strconv"
+       "time"
+)
+
+type NullTime struct {
+       Time  time.Time
+       Valid bool // Valid is true if Time is not NULL
+}
+
+type NullInt struct {
+       Integer int
+       Valid   bool
+}
+
+// Satisfy sql.Scanner interface
+func (ni *NullInt) Scan(value interface{}) (err error) {
+       if value == nil {
+               ni.Integer, ni.Valid = 0, false
+               return
+       }
+
+       switch v := value.(type) {
+       case int, int8, int16, int32, int64:
+               ni.Integer, ni.Valid = v.(int), true
+               return
+       case []byte:
+               ni.Integer, err = strconv.Atoi(string(v))
+               ni.Valid = (err == nil)
+               return
+       case string:
+               ni.Integer, err = strconv.Atoi(v)
+               ni.Valid = (err == nil)
+               return
+       }
+
+       ni.Valid = false
+       return fmt.Errorf("Can't convert %T to integer", value)
+}
+
+// Satisfy sql.Valuer interface.
+func (ni NullInt) Value() (driver.Value, error) {
+       if !ni.Valid {
+               return nil, nil
+       }
+       return ni.Integer, nil
+}
+
+// Satisfy sql.Scanner interface
+func (nt *NullTime) Scan(value interface{}) (err error) {
+       if value == nil {
+               nt.Time, nt.Valid = time.Time{}, false
+               return
+       }
+
+       switch v := value.(type) {
+       case time.Time:
+               nt.Time, nt.Valid = v, true
+               return
+       }
+
+       nt.Valid = false
+       return fmt.Errorf("Can't convert %T to time.Time", value)
+}
+
+// Satisfy sql.Valuer interface.
+func (nt NullTime) Value() (driver.Value, error) {
+       if !nt.Valid {
+               return nil, nil
+       }
+       return nt.Time, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
new file mode 100644
index 0000000..072e380
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
@@ -0,0 +1,13 @@
+package sqlmock
+
+import (
+       "regexp"
+       "strings"
+)
+
+var re = regexp.MustCompile("\\s+")
+
+// strip out new lines and trim spaces
+func stripQuery(q string) (s string) {
+       return strings.TrimSpace(re.ReplaceAllString(q, " "))
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
new file mode 100644
index 0000000..c4b3974
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
@@ -0,0 +1,21 @@
+package sqlmock
+
+import (
+       "testing"
+)
+
+func TestQueryStringStripping(t *testing.T) {
+       assert := func(actual, expected string) {
+               if res := stripQuery(actual); res != expected {
+                       t.Errorf("Expected '%s' to be '%s', but got '%s'", 
actual, expected, res)
+               }
+       }
+
+       assert(" SELECT 1", "SELECT 1")
+       assert("SELECT   1 FROM   d", "SELECT 1 FROM d")
+       assert(`
+    SELECT c
+    FROM D
+`, "SELECT c FROM D")
+       assert("UPDATE  (.+) SET  ", "UPDATE (.+) SET")
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go 
b/traffic_ops/traffic_ops_golang/wrappers.go
index f986d2f..30c36b4 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -22,8 +22,8 @@ package main
 import (
        "database/sql"
        "fmt"
+       
"github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
-       "log" // TODO change to traffic_monitor_golang/common/log
        "net/http"
        "time"
 )
@@ -33,8 +33,16 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret 
string, privLevelStmt *sql
                return h
        }
        return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+               // TODO remove, and make username available to wrapLogTime
+               start := time.Now()
+               iw := &Interceptor{w: w}
+               w = iw
+               username := "-"
+               defer func() {
+                       log.Infof(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 
"%v"\n`, r.RemoteAddr, username, time.Now().Format(AccessLogTimeFormat), 
r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, 
iw.byteCount, r.UserAgent())
+               }()
+
                handleUnauthorized := func(reason string) {
-                       log.Printf("%v %v %v sent 401 - %v\n", time.Now(), 
r.RemoteAddr, r.URL.Path, reason)
                        status := http.StatusUnauthorized
                        w.WriteHeader(status)
                        fmt.Fprintf(w, http.StatusText(status))
@@ -57,7 +65,7 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, 
privLevelStmt *sql
                        return
                }
 
-               username := oldCookie.AuthData
+               username = oldCookie.AuthData
                if !hasPrivLevel(privLevelStmt, username, privLevelRequired) {
                        handleUnauthorized("insufficient privileges")
                        return
@@ -65,17 +73,42 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret 
string, privLevelStmt *sql
 
                newCookieVal := tocookie.Refresh(oldCookie, secret)
                http.SetCookie(w, &http.Cookie{Name: tocookie.Name, Value: 
newCookieVal})
+
                h(w, r, p)
        }
 }
 
+const AccessLogTimeFormat = "02/Jan/2006:15:04:05 -0700"
+
 func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
        return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
                start := time.Now()
+               iw := &Interceptor{w: w}
                defer func() {
-                       now := time.Now()
-                       log.Printf("%v %v served %v in %v\n", now, 
r.RemoteAddr, r.URL.Path, now.Sub(start))
+                       user := "-" // TODO fix
+                       log.Infof(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 
"%v"\n`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, 
r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, 
r.UserAgent())
                }()
-               h(w, r, p)
+               h(iw, r, p)
        }
 }
+
+type Interceptor struct {
+       w         http.ResponseWriter
+       code      int
+       byteCount int
+}
+
+func (i *Interceptor) WriteHeader(rc int) {
+       i.w.WriteHeader(rc)
+       i.code = rc
+}
+
+func (i *Interceptor) Write(b []byte) (int, error) {
+       wi, werr := i.w.Write(b)
+       i.byteCount += wi
+       return wi, werr
+}
+
+func (i *Interceptor) Header() http.Header {
+       return i.w.Header()
+}


Reply via email to