Merge pull request #23 from mihaelabalutoiu/add-db-instances-unit-tests
Add `instances.go` database unit tests
This commit is contained in:
commit
e9aba82ec1
20 changed files with 2064 additions and 44 deletions
|
|
@ -16,27 +16,38 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
dbCommon "garm/database/common"
|
||||
garmTesting "garm/internal/testing"
|
||||
"garm/params"
|
||||
"garm/runner/providers/common"
|
||||
"regexp"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/DATA-DOG/go-sqlmock.v1"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
type InstancesTestFixtures struct {
|
||||
Org params.Organization
|
||||
Pool params.Pool
|
||||
Instances []params.Instance
|
||||
Org params.Organization
|
||||
Pool params.Pool
|
||||
Instances []params.Instance
|
||||
CreateInstanceParams params.CreateInstanceParams
|
||||
UpdateInstanceParams params.UpdateInstanceParams
|
||||
SQLMock sqlmock.Sqlmock
|
||||
}
|
||||
|
||||
type InstancesTestSuite struct {
|
||||
suite.Suite
|
||||
Store dbCommon.Store
|
||||
Fixtures *InstancesTestFixtures
|
||||
Store dbCommon.Store
|
||||
StoreSQLMocked *sqlDatabase
|
||||
Fixtures *InstancesTestFixtures
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) equalInstancesByName(expected, actual []params.Instance) {
|
||||
|
|
@ -50,6 +61,13 @@ func (s *InstancesTestSuite) equalInstancesByName(expected, actual []params.Inst
|
|||
}
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) assertSQLMockExpectations() {
|
||||
err := s.Fixtures.SQLMock.ExpectationsWereMet()
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to meet sqlmock expectations, got error: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) SetupTest() {
|
||||
// create testing sqlite database
|
||||
db, err := NewSQLDatabase(context.Background(), garmTesting.GetTestSqliteDBConfig(s.T()))
|
||||
|
|
@ -100,31 +118,70 @@ func (s *InstancesTestSuite) SetupTest() {
|
|||
instances = append(instances, instance)
|
||||
}
|
||||
|
||||
// create store with mocked sql connection
|
||||
sqlDB, sqlMock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to run 'sqlmock.New()', got error: %v", err))
|
||||
}
|
||||
s.T().Cleanup(func() { sqlDB.Close() })
|
||||
mysqlConfig := mysql.Config{
|
||||
Conn: sqlDB,
|
||||
SkipInitializeWithVersion: true,
|
||||
}
|
||||
gormConfig := &gorm.Config{}
|
||||
if flag.Lookup("test.v").Value.String() == "false" {
|
||||
gormConfig.Logger = logger.Default.LogMode(logger.Silent)
|
||||
}
|
||||
gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("fail to open gorm connection: %v", err))
|
||||
}
|
||||
s.StoreSQLMocked = &sqlDatabase{
|
||||
conn: gormConn,
|
||||
}
|
||||
|
||||
// setup test fixtures
|
||||
fixtures := &InstancesTestFixtures{
|
||||
Org: org,
|
||||
Pool: pool,
|
||||
Instances: instances,
|
||||
CreateInstanceParams: params.CreateInstanceParams{
|
||||
Name: "test-create-instance",
|
||||
OSType: "linux",
|
||||
OSArch: "amd64",
|
||||
CallbackURL: "https://garm.example.com/",
|
||||
},
|
||||
UpdateInstanceParams: params.UpdateInstanceParams{
|
||||
ProviderID: "update-provider-test",
|
||||
OSName: "ubuntu",
|
||||
OSVersion: "focal",
|
||||
Status: common.InstancePendingDelete,
|
||||
RunnerStatus: common.RunnerActive,
|
||||
AgentID: 4,
|
||||
CreateAttempt: 3,
|
||||
Addresses: []params.Address{
|
||||
{
|
||||
Address: "12.10.12.10",
|
||||
Type: params.PublicAddress,
|
||||
},
|
||||
{
|
||||
Address: "10.1.1.2",
|
||||
Type: params.PrivateAddress,
|
||||
},
|
||||
},
|
||||
},
|
||||
SQLMock: sqlMock,
|
||||
}
|
||||
s.Fixtures = fixtures
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestCreateInstance() {
|
||||
// setup enviroment for this test
|
||||
instanceName := "test-create-instance"
|
||||
createInstanceParams := params.CreateInstanceParams{
|
||||
Name: instanceName,
|
||||
OSType: "linux",
|
||||
OSArch: "amd64",
|
||||
CallbackURL: "https://garm.example.com/",
|
||||
}
|
||||
|
||||
// call tested function
|
||||
instance, err := s.Store.CreateInstance(context.Background(), s.Fixtures.Pool.ID, createInstanceParams)
|
||||
instance, err := s.Store.CreateInstance(context.Background(), s.Fixtures.Pool.ID, s.Fixtures.CreateInstanceParams)
|
||||
|
||||
// assertions
|
||||
s.Require().Nil(err)
|
||||
storeInstance, err := s.Store.GetInstanceByName(context.Background(), instanceName)
|
||||
storeInstance, err := s.Store.GetInstanceByName(context.Background(), s.Fixtures.CreateInstanceParams.Name)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to get instance: %v", err))
|
||||
}
|
||||
|
|
@ -141,6 +198,29 @@ func (s *InstancesTestSuite) TestCreateInstanceInvalidPoolID() {
|
|||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestCreateInstanceDBCreateErr() {
|
||||
pool := s.Fixtures.Pool
|
||||
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
|
||||
WithArgs(pool.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pool.ID))
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec("INSERT INTO `pools`").
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec("INSERT INTO `instances`").
|
||||
WillReturnError(fmt.Errorf("mocked insert instance error"))
|
||||
s.Fixtures.SQLMock.ExpectRollback()
|
||||
|
||||
_, err := s.StoreSQLMocked.CreateInstance(context.Background(), pool.ID, s.Fixtures.CreateInstanceParams)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("creating instance: mocked insert instance error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestGetPoolInstanceByName() {
|
||||
storeInstance := s.Fixtures.Instances[0] // this is already created in `SetupTest()`
|
||||
|
||||
|
|
@ -181,6 +261,7 @@ func (s *InstancesTestSuite) TestGetInstanceByNameFetchInstanceFailed() {
|
|||
|
||||
func (s *InstancesTestSuite) TestDeleteInstance() {
|
||||
storeInstance := s.Fixtures.Instances[0]
|
||||
|
||||
err := s.Store.DeleteInstance(context.Background(), s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
|
||||
s.Require().Nil(err)
|
||||
|
|
@ -195,6 +276,73 @@ func (s *InstancesTestSuite) TestDeleteInstanceInvalidPoolID() {
|
|||
s.Require().Equal("deleting instance: fetching pool: parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestDeleteInstanceDBRecordNotFoundErr() {
|
||||
pool := s.Fixtures.Pool
|
||||
instance := s.Fixtures.Instances[0]
|
||||
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
|
||||
WithArgs(pool.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pool.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instances` WHERE (name = ? and pool_id = ?) AND `instances`.`deleted_at` IS NULL ORDER BY `instances`.`id` LIMIT 1")).
|
||||
WithArgs(instance.Name, pool.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `addresses` WHERE `addresses`.`instance_id` = ? AND `addresses`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"address", "type", "instance_id"}).AddRow("10.10.1.10", "private", instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instance_status_updates` WHERE `instance_status_updates`.`instance_id` = ? AND `instance_status_updates`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"message", "instance_id"}).AddRow("instance sample message", instance.ID))
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("DELETE FROM `instances` WHERE `instances`.`id` = ?")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnError(gorm.ErrRecordNotFound)
|
||||
s.Fixtures.SQLMock.ExpectRollback()
|
||||
|
||||
err := s.StoreSQLMocked.DeleteInstance(context.Background(), pool.ID, instance.Name)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().Nil(err)
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestDeleteInstanceDBDeleteErr() {
|
||||
pool := s.Fixtures.Pool
|
||||
instance := s.Fixtures.Instances[0]
|
||||
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
|
||||
WithArgs(pool.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pool.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instances` WHERE (name = ? and pool_id = ?) AND `instances`.`deleted_at` IS NULL ORDER BY `instances`.`id` LIMIT 1")).
|
||||
WithArgs(instance.Name, pool.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `addresses` WHERE `addresses`.`instance_id` = ? AND `addresses`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"address", "type", "instance_id"}).AddRow("12.10.12.13", "public", instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instance_status_updates` WHERE `instance_status_updates`.`instance_id` = ? AND `instance_status_updates`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"message", "instance_id"}).AddRow("instance sample message", instance.ID))
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("DELETE FROM `instances` WHERE `instances`.`id` = ?")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnError(fmt.Errorf("mocked delete instance error"))
|
||||
s.Fixtures.SQLMock.ExpectRollback()
|
||||
|
||||
err := s.StoreSQLMocked.DeleteInstance(context.Background(), pool.ID, instance.Name)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("deleting instance: mocked delete instance error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestAddInstanceStatusMessage() {
|
||||
storeInstance := s.Fixtures.Instances[0]
|
||||
statusMsg := "test-status-message"
|
||||
|
|
@ -216,37 +364,50 @@ func (s *InstancesTestSuite) TestAddInstanceStatusMessageInvalidPoolID() {
|
|||
s.Require().Equal("updating instance: parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestUpdateInstance() {
|
||||
updateInstanceParams := params.UpdateInstanceParams{
|
||||
ProviderID: "update-provider-test",
|
||||
OSName: "ubuntu",
|
||||
OSVersion: "focal",
|
||||
Status: common.InstancePendingDelete,
|
||||
RunnerStatus: common.RunnerActive,
|
||||
AgentID: 4,
|
||||
CreateAttempt: 3,
|
||||
Addresses: []params.Address{
|
||||
{
|
||||
Address: "12.10.12.10",
|
||||
Type: params.PublicAddress,
|
||||
},
|
||||
{
|
||||
Address: "10.1.1.2",
|
||||
Type: params.PrivateAddress,
|
||||
},
|
||||
},
|
||||
}
|
||||
func (s *InstancesTestSuite) TestAddInstanceStatusMessageDBUpdateErr() {
|
||||
instance := s.Fixtures.Instances[0]
|
||||
statusMsg := "test-status-message"
|
||||
|
||||
instance, err := s.Store.UpdateInstance(context.Background(), s.Fixtures.Instances[0].ID, updateInstanceParams)
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instances` WHERE id = ? AND `instances`.`deleted_at` IS NULL ORDER BY `instances`.`id` LIMIT 1")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `addresses` WHERE `addresses`.`instance_id` = ? AND `addresses`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"address", "type", "instance_id"}).AddRow("10.10.1.10", "private", instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instance_status_updates` WHERE `instance_status_updates`.`instance_id` = ? AND `instance_status_updates`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"message", "instance_id"}).AddRow("instance sample message", instance.ID))
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("UPDATE `instances` SET `updated_at`=? WHERE `instances`.`deleted_at` IS NULL AND `id` = ?")).
|
||||
WithArgs(sqlmock.AnyArg(), instance.ID).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("INSERT INTO `instance_status_updates`")).
|
||||
WillReturnError(fmt.Errorf("mocked add status message error"))
|
||||
s.Fixtures.SQLMock.ExpectRollback()
|
||||
|
||||
err := s.StoreSQLMocked.AddInstanceStatusMessage(context.Background(), instance.ID, statusMsg)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("adding status message: mocked add status message error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestUpdateInstance() {
|
||||
instance, err := s.Store.UpdateInstance(context.Background(), s.Fixtures.Instances[0].ID, s.Fixtures.UpdateInstanceParams)
|
||||
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(updateInstanceParams.ProviderID, instance.ProviderID)
|
||||
s.Require().Equal(updateInstanceParams.OSName, instance.OSName)
|
||||
s.Require().Equal(updateInstanceParams.OSVersion, instance.OSVersion)
|
||||
s.Require().Equal(updateInstanceParams.Status, instance.Status)
|
||||
s.Require().Equal(updateInstanceParams.RunnerStatus, instance.RunnerStatus)
|
||||
s.Require().Equal(updateInstanceParams.AgentID, instance.AgentID)
|
||||
s.Require().Equal(updateInstanceParams.CreateAttempt, instance.CreateAttempt)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.ProviderID, instance.ProviderID)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.OSName, instance.OSName)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.OSVersion, instance.OSVersion)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.Status, instance.Status)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.RunnerStatus, instance.RunnerStatus)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.AgentID, instance.AgentID)
|
||||
s.Require().Equal(s.Fixtures.UpdateInstanceParams.CreateAttempt, instance.CreateAttempt)
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestUpdateInstanceInvalidPoolID() {
|
||||
|
|
@ -255,6 +416,76 @@ func (s *InstancesTestSuite) TestUpdateInstanceInvalidPoolID() {
|
|||
s.Require().Equal("updating instance: parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestUpdateInstanceDBUpdateInstanceErr() {
|
||||
instance := s.Fixtures.Instances[0]
|
||||
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instances` WHERE id = ? AND `instances`.`deleted_at` IS NULL ORDER BY `instances`.`id` LIMIT 1")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `addresses` WHERE `addresses`.`instance_id` = ? AND `addresses`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"address", "type", "instance_id"}).AddRow("10.10.1.10", "private", instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instance_status_updates` WHERE `instance_status_updates`.`instance_id` = ? AND `instance_status_updates`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"message", "instance_id"}).AddRow("instance sample message", instance.ID))
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(("UPDATE `instances`")).
|
||||
WillReturnError(fmt.Errorf("mocked update instance error"))
|
||||
s.Fixtures.SQLMock.ExpectRollback()
|
||||
|
||||
_, err := s.StoreSQLMocked.UpdateInstance(context.Background(), instance.ID, s.Fixtures.UpdateInstanceParams)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating instance: mocked update instance error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestUpdateInstanceDBUpdateAddressErr() {
|
||||
instance := s.Fixtures.Instances[0]
|
||||
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instances` WHERE id = ? AND `instances`.`deleted_at` IS NULL ORDER BY `instances`.`id` LIMIT 1")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `addresses` WHERE `addresses`.`instance_id` = ? AND `addresses`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"address", "type", "instance_id"}).AddRow("10.10.1.10", "private", instance.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instance_status_updates` WHERE `instance_status_updates`.`instance_id` = ? AND `instance_status_updates`.`deleted_at` IS NULL")).
|
||||
WithArgs(instance.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"message", "instance_id"}).AddRow("instance sample message", instance.ID))
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("UPDATE `instances` SET")).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("INSERT INTO `addresses`")).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("INSERT INTO `instance_status_updates`")).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
s.Fixtures.SQLMock.ExpectCommit()
|
||||
s.Fixtures.SQLMock.ExpectBegin()
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("UPDATE `instances` SET")).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectExec(regexp.QuoteMeta("INSERT INTO `addresses`")).
|
||||
WillReturnError(fmt.Errorf("update addresses mock error"))
|
||||
s.Fixtures.SQLMock.ExpectRollback()
|
||||
|
||||
_, err := s.StoreSQLMocked.UpdateInstance(context.Background(), instance.ID, s.Fixtures.UpdateInstanceParams)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("updating addresses: update addresses mock error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestListPoolInstances() {
|
||||
instances, err := s.Store.ListPoolInstances(context.Background(), s.Fixtures.Pool.ID)
|
||||
|
||||
|
|
@ -275,6 +506,18 @@ func (s *InstancesTestSuite) TestListAllInstances() {
|
|||
s.equalInstancesByName(s.Fixtures.Instances, instances)
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestListAllInstancesDBFetchErr() {
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `instances` WHERE `instances`.`deleted_at` IS NULL")).
|
||||
WillReturnError(fmt.Errorf("fetch instances mock error"))
|
||||
|
||||
_, err := s.StoreSQLMocked.ListAllInstances(context.Background())
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching instances: fetch instances mock error", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestPoolInstanceCount() {
|
||||
instancesCount, err := s.Store.PoolInstanceCount(context.Background(), s.Fixtures.Pool.ID)
|
||||
|
||||
|
|
@ -288,6 +531,25 @@ func (s *InstancesTestSuite) TestPoolInstanceCountInvalidPoolID() {
|
|||
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestPoolInstanceCountDBCountErr() {
|
||||
pool := s.Fixtures.Pool
|
||||
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
|
||||
WithArgs(pool.ID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pool.ID))
|
||||
s.Fixtures.SQLMock.
|
||||
ExpectQuery(regexp.QuoteMeta("SELECT count(*) FROM `instances` WHERE pool_id = ? AND `instances`.`deleted_at` IS NULL")).
|
||||
WithArgs(pool.ID).
|
||||
WillReturnError(fmt.Errorf("count mock error"))
|
||||
|
||||
_, err := s.StoreSQLMocked.PoolInstanceCount(context.Background(), pool.ID)
|
||||
|
||||
s.assertSQLMockExpectations()
|
||||
s.Require().NotNil(err)
|
||||
s.Require().Equal("fetching instance count: count mock error", err.Error())
|
||||
}
|
||||
|
||||
func TestInstTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(InstancesTestSuite))
|
||||
}
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -28,6 +28,7 @@ require (
|
|||
gorm.io/driver/mysql v1.3.3
|
||||
gorm.io/driver/sqlite v1.3.2
|
||||
gorm.io/gorm v1.23.4
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -519,6 +519,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY=
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
|||
3
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/.gitignore
generated
vendored
Normal file
3
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/examples/blog/blog
|
||||
/examples/orders/orders
|
||||
/examples/basic/basic
|
||||
19
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/.travis.yml
generated
vendored
Normal file
19
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.2.x
|
||||
- 1.3.x
|
||||
- 1.4 # has no cover tool for latest releases
|
||||
- 1.5.x
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
# - tip # sadly fails most of the times
|
||||
|
||||
script:
|
||||
- go vet
|
||||
- test -z "$(go fmt ./...)" # fail if not formatted properly
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
28
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/LICENSE
generated
vendored
Normal file
28
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
The three clause BSD license (http://en.wikipedia.org/wiki/BSD_licenses)
|
||||
|
||||
Copyright (c) 2013-2017, DATA-DOG team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* The name DataDog.lt may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
229
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/README.md
generated
vendored
Normal file
229
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
[](https://travis-ci.org/DATA-DOG/go-sqlmock)
|
||||
[](https://godoc.org/github.com/DATA-DOG/go-sqlmock)
|
||||
[](https://codecov.io/github/DATA-DOG/go-sqlmock)
|
||||
|
||||
# Sql driver mock for Golang
|
||||
|
||||
**sqlmock** is a mock library implementing [sql/driver](https://godoc.org/database/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.
|
||||
|
||||
- this library is now complete and stable. (you may not find new changes for this reason)
|
||||
- supports concurrency and multiple connections.
|
||||
- supports **go1.8** Context related feature mocking and Named sql parameters.
|
||||
- does not require any modifications to your source code.
|
||||
- the driver allows to mock any sql driver method behavior.
|
||||
- has strict by default expectation order matching.
|
||||
- has no third party dependencies.
|
||||
|
||||
**NOTE:** in **v1.2.0** **sqlmock.Rows** has changed to struct from interface, if you were using any type references to that
|
||||
interface, you will need to switch it to a pointer struct type. Also, **sqlmock.Rows** were used to implement **driver.Rows**
|
||||
interface, which was not required or useful for mocking and was removed. Hope it will not cause issues.
|
||||
|
||||
## Install
|
||||
|
||||
go get gopkg.in/DATA-DOG/go-sqlmock.v1
|
||||
|
||||
## Documentation and Examples
|
||||
|
||||
Visit [godoc](http://godoc.org/github.com/DATA-DOG/go-sqlmock) for general examples and public api reference.
|
||||
See **.travis.yml** for supported **go** versions.
|
||||
Different use case, is to functionally test with a real database - [go-txdb](https://github.com/DATA-DOG/go-txdb)
|
||||
all database related actions are isolated within a single transaction so the database can remain in the same state.
|
||||
|
||||
See implementation examples:
|
||||
|
||||
- [blog API server](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/blog)
|
||||
- [the same orders example](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/orders)
|
||||
|
||||
### Something you may want to test
|
||||
|
||||
``` go
|
||||
package main
|
||||
|
||||
import "database/sql"
|
||||
|
||||
func recordStats(db *sql.DB, userID, productID int64) (err error) {
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
switch err {
|
||||
case nil:
|
||||
err = tx.Commit()
|
||||
default:
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
// @NOTE: the real connection is not required for tests
|
||||
db, err := sql.Open("mysql", "root@/blog")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Tests with sqlmock
|
||||
|
||||
``` go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/DATA-DOG/go-sqlmock.v1"
|
||||
)
|
||||
|
||||
// a successful case
|
||||
func TestShouldUpdateStats(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectCommit()
|
||||
|
||||
// now we execute our method
|
||||
if err = recordStats(db, 2, 3); err != nil {
|
||||
t.Errorf("error was not expected while updating stats: %s", err)
|
||||
}
|
||||
|
||||
// we make sure that all expectations were met
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("there were unfulfilled expections: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// a failing test case
|
||||
func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectExec("INSERT INTO product_viewers").
|
||||
WithArgs(2, 3).
|
||||
WillReturnError(fmt.Errorf("some error"))
|
||||
mock.ExpectRollback()
|
||||
|
||||
// now we execute our method
|
||||
if err = recordStats(db, 2, 3); err == nil {
|
||||
t.Errorf("was expecting an error, but there was none")
|
||||
}
|
||||
|
||||
// we make sure that all expectations were met
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("there were unfulfilled expections: %s", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Matching arguments like time.Time
|
||||
|
||||
There may be arguments which are of `struct` type and cannot be compared easily by value like `time.Time`. In this case
|
||||
**sqlmock** provides an [Argument](https://godoc.org/github.com/DATA-DOG/go-sqlmock#Argument) interface which
|
||||
can be used in more sophisticated matching. Here is a simple example of time argument matching:
|
||||
|
||||
``` go
|
||||
type AnyTime struct{}
|
||||
|
||||
// Match satisfies sqlmock.Argument interface
|
||||
func (a AnyTime) Match(v driver.Value) bool {
|
||||
_, ok := v.(time.Time)
|
||||
return ok
|
||||
}
|
||||
|
||||
func TestAnyTimeArgument(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 users").
|
||||
WithArgs("john", AnyTime{}).
|
||||
WillReturnResult(NewResult(1, 1))
|
||||
|
||||
_, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
|
||||
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)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It only asserts that argument is of `time.Time` type.
|
||||
|
||||
## Run tests
|
||||
|
||||
go test -race
|
||||
|
||||
## Change Log
|
||||
|
||||
- **2017-09-01** - it is now possible to expect that prepared statement will be closed,
|
||||
using **ExpectedPrepare.WillBeClosed**.
|
||||
- **2017-02-09** - implemented support for **go1.8** features. **Rows** interface was changed to struct
|
||||
but contains all methods as before and should maintain backwards compatibility. **ExpectedQuery.WillReturnRows** may now
|
||||
accept multiple row sets.
|
||||
- **2016-11-02** - `db.Prepare()` was not validating expected prepare SQL
|
||||
query. It should still be validated even if Exec or Query is not
|
||||
executed on that prepared statement.
|
||||
- **2016-02-23** - added **sqlmock.AnyArg()** function to provide any kind
|
||||
of argument matcher.
|
||||
- **2016-02-23** - convert expected arguments to driver.Value as natural
|
||||
driver does, the change may affect time.Time comparison and will be
|
||||
stricter. See [issue](https://github.com/DATA-DOG/go-sqlmock/issues/31).
|
||||
- **2015-08-27** - **v1** api change, concurrency support, all known issues fixed.
|
||||
- **2014-08-16** instead of **panic** during reflect type mismatch when comparing query arguments - now return error
|
||||
- **2014-08-14** added **sqlmock.NewErrorResult** which gives an option to return driver.Result with errors for
|
||||
interface methods, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/5)
|
||||
- **2014-05-29** allow to match arguments in more sophisticated ways, by providing an **sqlmock.Argument** interface
|
||||
- **2014-04-21** introduce **sqlmock.New()** to open a mock database connection for tests. This method
|
||||
calls sql.DB.Ping to ensure that connection is open, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/4).
|
||||
This way on Close it will surely assert if all expectations are met, even if database was not triggered at all.
|
||||
The old way is still available, but it is advisable to call db.Ping manually before asserting with db.Close.
|
||||
- **2014-02-14** RowsFromCSVString is now a part of Rows interface named as FromCSVString.
|
||||
It has changed to allow more ways to construct rows and to easily extend this API in future.
|
||||
See [issue 1](https://github.com/DATA-DOG/go-sqlmock/issues/1)
|
||||
**RowsFromCSVString** is deprecated and will be removed in future
|
||||
|
||||
## Contributions
|
||||
|
||||
Feel free to open a pull request. Note, if you wish to contribute an extension to public (exported methods or types) -
|
||||
please open an issue before, to discuss whether these changes can be accepted. All backward incompatible changes are
|
||||
and will be treated cautiously
|
||||
|
||||
## License
|
||||
|
||||
The [three clause BSD license](http://en.wikipedia.org/wiki/BSD_licenses)
|
||||
|
||||
24
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/argument.go
generated
vendored
Normal file
24
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/argument.go
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package sqlmock
|
||||
|
||||
import "database/sql/driver"
|
||||
|
||||
// Argument interface allows to match
|
||||
// any argument in specific way when used with
|
||||
// ExpectedQuery and ExpectedExec expectations.
|
||||
type Argument interface {
|
||||
Match(driver.Value) bool
|
||||
}
|
||||
|
||||
// AnyArg will return an Argument which can
|
||||
// match any kind of arguments.
|
||||
//
|
||||
// Useful for time.Time or similar kinds of arguments.
|
||||
func AnyArg() Argument {
|
||||
return anyArgument{}
|
||||
}
|
||||
|
||||
type anyArgument struct{}
|
||||
|
||||
func (a anyArgument) Match(_ driver.Value) bool {
|
||||
return true
|
||||
}
|
||||
78
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/driver.go
generated
vendored
Normal file
78
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/driver.go
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package sqlmock
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var pool *mockDriver
|
||||
|
||||
func init() {
|
||||
pool = &mockDriver{
|
||||
conns: make(map[string]*sqlmock),
|
||||
}
|
||||
sql.Register("sqlmock", pool)
|
||||
}
|
||||
|
||||
type mockDriver struct {
|
||||
sync.Mutex
|
||||
counter int
|
||||
conns map[string]*sqlmock
|
||||
}
|
||||
|
||||
func (d *mockDriver) Open(dsn string) (driver.Conn, error) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
c, ok := d.conns[dsn]
|
||||
if !ok {
|
||||
return c, fmt.Errorf("expected a connection to be available, but it is not")
|
||||
}
|
||||
|
||||
c.opened++
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// New creates sqlmock database connection
|
||||
// and a mock to manage expectations.
|
||||
// Pings db so that all expectations could be
|
||||
// asserted.
|
||||
func New() (*sql.DB, Sqlmock, error) {
|
||||
pool.Lock()
|
||||
dsn := fmt.Sprintf("sqlmock_db_%d", pool.counter)
|
||||
pool.counter++
|
||||
|
||||
smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
|
||||
pool.conns[dsn] = smock
|
||||
pool.Unlock()
|
||||
|
||||
return smock.open()
|
||||
}
|
||||
|
||||
// NewWithDSN creates sqlmock database connection
|
||||
// with a specific DSN and a mock to manage expectations.
|
||||
// Pings db so that all expectations could be asserted.
|
||||
//
|
||||
// This method is introduced because of sql abstraction
|
||||
// libraries, which do not provide a way to initialize
|
||||
// with sql.DB instance. For example GORM library.
|
||||
//
|
||||
// Note, it will error if attempted to create with an
|
||||
// already used dsn
|
||||
//
|
||||
// It is not recommended to use this method, unless you
|
||||
// really need it and there is no other way around.
|
||||
func NewWithDSN(dsn string) (*sql.DB, Sqlmock, error) {
|
||||
pool.Lock()
|
||||
if _, ok := pool.conns[dsn]; ok {
|
||||
pool.Unlock()
|
||||
return nil, nil, fmt.Errorf("cannot create a new mock database with the same dsn: %s", dsn)
|
||||
}
|
||||
smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
|
||||
pool.conns[dsn] = smock
|
||||
pool.Unlock()
|
||||
|
||||
return smock.open()
|
||||
}
|
||||
353
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations.go
generated
vendored
Normal file
353
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations.go
generated
vendored
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
package sqlmock
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// an expectation interface
|
||||
type expectation interface {
|
||||
fulfilled() bool
|
||||
Lock()
|
||||
Unlock()
|
||||
String() string
|
||||
}
|
||||
|
||||
// common expectation struct
|
||||
// satisfies the expectation interface
|
||||
type commonExpectation struct {
|
||||
sync.Mutex
|
||||
triggered bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *commonExpectation) fulfilled() bool {
|
||||
return e.triggered
|
||||
}
|
||||
|
||||
// ExpectedClose is used to manage *sql.DB.Close expectation
|
||||
// returned by *Sqlmock.ExpectClose.
|
||||
type ExpectedClose struct {
|
||||
commonExpectation
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for *sql.DB.Close action
|
||||
func (e *ExpectedClose) WillReturnError(err error) *ExpectedClose {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedClose) String() string {
|
||||
msg := "ExpectedClose => expecting database Close"
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf(", which should return error: %s", e.err)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// ExpectedBegin is used to manage *sql.DB.Begin expectation
|
||||
// returned by *Sqlmock.ExpectBegin.
|
||||
type ExpectedBegin struct {
|
||||
commonExpectation
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for *sql.DB.Begin action
|
||||
func (e *ExpectedBegin) WillReturnError(err error) *ExpectedBegin {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedBegin) String() string {
|
||||
msg := "ExpectedBegin => expecting database transaction Begin"
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf(", which should return error: %s", e.err)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// WillDelayFor allows to specify duration for which it will delay
|
||||
// result. May be used together with Context
|
||||
func (e *ExpectedBegin) WillDelayFor(duration time.Duration) *ExpectedBegin {
|
||||
e.delay = duration
|
||||
return e
|
||||
}
|
||||
|
||||
// ExpectedCommit is used to manage *sql.Tx.Commit expectation
|
||||
// returned by *Sqlmock.ExpectCommit.
|
||||
type ExpectedCommit struct {
|
||||
commonExpectation
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for *sql.Tx.Close action
|
||||
func (e *ExpectedCommit) WillReturnError(err error) *ExpectedCommit {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedCommit) String() string {
|
||||
msg := "ExpectedCommit => expecting transaction Commit"
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf(", which should return error: %s", e.err)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// ExpectedRollback is used to manage *sql.Tx.Rollback expectation
|
||||
// returned by *Sqlmock.ExpectRollback.
|
||||
type ExpectedRollback struct {
|
||||
commonExpectation
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for *sql.Tx.Rollback action
|
||||
func (e *ExpectedRollback) WillReturnError(err error) *ExpectedRollback {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedRollback) String() string {
|
||||
msg := "ExpectedRollback => expecting transaction Rollback"
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf(", which should return error: %s", e.err)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// ExpectedQuery is used to manage *sql.DB.Query, *dql.DB.QueryRow, *sql.Tx.Query,
|
||||
// *sql.Tx.QueryRow, *sql.Stmt.Query or *sql.Stmt.QueryRow expectations.
|
||||
// Returned by *Sqlmock.ExpectQuery.
|
||||
type ExpectedQuery struct {
|
||||
queryBasedExpectation
|
||||
rows driver.Rows
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
// WithArgs will match given expected args to actual database query arguments.
|
||||
// if at least one argument does not match, it will return an error. For specific
|
||||
// arguments an sqlmock.Argument interface can be used to match an argument.
|
||||
func (e *ExpectedQuery) WithArgs(args ...driver.Value) *ExpectedQuery {
|
||||
e.args = args
|
||||
return e
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for expected database query
|
||||
func (e *ExpectedQuery) WillReturnError(err error) *ExpectedQuery {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// WillDelayFor allows to specify duration for which it will delay
|
||||
// result. May be used together with Context
|
||||
func (e *ExpectedQuery) WillDelayFor(duration time.Duration) *ExpectedQuery {
|
||||
e.delay = duration
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedQuery) String() string {
|
||||
msg := "ExpectedQuery => expecting Query, QueryContext or QueryRow which:"
|
||||
msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
|
||||
|
||||
if len(e.args) == 0 {
|
||||
msg += "\n - is without arguments"
|
||||
} else {
|
||||
msg += "\n - is with arguments:\n"
|
||||
for i, arg := range e.args {
|
||||
msg += fmt.Sprintf(" %d - %+v\n", i, arg)
|
||||
}
|
||||
msg = strings.TrimSpace(msg)
|
||||
}
|
||||
|
||||
if e.rows != nil {
|
||||
msg += fmt.Sprintf("\n - %s", e.rows)
|
||||
}
|
||||
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf("\n - should return error: %s", e.err)
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
// ExpectedExec is used to manage *sql.DB.Exec, *sql.Tx.Exec or *sql.Stmt.Exec expectations.
|
||||
// Returned by *Sqlmock.ExpectExec.
|
||||
type ExpectedExec struct {
|
||||
queryBasedExpectation
|
||||
result driver.Result
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
// WithArgs will match given expected args to actual database exec operation arguments.
|
||||
// if at least one argument does not match, it will return an error. For specific
|
||||
// arguments an sqlmock.Argument interface can be used to match an argument.
|
||||
func (e *ExpectedExec) WithArgs(args ...driver.Value) *ExpectedExec {
|
||||
e.args = args
|
||||
return e
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for expected database exec action
|
||||
func (e *ExpectedExec) WillReturnError(err error) *ExpectedExec {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// WillDelayFor allows to specify duration for which it will delay
|
||||
// result. May be used together with Context
|
||||
func (e *ExpectedExec) WillDelayFor(duration time.Duration) *ExpectedExec {
|
||||
e.delay = duration
|
||||
return e
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedExec) String() string {
|
||||
msg := "ExpectedExec => expecting Exec or ExecContext which:"
|
||||
msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
|
||||
|
||||
if len(e.args) == 0 {
|
||||
msg += "\n - is without arguments"
|
||||
} else {
|
||||
msg += "\n - is with arguments:\n"
|
||||
var margs []string
|
||||
for i, arg := range e.args {
|
||||
margs = append(margs, fmt.Sprintf(" %d - %+v", i, arg))
|
||||
}
|
||||
msg += strings.Join(margs, "\n")
|
||||
}
|
||||
|
||||
if e.result != nil {
|
||||
res, _ := e.result.(*result)
|
||||
msg += "\n - should return Result having:"
|
||||
msg += fmt.Sprintf("\n LastInsertId: %d", res.insertID)
|
||||
msg += fmt.Sprintf("\n RowsAffected: %d", res.rowsAffected)
|
||||
if res.err != nil {
|
||||
msg += fmt.Sprintf("\n Error: %s", res.err)
|
||||
}
|
||||
}
|
||||
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf("\n - should return error: %s", e.err)
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
// WillReturnResult arranges for an expected Exec() to return a particular
|
||||
// result, there is sqlmock.NewResult(lastInsertID int64, affectedRows int64) method
|
||||
// to build a corresponding result. Or if actions needs to be tested against errors
|
||||
// sqlmock.NewErrorResult(err error) to return a given error.
|
||||
func (e *ExpectedExec) WillReturnResult(result driver.Result) *ExpectedExec {
|
||||
e.result = result
|
||||
return e
|
||||
}
|
||||
|
||||
// ExpectedPrepare is used to manage *sql.DB.Prepare or *sql.Tx.Prepare expectations.
|
||||
// Returned by *Sqlmock.ExpectPrepare.
|
||||
type ExpectedPrepare struct {
|
||||
commonExpectation
|
||||
mock *sqlmock
|
||||
sqlRegex *regexp.Regexp
|
||||
statement driver.Stmt
|
||||
closeErr error
|
||||
mustBeClosed bool
|
||||
wasClosed bool
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
// WillReturnError allows to set an error for the expected *sql.DB.Prepare or *sql.Tx.Prepare action.
|
||||
func (e *ExpectedPrepare) WillReturnError(err error) *ExpectedPrepare {
|
||||
e.err = err
|
||||
return e
|
||||
}
|
||||
|
||||
// WillReturnCloseError allows to set an error for this prepared statement Close action
|
||||
func (e *ExpectedPrepare) WillReturnCloseError(err error) *ExpectedPrepare {
|
||||
e.closeErr = err
|
||||
return e
|
||||
}
|
||||
|
||||
// WillDelayFor allows to specify duration for which it will delay
|
||||
// result. May be used together with Context
|
||||
func (e *ExpectedPrepare) WillDelayFor(duration time.Duration) *ExpectedPrepare {
|
||||
e.delay = duration
|
||||
return e
|
||||
}
|
||||
|
||||
// WillBeClosed expects this prepared statement to
|
||||
// be closed.
|
||||
func (e *ExpectedPrepare) WillBeClosed() *ExpectedPrepare {
|
||||
e.mustBeClosed = true
|
||||
return e
|
||||
}
|
||||
|
||||
// ExpectQuery allows to expect Query() or QueryRow() on this prepared statement.
|
||||
// this method is convenient in order to prevent duplicating sql query string matching.
|
||||
func (e *ExpectedPrepare) ExpectQuery() *ExpectedQuery {
|
||||
eq := &ExpectedQuery{}
|
||||
eq.sqlRegex = e.sqlRegex
|
||||
e.mock.expected = append(e.mock.expected, eq)
|
||||
return eq
|
||||
}
|
||||
|
||||
// ExpectExec allows to expect Exec() on this prepared statement.
|
||||
// this method is convenient in order to prevent duplicating sql query string matching.
|
||||
func (e *ExpectedPrepare) ExpectExec() *ExpectedExec {
|
||||
eq := &ExpectedExec{}
|
||||
eq.sqlRegex = e.sqlRegex
|
||||
e.mock.expected = append(e.mock.expected, eq)
|
||||
return eq
|
||||
}
|
||||
|
||||
// String returns string representation
|
||||
func (e *ExpectedPrepare) String() string {
|
||||
msg := "ExpectedPrepare => expecting Prepare statement which:"
|
||||
msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
|
||||
|
||||
if e.err != nil {
|
||||
msg += fmt.Sprintf("\n - should return error: %s", e.err)
|
||||
}
|
||||
|
||||
if e.closeErr != nil {
|
||||
msg += fmt.Sprintf("\n - should return error on Close: %s", e.closeErr)
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
// query based expectation
|
||||
// adds a query matching logic
|
||||
type queryBasedExpectation struct {
|
||||
commonExpectation
|
||||
sqlRegex *regexp.Regexp
|
||||
args []driver.Value
|
||||
}
|
||||
|
||||
func (e *queryBasedExpectation) attemptMatch(sql string, args []namedValue) (err error) {
|
||||
if !e.queryMatches(sql) {
|
||||
return fmt.Errorf(`could not match sql: "%s" with expected regexp "%s"`, sql, e.sqlRegex.String())
|
||||
}
|
||||
|
||||
// catch panic
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
_, ok := e.(error)
|
||||
if !ok {
|
||||
err = fmt.Errorf(e.(string))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = e.argsMatches(args)
|
||||
return
|
||||
}
|
||||
|
||||
func (e *queryBasedExpectation) queryMatches(sql string) bool {
|
||||
return e.sqlRegex.MatchString(sql)
|
||||
}
|
||||
52
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_before_go18.go
generated
vendored
Normal file
52
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_before_go18.go
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// +build !go1.8
|
||||
|
||||
package sqlmock
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// WillReturnRows specifies the set of resulting rows that will be returned
|
||||
// by the triggered query
|
||||
func (e *ExpectedQuery) WillReturnRows(rows *Rows) *ExpectedQuery {
|
||||
e.rows = &rowSets{sets: []*Rows{rows}}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
|
||||
if nil == e.args {
|
||||
return nil
|
||||
}
|
||||
if len(args) != len(e.args) {
|
||||
return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
|
||||
}
|
||||
for k, v := range args {
|
||||
// custom argument matcher
|
||||
matcher, ok := e.args[k].(Argument)
|
||||
if ok {
|
||||
// @TODO: does it make sense to pass value instead of named value?
|
||||
if !matcher.Match(v.Value) {
|
||||
return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
dval := e.args[k]
|
||||
// convert to driver converter
|
||||
darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
|
||||
}
|
||||
|
||||
if !driver.IsValue(darg) {
|
||||
return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(darg, v.Value) {
|
||||
return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
66
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18.go
generated
vendored
Normal file
66
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/expectations_go18.go
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// +build go1.8
|
||||
|
||||
package sqlmock
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// WillReturnRows specifies the set of resulting rows that will be returned
|
||||
// by the triggered query
|
||||
func (e *ExpectedQuery) WillReturnRows(rows ...*Rows) *ExpectedQuery {
|
||||
sets := make([]*Rows, len(rows))
|
||||
for i, r := range rows {
|
||||
sets[i] = r
|
||||
}
|
||||
e.rows = &rowSets{sets: sets}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
|
||||
if nil == e.args {
|
||||
return nil
|
||||
}
|
||||
if len(args) != len(e.args) {
|
||||
return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
|
||||
}
|
||||
// @TODO should we assert either all args are named or ordinal?
|
||||
for k, v := range args {
|
||||
// custom argument matcher
|
||||
matcher, ok := e.args[k].(Argument)
|
||||
if ok {
|
||||
if !matcher.Match(v.Value) {
|
||||
return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
dval := e.args[k]
|
||||
if named, isNamed := dval.(sql.NamedArg); isNamed {
|
||||
dval = named.Value
|
||||
if v.Name != named.Name {
|
||||
return fmt.Errorf("named argument %d: name: \"%s\" does not match expected: \"%s\"", k, v.Name, named.Name)
|
||||
}
|
||||
} else if k+1 != v.Ordinal {
|
||||
return fmt.Errorf("argument %d: ordinal position: %d does not match expected: %d", k, k+1, v.Ordinal)
|
||||
}
|
||||
|
||||
// convert to driver converter
|
||||
darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
|
||||
}
|
||||
|
||||
if !driver.IsValue(darg) {
|
||||
return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(darg, v.Value) {
|
||||
return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
39
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result.go
generated
vendored
Normal file
39
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/result.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
157
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go
generated
vendored
Normal file
157
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
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 {
|
||||
if rs.empty() {
|
||||
return "with empty rows"
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (rs *rowSets) empty() bool {
|
||||
for _, set := range rs.sets {
|
||||
if len(set.rows) > 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
20
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18.go
generated
vendored
Normal file
20
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/rows_go18.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
542
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go
generated
vendored
Normal file
542
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go
generated
vendored
Normal file
|
|
@ -0,0 +1,542 @@
|
|||
/*
|
||||
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)
|
||||
}
|
||||
|
||||
// for expected prepared statement check whether it was closed if expected
|
||||
if prep, ok := e.(*ExpectedPrepare); ok {
|
||||
if prep.mustBeClosed && !prep.wasClosed {
|
||||
return fmt.Errorf("expected prepared statement to be closed, but it was not: %s", prep)
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ExecQuery '%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 ExecQuery '%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("ExecQuery '%s', does not match regex '%s'", query, expected.sqlRegex.String())
|
||||
}
|
||||
|
||||
if err := expected.argsMatches(args); err != nil {
|
||||
return nil, fmt.Errorf("ExecQuery '%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("ExecQuery '%s' with args %+v, must return a database/sql/driver.Result, but it was not set for expectation %T as %+v", query, args, expected, expected)
|
||||
}
|
||||
|
||||
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, ex, query}, nil
|
||||
}
|
||||
|
||||
func (c *sqlmock) prepare(query string) (*ExpectedPrepare, error) {
|
||||
var expected *ExpectedPrepare
|
||||
var fulfilled int
|
||||
var ok bool
|
||||
|
||||
query = stripQuery(query)
|
||||
|
||||
for _, next := range c.expected {
|
||||
next.Lock()
|
||||
if next.fulfilled() {
|
||||
next.Unlock()
|
||||
fulfilled++
|
||||
continue
|
||||
}
|
||||
|
||||
if c.ordered {
|
||||
if expected, ok = next.(*ExpectedPrepare); ok {
|
||||
break
|
||||
}
|
||||
|
||||
next.Unlock()
|
||||
return nil, fmt.Errorf("call to Prepare statement with query '%s', was not expected, next expectation is: %s", query, next)
|
||||
}
|
||||
|
||||
if pr, ok := next.(*ExpectedPrepare); ok {
|
||||
if pr.sqlRegex.MatchString(query) {
|
||||
expected = pr
|
||||
break
|
||||
}
|
||||
}
|
||||
next.Unlock()
|
||||
}
|
||||
|
||||
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("Prepare query string '%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("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
|
||||
}
|
||||
101
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18.go
generated
vendored
Normal file
101
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock_go18.go
generated
vendored
Normal file
|
|
@ -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, ex, query}, 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)
|
||||
28
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/statement.go
generated
vendored
Normal file
28
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/statement.go
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package sqlmock
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
)
|
||||
|
||||
type statement struct {
|
||||
conn *sqlmock
|
||||
ex *ExpectedPrepare
|
||||
query string
|
||||
}
|
||||
|
||||
func (stmt *statement) Close() error {
|
||||
stmt.ex.wasClosed = true
|
||||
return stmt.ex.closeErr
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
13
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/util.go
generated
vendored
Normal file
13
vendor/gopkg.in/DATA-DOG/go-sqlmock.v1/util.go
generated
vendored
Normal file
|
|
@ -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, " "))
|
||||
}
|
||||
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
|
|
@ -253,6 +253,9 @@ google.golang.org/protobuf/reflect/protoregistry
|
|||
google.golang.org/protobuf/runtime/protoiface
|
||||
google.golang.org/protobuf/runtime/protoimpl
|
||||
google.golang.org/protobuf/types/descriptorpb
|
||||
# gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0
|
||||
## explicit
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1
|
||||
# gopkg.in/errgo.v1 v1.0.1
|
||||
## explicit
|
||||
gopkg.in/errgo.v1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue