From 59761f522fe7d35a67c3c1354d5bc6aa958de963 Mon Sep 17 00:00:00 2001 From: Sanath Kumar Date: Fri, 26 Jan 2024 18:08:49 -0800 Subject: [PATCH] test: initial service tests --- go.mod | 14 ++- go.sum | 32 +++-- internal/tiny/api.go | 3 +- internal/tiny/service.go | 4 +- internal/tiny/service_test.go | 62 +++++++++ pkg/fakes/fake_postgres_interface.go | 180 +++++++++++++++++++++++++++ pkg/fakes/generate.go | 5 + pkg/postgres/postgres.go | 5 + tools/tools.go | 10 ++ 9 files changed, 295 insertions(+), 20 deletions(-) create mode 100644 internal/tiny/service_test.go create mode 100644 pkg/fakes/fake_postgres_interface.go create mode 100644 pkg/fakes/generate.go create mode 100644 tools/tools.go diff --git a/go.mod b/go.mod index 611bdf9..b77aeba 100644 --- a/go.mod +++ b/go.mod @@ -7,11 +7,14 @@ require ( github.com/golang-migrate/migrate/v4 v4.17.0 github.com/jackc/pgx/v5 v5.5.1 github.com/labstack/echo/v4 v4.11.4 + github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 github.com/oapi-codegen/runtime v1.1.1 github.com/spf13/cobra v1.8.0 + github.com/stretchr/testify v1.8.4 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/swag v0.22.4 // indirect github.com/google/uuid v1.5.0 // indirect @@ -30,15 +33,18 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e27f099..cc21fc6 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYND2gB4p7xcaU= github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -71,6 +73,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM= +github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= @@ -79,6 +83,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= @@ -92,6 +98,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -114,22 +122,22 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= -golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/tiny/api.go b/internal/tiny/api.go index 6d12bec..9ad8e2d 100644 --- a/internal/tiny/api.go +++ b/internal/tiny/api.go @@ -59,7 +59,8 @@ func (a *APIHandler) CreateTinyURL(ec echo.Context) error { Expiry: body.Expiry.Time, Original: body.Original, } - resp, err = a.svc.CreateTinyURL(ec, req) + + resp, err = a.svc.CreateTinyURL(ec.Request().Context(), req) if err != nil { slog.Error("could not complete creating TinyURL", slog.Any("error", err.Error())) ae := APIError{ diff --git a/internal/tiny/service.go b/internal/tiny/service.go index 5e947f6..3fd7531 100644 --- a/internal/tiny/service.go +++ b/internal/tiny/service.go @@ -5,8 +5,6 @@ import ( "io/fs" "log/slog" "time" - - "github.com/labstack/echo/v4" ) type DatabaseInterface interface { @@ -35,7 +33,7 @@ func NewService(ctx context.Context, db DatabaseInterface) (*Service, error) { }, nil } -func (s *Service) CreateTinyURL(ec echo.Context, req TinyURLRequest) (TinyURLResponse, error) { +func (s *Service) CreateTinyURL(ctx context.Context, req TinyURLRequest) (TinyURLResponse, error) { slog.Info("processing a TinyURL request") return TinyURLResponse{ Expiry: req.Expiry, diff --git a/internal/tiny/service_test.go b/internal/tiny/service_test.go new file mode 100644 index 0000000..7934b9b --- /dev/null +++ b/internal/tiny/service_test.go @@ -0,0 +1,62 @@ +package tiny_test + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "sanathk.com/tinyurl/internal/tiny" + "sanathk.com/tinyurl/pkg/fakes" +) + +func TestServiceInit(t *testing.T) { + fakeDB := fakes.FakePostgresInterface{} + + _, err := tiny.NewService(context.Background(), &fakeDB) + require.NoError(t, err) +} + +func TestServiceCreateTinyURL(t *testing.T) { + fakeDB := fakes.FakePostgresInterface{} + + svc, err := tiny.NewService(context.Background(), &fakeDB) + require.NoError(t, err) + + type testcase struct { + name string + in tiny.TinyURLRequest + expected tiny.TinyURLResponse + } + + validExpiryTime := time.Now().Add(10 * time.Hour) + validOriginalLink := "https://www.sanathk.com" + + testcases := []testcase{ + { + name: "valid expiry and original", + in: tiny.TinyURLRequest{ + Expiry: validExpiryTime, + Original: validOriginalLink, + }, + expected: tiny.TinyURLResponse{ + Expiry: validExpiryTime, + Original: validOriginalLink, + }, + // TODO: add more tests: + // Negative Cases: + // * invalid time + // * invalid or empty url + // * max url length for hashing? + }, + } + + for _, tc := range testcases { + resp, err := svc.CreateTinyURL(context.Background(), tc.in) + require.NoError(t, err) + + require.Equal(t, tc.expected.Original, resp.Original) + require.Equal(t, tc.expected.Expiry, resp.Expiry) + require.NotEqual(t, tc.expected.Original, resp.Tinyurl) + } +} diff --git a/pkg/fakes/fake_postgres_interface.go b/pkg/fakes/fake_postgres_interface.go new file mode 100644 index 0000000..3a8bb7a --- /dev/null +++ b/pkg/fakes/fake_postgres_interface.go @@ -0,0 +1,180 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package fakes + +import ( + "io/fs" + "sync" + + pgx "github.com/jackc/pgx/v5" + "sanathk.com/tinyurl/pkg/postgres" +) + +type FakePostgresInterface struct { + ConnStub func() *pgx.Conn + connMutex sync.RWMutex + connArgsForCall []struct { + } + connReturns struct { + result1 *pgx.Conn + } + connReturnsOnCall map[int]struct { + result1 *pgx.Conn + } + MigrateStub func(fs.FS, string) error + migrateMutex sync.RWMutex + migrateArgsForCall []struct { + arg1 fs.FS + arg2 string + } + migrateReturns struct { + result1 error + } + migrateReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakePostgresInterface) Conn() *pgx.Conn { + fake.connMutex.Lock() + ret, specificReturn := fake.connReturnsOnCall[len(fake.connArgsForCall)] + fake.connArgsForCall = append(fake.connArgsForCall, struct { + }{}) + stub := fake.ConnStub + fakeReturns := fake.connReturns + fake.recordInvocation("Conn", []interface{}{}) + fake.connMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakePostgresInterface) ConnCallCount() int { + fake.connMutex.RLock() + defer fake.connMutex.RUnlock() + return len(fake.connArgsForCall) +} + +func (fake *FakePostgresInterface) ConnCalls(stub func() *pgx.Conn) { + fake.connMutex.Lock() + defer fake.connMutex.Unlock() + fake.ConnStub = stub +} + +func (fake *FakePostgresInterface) ConnReturns(result1 *pgx.Conn) { + fake.connMutex.Lock() + defer fake.connMutex.Unlock() + fake.ConnStub = nil + fake.connReturns = struct { + result1 *pgx.Conn + }{result1} +} + +func (fake *FakePostgresInterface) ConnReturnsOnCall(i int, result1 *pgx.Conn) { + fake.connMutex.Lock() + defer fake.connMutex.Unlock() + fake.ConnStub = nil + if fake.connReturnsOnCall == nil { + fake.connReturnsOnCall = make(map[int]struct { + result1 *pgx.Conn + }) + } + fake.connReturnsOnCall[i] = struct { + result1 *pgx.Conn + }{result1} +} + +func (fake *FakePostgresInterface) Migrate(arg1 fs.FS, arg2 string) error { + fake.migrateMutex.Lock() + ret, specificReturn := fake.migrateReturnsOnCall[len(fake.migrateArgsForCall)] + fake.migrateArgsForCall = append(fake.migrateArgsForCall, struct { + arg1 fs.FS + arg2 string + }{arg1, arg2}) + stub := fake.MigrateStub + fakeReturns := fake.migrateReturns + fake.recordInvocation("Migrate", []interface{}{arg1, arg2}) + fake.migrateMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakePostgresInterface) MigrateCallCount() int { + fake.migrateMutex.RLock() + defer fake.migrateMutex.RUnlock() + return len(fake.migrateArgsForCall) +} + +func (fake *FakePostgresInterface) MigrateCalls(stub func(fs.FS, string) error) { + fake.migrateMutex.Lock() + defer fake.migrateMutex.Unlock() + fake.MigrateStub = stub +} + +func (fake *FakePostgresInterface) MigrateArgsForCall(i int) (fs.FS, string) { + fake.migrateMutex.RLock() + defer fake.migrateMutex.RUnlock() + argsForCall := fake.migrateArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakePostgresInterface) MigrateReturns(result1 error) { + fake.migrateMutex.Lock() + defer fake.migrateMutex.Unlock() + fake.MigrateStub = nil + fake.migrateReturns = struct { + result1 error + }{result1} +} + +func (fake *FakePostgresInterface) MigrateReturnsOnCall(i int, result1 error) { + fake.migrateMutex.Lock() + defer fake.migrateMutex.Unlock() + fake.MigrateStub = nil + if fake.migrateReturnsOnCall == nil { + fake.migrateReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.migrateReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakePostgresInterface) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.connMutex.RLock() + defer fake.connMutex.RUnlock() + fake.migrateMutex.RLock() + defer fake.migrateMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakePostgresInterface) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ postgres.PostgresInterface = new(FakePostgresInterface) diff --git a/pkg/fakes/generate.go b/pkg/fakes/generate.go new file mode 100644 index 0000000..b6046b5 --- /dev/null +++ b/pkg/fakes/generate.go @@ -0,0 +1,5 @@ +package fakes + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate + +//counterfeiter:generate -o ./ ../postgres PostgresInterface diff --git a/pkg/postgres/postgres.go b/pkg/postgres/postgres.go index 526b1c9..c2c213e 100644 --- a/pkg/postgres/postgres.go +++ b/pkg/postgres/postgres.go @@ -15,6 +15,11 @@ import ( "github.com/jackc/pgx/v5/stdlib" ) +type PostgresInterface interface { + Conn() *pgx.Conn + Migrate(files fs.FS, path string) error +} + type Postgres struct { connString *url.URL conn *pgx.Conn diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 0000000..c4b77c9 --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,10 @@ +//go:build tools + +package tools + +import ( + _ "github.com/maxbrunsfeld/counterfeiter/v6" +) + +// This file imports packages that are used when running go generate, or used +// during the development process but not otherwise depended on by built code.