From 3552f695722c09d9e48dfe5875031794f201a530 Mon Sep 17 00:00:00 2001 From: vallyenfail Date: Mon, 19 Jan 2026 19:51:39 +0300 Subject: [PATCH] add service --- .gitignore | 6 +- Makefile | 46 ++- api/proto/invite/invite.proto | 10 +- internal/grpc/invite_handler.go | 9 +- internal/mocks/invite_repository_mock.go | 356 +++++++++++++++++ internal/mocks/invite_service_mock.go | 56 +-- internal/mocks/token_usage_repository_mock.go | 359 +++++++++++++++++- internal/mocks/user_service_mock.go | 356 +++++++++++++++++ internal/repository/interfaces.go | 1 + internal/repository/invite.go | 32 ++ internal/service/interfaces.go | 2 +- internal/service/invite.go | 4 +- tests/full_flow_test.go | 4 +- tests/invite_handler_test.go | 19 +- tests/repository_test.go | 37 ++ 15 files changed, 1213 insertions(+), 84 deletions(-) diff --git a/.gitignore b/.gitignore index bf98ce0..548abba 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,8 @@ config/config.yaml /bin/ /dist/ .gitea -.gitea/workflows \ No newline at end of file +.gitea/workflows + +# Coverage +coverage/ +/pkg/pb/ \ No newline at end of file diff --git a/Makefile b/Makefile index 8c4ece1..b068bcb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help build run migrate-up migrate-down migrate-create lint test test-integration proto clean +.PHONY: help build run migrate-up migrate-down migrate-create lint test test-integration test-coverage proto clean help: @echo "Available commands:" @@ -12,6 +12,7 @@ help: @echo " make generate-mock - Generate mocks for all interfaces (minimock)" @echo " make test - Run unit tests" @echo " make test-integration - Run integration tests with testcontainers" + @echo " make test-coverage - Run tests with coverage report" @echo " make clean - Clean build artifacts" build: @@ -40,23 +41,24 @@ lint: @echo "Running linter..." golangci-lint run ./... -proto: - @echo "Generating proto files..." - @mkdir -p pkg/pb - @cd api/proto && protoc --go_out=../../pkg/pb --go_opt=paths=source_relative \ - --go-grpc_out=../../pkg/pb --go-grpc_opt=paths=source_relative \ - auth/auth.proto \ - user/user.proto \ - invite/invite.proto \ - request/request.proto \ - supplier/supplier.proto - @echo "Proto generation complete" - -clean: - @echo "Cleaning build artifacts..." - rm -rf bin/ - rm -rf pkg/pb/ - @echo "Clean complete" +#Протник генерируем как показано в smart-search-gateway! Здесь это оставлено на всякий случай +#proto: +# @echo "Generating proto files..." +# @mkdir -p pkg/pb +# @cd api/proto && protoc --go_out=../../pkg/pb --go_opt=paths=source_relative \ +# --go-grpc_out=../../pkg/pb --go-grpc_opt=paths=source_relative \ +# auth/auth.proto \ +# user/user.proto \ +# invite/invite.proto \ +# request/request.proto \ +# supplier/supplier.proto +# @echo "Proto generation complete" +# +#clean: +# @echo "Cleaning build artifacts..." +# rm -rf bin/ +# rm -rf pkg/pb/ +# @echo "Clean complete" .PHONY: generate-mock generate-mock: @@ -87,5 +89,13 @@ test-integration: @echo "This may take several minutes..." go test -v -timeout=10m ./tests/... +test-coverage: + @echo "Running tests with coverage..." + @mkdir -p coverage + go test -timeout=10m -coverprofile=coverage/coverage.out -covermode=atomic ./... + go tool cover -func=coverage/coverage.out + go tool cover -html=coverage/coverage.out -o coverage/coverage.html + @echo "Coverage report: coverage/coverage.html" + # Default DB URL for local development DB_URL ?= postgres://postgres:password@localhost:5432/b2b_search?sslmode=disable diff --git a/api/proto/invite/invite.proto b/api/proto/invite/invite.proto index 1a0bede..3685364 100644 --- a/api/proto/invite/invite.proto +++ b/api/proto/invite/invite.proto @@ -22,14 +22,12 @@ message GenerateResponse { } message GetInfoRequest { - string code = 1; + int64 user_id = 1; } message GetInfoResponse { string code = 1; - int64 user_id = 2; - int32 can_be_used_count = 3; - google.protobuf.Timestamp expires_at = 4; - bool is_active = 5; - google.protobuf.Timestamp created_at = 6; + int32 can_be_used_count = 2; + google.protobuf.Timestamp expires_at = 3; + google.protobuf.Timestamp created_at = 4; } diff --git a/internal/grpc/invite_handler.go b/internal/grpc/invite_handler.go index 546a9de..6d83ddf 100644 --- a/internal/grpc/invite_handler.go +++ b/internal/grpc/invite_handler.go @@ -23,22 +23,15 @@ func (h *InviteHandler) Generate(ctx context.Context, req *pb.GenerateRequest) ( } func (h *InviteHandler) GetInfo(ctx context.Context, req *pb.GetInfoRequest) (*pb.GetInfoResponse, error) { - code, err := strconv.ParseInt(req.Code, 10, 64) - if err != nil { - return nil, errors.ToGRPCError(err, h.logger, "InviteService.GetInfo") - } - - invite, err := h.inviteService.GetInfo(ctx, code) + invite, err := h.inviteService.GetInfo(ctx, int(req.UserId)) if err != nil { return nil, errors.ToGRPCError(err, h.logger, "InviteService.GetInfo") } return &pb.GetInfoResponse{ Code: strconv.FormatInt(invite.Code, 10), - UserId: int64(invite.UserID), CanBeUsedCount: int32(invite.CanBeUsedCount), ExpiresAt: timestamppb.New(invite.ExpiresAt), - IsActive: invite.IsActive, CreatedAt: timestamppb.New(invite.CreatedAt), }, nil } diff --git a/internal/mocks/invite_repository_mock.go b/internal/mocks/invite_repository_mock.go index c952da6..993e8d4 100644 --- a/internal/mocks/invite_repository_mock.go +++ b/internal/mocks/invite_repository_mock.go @@ -55,6 +55,13 @@ type InviteRepositoryMock struct { beforeFindActiveByCodeCounter uint64 FindActiveByCodeMock mInviteRepositoryMockFindActiveByCode + funcFindActiveByUserID func(ctx context.Context, userID int) (ip1 *model.InviteCode, err error) + funcFindActiveByUserIDOrigin string + inspectFuncFindActiveByUserID func(ctx context.Context, userID int) + afterFindActiveByUserIDCounter uint64 + beforeFindActiveByUserIDCounter uint64 + FindActiveByUserIDMock mInviteRepositoryMockFindActiveByUserID + funcFindByCode func(ctx context.Context, code int64) (ip1 *model.InviteCode, err error) funcFindByCodeOrigin string inspectFuncFindByCode func(ctx context.Context, code int64) @@ -93,6 +100,9 @@ func NewInviteRepositoryMock(t minimock.Tester) *InviteRepositoryMock { m.FindActiveByCodeMock = mInviteRepositoryMockFindActiveByCode{mock: m} m.FindActiveByCodeMock.callArgs = []*InviteRepositoryMockFindActiveByCodeParams{} + m.FindActiveByUserIDMock = mInviteRepositoryMockFindActiveByUserID{mock: m} + m.FindActiveByUserIDMock.callArgs = []*InviteRepositoryMockFindActiveByUserIDParams{} + m.FindByCodeMock = mInviteRepositoryMockFindByCode{mock: m} m.FindByCodeMock.callArgs = []*InviteRepositoryMockFindByCodeParams{} @@ -1847,6 +1857,349 @@ func (m *InviteRepositoryMock) MinimockFindActiveByCodeInspect() { } } +type mInviteRepositoryMockFindActiveByUserID struct { + optional bool + mock *InviteRepositoryMock + defaultExpectation *InviteRepositoryMockFindActiveByUserIDExpectation + expectations []*InviteRepositoryMockFindActiveByUserIDExpectation + + callArgs []*InviteRepositoryMockFindActiveByUserIDParams + mutex sync.RWMutex + + expectedInvocations uint64 + expectedInvocationsOrigin string +} + +// InviteRepositoryMockFindActiveByUserIDExpectation specifies expectation struct of the InviteRepository.FindActiveByUserID +type InviteRepositoryMockFindActiveByUserIDExpectation struct { + mock *InviteRepositoryMock + params *InviteRepositoryMockFindActiveByUserIDParams + paramPtrs *InviteRepositoryMockFindActiveByUserIDParamPtrs + expectationOrigins InviteRepositoryMockFindActiveByUserIDExpectationOrigins + results *InviteRepositoryMockFindActiveByUserIDResults + returnOrigin string + Counter uint64 +} + +// InviteRepositoryMockFindActiveByUserIDParams contains parameters of the InviteRepository.FindActiveByUserID +type InviteRepositoryMockFindActiveByUserIDParams struct { + ctx context.Context + userID int +} + +// InviteRepositoryMockFindActiveByUserIDParamPtrs contains pointers to parameters of the InviteRepository.FindActiveByUserID +type InviteRepositoryMockFindActiveByUserIDParamPtrs struct { + ctx *context.Context + userID *int +} + +// InviteRepositoryMockFindActiveByUserIDResults contains results of the InviteRepository.FindActiveByUserID +type InviteRepositoryMockFindActiveByUserIDResults struct { + ip1 *model.InviteCode + err error +} + +// InviteRepositoryMockFindActiveByUserIDOrigins contains origins of expectations of the InviteRepository.FindActiveByUserID +type InviteRepositoryMockFindActiveByUserIDExpectationOrigins struct { + origin string + originCtx string + originUserID string +} + +// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning +// the test will fail minimock's automatic final call check if the mocked method was not called at least once. +// Optional() makes method check to work in '0 or more' mode. +// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to +// catch the problems when the expected method call is totally skipped during test run. +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Optional() *mInviteRepositoryMockFindActiveByUserID { + mmFindActiveByUserID.optional = true + return mmFindActiveByUserID +} + +// Expect sets up expected params for InviteRepository.FindActiveByUserID +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Expect(ctx context.Context, userID int) *mInviteRepositoryMockFindActiveByUserID { + if mmFindActiveByUserID.mock.funcFindActiveByUserID != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Set") + } + + if mmFindActiveByUserID.defaultExpectation == nil { + mmFindActiveByUserID.defaultExpectation = &InviteRepositoryMockFindActiveByUserIDExpectation{} + } + + if mmFindActiveByUserID.defaultExpectation.paramPtrs != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by ExpectParams functions") + } + + mmFindActiveByUserID.defaultExpectation.params = &InviteRepositoryMockFindActiveByUserIDParams{ctx, userID} + mmFindActiveByUserID.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1) + for _, e := range mmFindActiveByUserID.expectations { + if minimock.Equal(e.params, mmFindActiveByUserID.defaultExpectation.params) { + mmFindActiveByUserID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmFindActiveByUserID.defaultExpectation.params) + } + } + + return mmFindActiveByUserID +} + +// ExpectCtxParam1 sets up expected param ctx for InviteRepository.FindActiveByUserID +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) ExpectCtxParam1(ctx context.Context) *mInviteRepositoryMockFindActiveByUserID { + if mmFindActiveByUserID.mock.funcFindActiveByUserID != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Set") + } + + if mmFindActiveByUserID.defaultExpectation == nil { + mmFindActiveByUserID.defaultExpectation = &InviteRepositoryMockFindActiveByUserIDExpectation{} + } + + if mmFindActiveByUserID.defaultExpectation.params != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Expect") + } + + if mmFindActiveByUserID.defaultExpectation.paramPtrs == nil { + mmFindActiveByUserID.defaultExpectation.paramPtrs = &InviteRepositoryMockFindActiveByUserIDParamPtrs{} + } + mmFindActiveByUserID.defaultExpectation.paramPtrs.ctx = &ctx + mmFindActiveByUserID.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1) + + return mmFindActiveByUserID +} + +// ExpectUserIDParam2 sets up expected param userID for InviteRepository.FindActiveByUserID +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) ExpectUserIDParam2(userID int) *mInviteRepositoryMockFindActiveByUserID { + if mmFindActiveByUserID.mock.funcFindActiveByUserID != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Set") + } + + if mmFindActiveByUserID.defaultExpectation == nil { + mmFindActiveByUserID.defaultExpectation = &InviteRepositoryMockFindActiveByUserIDExpectation{} + } + + if mmFindActiveByUserID.defaultExpectation.params != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Expect") + } + + if mmFindActiveByUserID.defaultExpectation.paramPtrs == nil { + mmFindActiveByUserID.defaultExpectation.paramPtrs = &InviteRepositoryMockFindActiveByUserIDParamPtrs{} + } + mmFindActiveByUserID.defaultExpectation.paramPtrs.userID = &userID + mmFindActiveByUserID.defaultExpectation.expectationOrigins.originUserID = minimock.CallerInfo(1) + + return mmFindActiveByUserID +} + +// Inspect accepts an inspector function that has same arguments as the InviteRepository.FindActiveByUserID +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Inspect(f func(ctx context.Context, userID int)) *mInviteRepositoryMockFindActiveByUserID { + if mmFindActiveByUserID.mock.inspectFuncFindActiveByUserID != nil { + mmFindActiveByUserID.mock.t.Fatalf("Inspect function is already set for InviteRepositoryMock.FindActiveByUserID") + } + + mmFindActiveByUserID.mock.inspectFuncFindActiveByUserID = f + + return mmFindActiveByUserID +} + +// Return sets up results that will be returned by InviteRepository.FindActiveByUserID +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Return(ip1 *model.InviteCode, err error) *InviteRepositoryMock { + if mmFindActiveByUserID.mock.funcFindActiveByUserID != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Set") + } + + if mmFindActiveByUserID.defaultExpectation == nil { + mmFindActiveByUserID.defaultExpectation = &InviteRepositoryMockFindActiveByUserIDExpectation{mock: mmFindActiveByUserID.mock} + } + mmFindActiveByUserID.defaultExpectation.results = &InviteRepositoryMockFindActiveByUserIDResults{ip1, err} + mmFindActiveByUserID.defaultExpectation.returnOrigin = minimock.CallerInfo(1) + return mmFindActiveByUserID.mock +} + +// Set uses given function f to mock the InviteRepository.FindActiveByUserID method +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Set(f func(ctx context.Context, userID int) (ip1 *model.InviteCode, err error)) *InviteRepositoryMock { + if mmFindActiveByUserID.defaultExpectation != nil { + mmFindActiveByUserID.mock.t.Fatalf("Default expectation is already set for the InviteRepository.FindActiveByUserID method") + } + + if len(mmFindActiveByUserID.expectations) > 0 { + mmFindActiveByUserID.mock.t.Fatalf("Some expectations are already set for the InviteRepository.FindActiveByUserID method") + } + + mmFindActiveByUserID.mock.funcFindActiveByUserID = f + mmFindActiveByUserID.mock.funcFindActiveByUserIDOrigin = minimock.CallerInfo(1) + return mmFindActiveByUserID.mock +} + +// When sets expectation for the InviteRepository.FindActiveByUserID which will trigger the result defined by the following +// Then helper +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) When(ctx context.Context, userID int) *InviteRepositoryMockFindActiveByUserIDExpectation { + if mmFindActiveByUserID.mock.funcFindActiveByUserID != nil { + mmFindActiveByUserID.mock.t.Fatalf("InviteRepositoryMock.FindActiveByUserID mock is already set by Set") + } + + expectation := &InviteRepositoryMockFindActiveByUserIDExpectation{ + mock: mmFindActiveByUserID.mock, + params: &InviteRepositoryMockFindActiveByUserIDParams{ctx, userID}, + expectationOrigins: InviteRepositoryMockFindActiveByUserIDExpectationOrigins{origin: minimock.CallerInfo(1)}, + } + mmFindActiveByUserID.expectations = append(mmFindActiveByUserID.expectations, expectation) + return expectation +} + +// Then sets up InviteRepository.FindActiveByUserID return parameters for the expectation previously defined by the When method +func (e *InviteRepositoryMockFindActiveByUserIDExpectation) Then(ip1 *model.InviteCode, err error) *InviteRepositoryMock { + e.results = &InviteRepositoryMockFindActiveByUserIDResults{ip1, err} + return e.mock +} + +// Times sets number of times InviteRepository.FindActiveByUserID should be invoked +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Times(n uint64) *mInviteRepositoryMockFindActiveByUserID { + if n == 0 { + mmFindActiveByUserID.mock.t.Fatalf("Times of InviteRepositoryMock.FindActiveByUserID mock can not be zero") + } + mm_atomic.StoreUint64(&mmFindActiveByUserID.expectedInvocations, n) + mmFindActiveByUserID.expectedInvocationsOrigin = minimock.CallerInfo(1) + return mmFindActiveByUserID +} + +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) invocationsDone() bool { + if len(mmFindActiveByUserID.expectations) == 0 && mmFindActiveByUserID.defaultExpectation == nil && mmFindActiveByUserID.mock.funcFindActiveByUserID == nil { + return true + } + + totalInvocations := mm_atomic.LoadUint64(&mmFindActiveByUserID.mock.afterFindActiveByUserIDCounter) + expectedInvocations := mm_atomic.LoadUint64(&mmFindActiveByUserID.expectedInvocations) + + return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations) +} + +// FindActiveByUserID implements mm_repository.InviteRepository +func (mmFindActiveByUserID *InviteRepositoryMock) FindActiveByUserID(ctx context.Context, userID int) (ip1 *model.InviteCode, err error) { + mm_atomic.AddUint64(&mmFindActiveByUserID.beforeFindActiveByUserIDCounter, 1) + defer mm_atomic.AddUint64(&mmFindActiveByUserID.afterFindActiveByUserIDCounter, 1) + + mmFindActiveByUserID.t.Helper() + + if mmFindActiveByUserID.inspectFuncFindActiveByUserID != nil { + mmFindActiveByUserID.inspectFuncFindActiveByUserID(ctx, userID) + } + + mm_params := InviteRepositoryMockFindActiveByUserIDParams{ctx, userID} + + // Record call args + mmFindActiveByUserID.FindActiveByUserIDMock.mutex.Lock() + mmFindActiveByUserID.FindActiveByUserIDMock.callArgs = append(mmFindActiveByUserID.FindActiveByUserIDMock.callArgs, &mm_params) + mmFindActiveByUserID.FindActiveByUserIDMock.mutex.Unlock() + + for _, e := range mmFindActiveByUserID.FindActiveByUserIDMock.expectations { + if minimock.Equal(*e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.ip1, e.results.err + } + } + + if mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.Counter, 1) + mm_want := mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.params + mm_want_ptrs := mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.paramPtrs + + mm_got := InviteRepositoryMockFindActiveByUserIDParams{ctx, userID} + + if mm_want_ptrs != nil { + + if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) { + mmFindActiveByUserID.t.Errorf("InviteRepositoryMock.FindActiveByUserID got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx)) + } + + if mm_want_ptrs.userID != nil && !minimock.Equal(*mm_want_ptrs.userID, mm_got.userID) { + mmFindActiveByUserID.t.Errorf("InviteRepositoryMock.FindActiveByUserID got unexpected parameter userID, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.expectationOrigins.originUserID, *mm_want_ptrs.userID, mm_got.userID, minimock.Diff(*mm_want_ptrs.userID, mm_got.userID)) + } + + } else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmFindActiveByUserID.t.Errorf("InviteRepositoryMock.FindActiveByUserID got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmFindActiveByUserID.FindActiveByUserIDMock.defaultExpectation.results + if mm_results == nil { + mmFindActiveByUserID.t.Fatal("No results are set for the InviteRepositoryMock.FindActiveByUserID") + } + return (*mm_results).ip1, (*mm_results).err + } + if mmFindActiveByUserID.funcFindActiveByUserID != nil { + return mmFindActiveByUserID.funcFindActiveByUserID(ctx, userID) + } + mmFindActiveByUserID.t.Fatalf("Unexpected call to InviteRepositoryMock.FindActiveByUserID. %v %v", ctx, userID) + return +} + +// FindActiveByUserIDAfterCounter returns a count of finished InviteRepositoryMock.FindActiveByUserID invocations +func (mmFindActiveByUserID *InviteRepositoryMock) FindActiveByUserIDAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmFindActiveByUserID.afterFindActiveByUserIDCounter) +} + +// FindActiveByUserIDBeforeCounter returns a count of InviteRepositoryMock.FindActiveByUserID invocations +func (mmFindActiveByUserID *InviteRepositoryMock) FindActiveByUserIDBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmFindActiveByUserID.beforeFindActiveByUserIDCounter) +} + +// Calls returns a list of arguments used in each call to InviteRepositoryMock.FindActiveByUserID. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmFindActiveByUserID *mInviteRepositoryMockFindActiveByUserID) Calls() []*InviteRepositoryMockFindActiveByUserIDParams { + mmFindActiveByUserID.mutex.RLock() + + argCopy := make([]*InviteRepositoryMockFindActiveByUserIDParams, len(mmFindActiveByUserID.callArgs)) + copy(argCopy, mmFindActiveByUserID.callArgs) + + mmFindActiveByUserID.mutex.RUnlock() + + return argCopy +} + +// MinimockFindActiveByUserIDDone returns true if the count of the FindActiveByUserID invocations corresponds +// the number of defined expectations +func (m *InviteRepositoryMock) MinimockFindActiveByUserIDDone() bool { + if m.FindActiveByUserIDMock.optional { + // Optional methods provide '0 or more' call count restriction. + return true + } + + for _, e := range m.FindActiveByUserIDMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + return m.FindActiveByUserIDMock.invocationsDone() +} + +// MinimockFindActiveByUserIDInspect logs each unmet expectation +func (m *InviteRepositoryMock) MinimockFindActiveByUserIDInspect() { + for _, e := range m.FindActiveByUserIDMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to InviteRepositoryMock.FindActiveByUserID at\n%s with params: %#v", e.expectationOrigins.origin, *e.params) + } + } + + afterFindActiveByUserIDCounter := mm_atomic.LoadUint64(&m.afterFindActiveByUserIDCounter) + // if default expectation was set then invocations count should be greater than zero + if m.FindActiveByUserIDMock.defaultExpectation != nil && afterFindActiveByUserIDCounter < 1 { + if m.FindActiveByUserIDMock.defaultExpectation.params == nil { + m.t.Errorf("Expected call to InviteRepositoryMock.FindActiveByUserID at\n%s", m.FindActiveByUserIDMock.defaultExpectation.returnOrigin) + } else { + m.t.Errorf("Expected call to InviteRepositoryMock.FindActiveByUserID at\n%s with params: %#v", m.FindActiveByUserIDMock.defaultExpectation.expectationOrigins.origin, *m.FindActiveByUserIDMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcFindActiveByUserID != nil && afterFindActiveByUserIDCounter < 1 { + m.t.Errorf("Expected call to InviteRepositoryMock.FindActiveByUserID at\n%s", m.funcFindActiveByUserIDOrigin) + } + + if !m.FindActiveByUserIDMock.invocationsDone() && afterFindActiveByUserIDCounter > 0 { + m.t.Errorf("Expected %d calls to InviteRepositoryMock.FindActiveByUserID at\n%s but found %d calls", + mm_atomic.LoadUint64(&m.FindActiveByUserIDMock.expectedInvocations), m.FindActiveByUserIDMock.expectedInvocationsOrigin, afterFindActiveByUserIDCounter) + } +} + type mInviteRepositoryMockFindByCode struct { optional bool mock *InviteRepositoryMock @@ -2547,6 +2900,8 @@ func (m *InviteRepositoryMock) MinimockFinish() { m.MinimockFindActiveByCodeInspect() + m.MinimockFindActiveByUserIDInspect() + m.MinimockFindByCodeInspect() m.MinimockGetUserInvitesInspect() @@ -2578,6 +2933,7 @@ func (m *InviteRepositoryMock) minimockDone() bool { m.MinimockDeactivateExpiredDone() && m.MinimockDecrementCanBeUsedCountTxDone() && m.MinimockFindActiveByCodeDone() && + m.MinimockFindActiveByUserIDDone() && m.MinimockFindByCodeDone() && m.MinimockGetUserInvitesDone() } diff --git a/internal/mocks/invite_service_mock.go b/internal/mocks/invite_service_mock.go index beee5c7..5de7e05 100644 --- a/internal/mocks/invite_service_mock.go +++ b/internal/mocks/invite_service_mock.go @@ -26,9 +26,9 @@ type InviteServiceMock struct { beforeGenerateCounter uint64 GenerateMock mInviteServiceMockGenerate - funcGetInfo func(ctx context.Context, code int64) (ip1 *model.InviteCode, err error) + funcGetInfo func(ctx context.Context, userID int) (ip1 *model.InviteCode, err error) funcGetInfoOrigin string - inspectFuncGetInfo func(ctx context.Context, code int64) + inspectFuncGetInfo func(ctx context.Context, userID int) afterGetInfoCounter uint64 beforeGetInfoCounter uint64 GetInfoMock mInviteServiceMockGetInfo @@ -484,14 +484,14 @@ type InviteServiceMockGetInfoExpectation struct { // InviteServiceMockGetInfoParams contains parameters of the InviteService.GetInfo type InviteServiceMockGetInfoParams struct { - ctx context.Context - code int64 + ctx context.Context + userID int } // InviteServiceMockGetInfoParamPtrs contains pointers to parameters of the InviteService.GetInfo type InviteServiceMockGetInfoParamPtrs struct { - ctx *context.Context - code *int64 + ctx *context.Context + userID *int } // InviteServiceMockGetInfoResults contains results of the InviteService.GetInfo @@ -502,9 +502,9 @@ type InviteServiceMockGetInfoResults struct { // InviteServiceMockGetInfoOrigins contains origins of expectations of the InviteService.GetInfo type InviteServiceMockGetInfoExpectationOrigins struct { - origin string - originCtx string - originCode string + origin string + originCtx string + originUserID string } // Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning @@ -518,7 +518,7 @@ func (mmGetInfo *mInviteServiceMockGetInfo) Optional() *mInviteServiceMockGetInf } // Expect sets up expected params for InviteService.GetInfo -func (mmGetInfo *mInviteServiceMockGetInfo) Expect(ctx context.Context, code int64) *mInviteServiceMockGetInfo { +func (mmGetInfo *mInviteServiceMockGetInfo) Expect(ctx context.Context, userID int) *mInviteServiceMockGetInfo { if mmGetInfo.mock.funcGetInfo != nil { mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set") } @@ -531,7 +531,7 @@ func (mmGetInfo *mInviteServiceMockGetInfo) Expect(ctx context.Context, code int mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by ExpectParams functions") } - mmGetInfo.defaultExpectation.params = &InviteServiceMockGetInfoParams{ctx, code} + mmGetInfo.defaultExpectation.params = &InviteServiceMockGetInfoParams{ctx, userID} mmGetInfo.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1) for _, e := range mmGetInfo.expectations { if minimock.Equal(e.params, mmGetInfo.defaultExpectation.params) { @@ -565,8 +565,8 @@ func (mmGetInfo *mInviteServiceMockGetInfo) ExpectCtxParam1(ctx context.Context) return mmGetInfo } -// ExpectCodeParam2 sets up expected param code for InviteService.GetInfo -func (mmGetInfo *mInviteServiceMockGetInfo) ExpectCodeParam2(code int64) *mInviteServiceMockGetInfo { +// ExpectUserIDParam2 sets up expected param userID for InviteService.GetInfo +func (mmGetInfo *mInviteServiceMockGetInfo) ExpectUserIDParam2(userID int) *mInviteServiceMockGetInfo { if mmGetInfo.mock.funcGetInfo != nil { mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set") } @@ -582,14 +582,14 @@ func (mmGetInfo *mInviteServiceMockGetInfo) ExpectCodeParam2(code int64) *mInvit if mmGetInfo.defaultExpectation.paramPtrs == nil { mmGetInfo.defaultExpectation.paramPtrs = &InviteServiceMockGetInfoParamPtrs{} } - mmGetInfo.defaultExpectation.paramPtrs.code = &code - mmGetInfo.defaultExpectation.expectationOrigins.originCode = minimock.CallerInfo(1) + mmGetInfo.defaultExpectation.paramPtrs.userID = &userID + mmGetInfo.defaultExpectation.expectationOrigins.originUserID = minimock.CallerInfo(1) return mmGetInfo } // Inspect accepts an inspector function that has same arguments as the InviteService.GetInfo -func (mmGetInfo *mInviteServiceMockGetInfo) Inspect(f func(ctx context.Context, code int64)) *mInviteServiceMockGetInfo { +func (mmGetInfo *mInviteServiceMockGetInfo) Inspect(f func(ctx context.Context, userID int)) *mInviteServiceMockGetInfo { if mmGetInfo.mock.inspectFuncGetInfo != nil { mmGetInfo.mock.t.Fatalf("Inspect function is already set for InviteServiceMock.GetInfo") } @@ -614,7 +614,7 @@ func (mmGetInfo *mInviteServiceMockGetInfo) Return(ip1 *model.InviteCode, err er } // Set uses given function f to mock the InviteService.GetInfo method -func (mmGetInfo *mInviteServiceMockGetInfo) Set(f func(ctx context.Context, code int64) (ip1 *model.InviteCode, err error)) *InviteServiceMock { +func (mmGetInfo *mInviteServiceMockGetInfo) Set(f func(ctx context.Context, userID int) (ip1 *model.InviteCode, err error)) *InviteServiceMock { if mmGetInfo.defaultExpectation != nil { mmGetInfo.mock.t.Fatalf("Default expectation is already set for the InviteService.GetInfo method") } @@ -630,14 +630,14 @@ func (mmGetInfo *mInviteServiceMockGetInfo) Set(f func(ctx context.Context, code // When sets expectation for the InviteService.GetInfo which will trigger the result defined by the following // Then helper -func (mmGetInfo *mInviteServiceMockGetInfo) When(ctx context.Context, code int64) *InviteServiceMockGetInfoExpectation { +func (mmGetInfo *mInviteServiceMockGetInfo) When(ctx context.Context, userID int) *InviteServiceMockGetInfoExpectation { if mmGetInfo.mock.funcGetInfo != nil { mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set") } expectation := &InviteServiceMockGetInfoExpectation{ mock: mmGetInfo.mock, - params: &InviteServiceMockGetInfoParams{ctx, code}, + params: &InviteServiceMockGetInfoParams{ctx, userID}, expectationOrigins: InviteServiceMockGetInfoExpectationOrigins{origin: minimock.CallerInfo(1)}, } mmGetInfo.expectations = append(mmGetInfo.expectations, expectation) @@ -672,17 +672,17 @@ func (mmGetInfo *mInviteServiceMockGetInfo) invocationsDone() bool { } // GetInfo implements mm_service.InviteService -func (mmGetInfo *InviteServiceMock) GetInfo(ctx context.Context, code int64) (ip1 *model.InviteCode, err error) { +func (mmGetInfo *InviteServiceMock) GetInfo(ctx context.Context, userID int) (ip1 *model.InviteCode, err error) { mm_atomic.AddUint64(&mmGetInfo.beforeGetInfoCounter, 1) defer mm_atomic.AddUint64(&mmGetInfo.afterGetInfoCounter, 1) mmGetInfo.t.Helper() if mmGetInfo.inspectFuncGetInfo != nil { - mmGetInfo.inspectFuncGetInfo(ctx, code) + mmGetInfo.inspectFuncGetInfo(ctx, userID) } - mm_params := InviteServiceMockGetInfoParams{ctx, code} + mm_params := InviteServiceMockGetInfoParams{ctx, userID} // Record call args mmGetInfo.GetInfoMock.mutex.Lock() @@ -701,7 +701,7 @@ func (mmGetInfo *InviteServiceMock) GetInfo(ctx context.Context, code int64) (ip mm_want := mmGetInfo.GetInfoMock.defaultExpectation.params mm_want_ptrs := mmGetInfo.GetInfoMock.defaultExpectation.paramPtrs - mm_got := InviteServiceMockGetInfoParams{ctx, code} + mm_got := InviteServiceMockGetInfoParams{ctx, userID} if mm_want_ptrs != nil { @@ -710,9 +710,9 @@ func (mmGetInfo *InviteServiceMock) GetInfo(ctx context.Context, code int64) (ip mmGetInfo.GetInfoMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx)) } - if mm_want_ptrs.code != nil && !minimock.Equal(*mm_want_ptrs.code, mm_got.code) { - mmGetInfo.t.Errorf("InviteServiceMock.GetInfo got unexpected parameter code, expected at\n%s:\nwant: %#v\n got: %#v%s\n", - mmGetInfo.GetInfoMock.defaultExpectation.expectationOrigins.originCode, *mm_want_ptrs.code, mm_got.code, minimock.Diff(*mm_want_ptrs.code, mm_got.code)) + if mm_want_ptrs.userID != nil && !minimock.Equal(*mm_want_ptrs.userID, mm_got.userID) { + mmGetInfo.t.Errorf("InviteServiceMock.GetInfo got unexpected parameter userID, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetInfo.GetInfoMock.defaultExpectation.expectationOrigins.originUserID, *mm_want_ptrs.userID, mm_got.userID, minimock.Diff(*mm_want_ptrs.userID, mm_got.userID)) } } else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { @@ -727,9 +727,9 @@ func (mmGetInfo *InviteServiceMock) GetInfo(ctx context.Context, code int64) (ip return (*mm_results).ip1, (*mm_results).err } if mmGetInfo.funcGetInfo != nil { - return mmGetInfo.funcGetInfo(ctx, code) + return mmGetInfo.funcGetInfo(ctx, userID) } - mmGetInfo.t.Fatalf("Unexpected call to InviteServiceMock.GetInfo. %v %v", ctx, code) + mmGetInfo.t.Fatalf("Unexpected call to InviteServiceMock.GetInfo. %v %v", ctx, userID) return } diff --git a/internal/mocks/token_usage_repository_mock.go b/internal/mocks/token_usage_repository_mock.go index 779b8f3..88f1d84 100644 --- a/internal/mocks/token_usage_repository_mock.go +++ b/internal/mocks/token_usage_repository_mock.go @@ -33,6 +33,13 @@ type TokenUsageRepositoryMock struct { afterCreateTxCounter uint64 beforeCreateTxCounter uint64 CreateTxMock mTokenUsageRepositoryMockCreateTx + + funcGetBalanceStatistics func(ctx context.Context, userID int) (averageCost float64, history []*model.WriteOffHistory, err error) + funcGetBalanceStatisticsOrigin string + inspectFuncGetBalanceStatistics func(ctx context.Context, userID int) + afterGetBalanceStatisticsCounter uint64 + beforeGetBalanceStatisticsCounter uint64 + GetBalanceStatisticsMock mTokenUsageRepositoryMockGetBalanceStatistics } // NewTokenUsageRepositoryMock returns a mock for mm_repository.TokenUsageRepository @@ -49,6 +56,9 @@ func NewTokenUsageRepositoryMock(t minimock.Tester) *TokenUsageRepositoryMock { m.CreateTxMock = mTokenUsageRepositoryMockCreateTx{mock: m} m.CreateTxMock.callArgs = []*TokenUsageRepositoryMockCreateTxParams{} + m.GetBalanceStatisticsMock = mTokenUsageRepositoryMockGetBalanceStatistics{mock: m} + m.GetBalanceStatisticsMock.callArgs = []*TokenUsageRepositoryMockGetBalanceStatisticsParams{} + t.Cleanup(m.MinimockFinish) return m @@ -769,6 +779,350 @@ func (m *TokenUsageRepositoryMock) MinimockCreateTxInspect() { } } +type mTokenUsageRepositoryMockGetBalanceStatistics struct { + optional bool + mock *TokenUsageRepositoryMock + defaultExpectation *TokenUsageRepositoryMockGetBalanceStatisticsExpectation + expectations []*TokenUsageRepositoryMockGetBalanceStatisticsExpectation + + callArgs []*TokenUsageRepositoryMockGetBalanceStatisticsParams + mutex sync.RWMutex + + expectedInvocations uint64 + expectedInvocationsOrigin string +} + +// TokenUsageRepositoryMockGetBalanceStatisticsExpectation specifies expectation struct of the TokenUsageRepository.GetBalanceStatistics +type TokenUsageRepositoryMockGetBalanceStatisticsExpectation struct { + mock *TokenUsageRepositoryMock + params *TokenUsageRepositoryMockGetBalanceStatisticsParams + paramPtrs *TokenUsageRepositoryMockGetBalanceStatisticsParamPtrs + expectationOrigins TokenUsageRepositoryMockGetBalanceStatisticsExpectationOrigins + results *TokenUsageRepositoryMockGetBalanceStatisticsResults + returnOrigin string + Counter uint64 +} + +// TokenUsageRepositoryMockGetBalanceStatisticsParams contains parameters of the TokenUsageRepository.GetBalanceStatistics +type TokenUsageRepositoryMockGetBalanceStatisticsParams struct { + ctx context.Context + userID int +} + +// TokenUsageRepositoryMockGetBalanceStatisticsParamPtrs contains pointers to parameters of the TokenUsageRepository.GetBalanceStatistics +type TokenUsageRepositoryMockGetBalanceStatisticsParamPtrs struct { + ctx *context.Context + userID *int +} + +// TokenUsageRepositoryMockGetBalanceStatisticsResults contains results of the TokenUsageRepository.GetBalanceStatistics +type TokenUsageRepositoryMockGetBalanceStatisticsResults struct { + averageCost float64 + history []*model.WriteOffHistory + err error +} + +// TokenUsageRepositoryMockGetBalanceStatisticsOrigins contains origins of expectations of the TokenUsageRepository.GetBalanceStatistics +type TokenUsageRepositoryMockGetBalanceStatisticsExpectationOrigins struct { + origin string + originCtx string + originUserID string +} + +// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning +// the test will fail minimock's automatic final call check if the mocked method was not called at least once. +// Optional() makes method check to work in '0 or more' mode. +// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to +// catch the problems when the expected method call is totally skipped during test run. +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Optional() *mTokenUsageRepositoryMockGetBalanceStatistics { + mmGetBalanceStatistics.optional = true + return mmGetBalanceStatistics +} + +// Expect sets up expected params for TokenUsageRepository.GetBalanceStatistics +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Expect(ctx context.Context, userID int) *mTokenUsageRepositoryMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &TokenUsageRepositoryMockGetBalanceStatisticsExpectation{} + } + + if mmGetBalanceStatistics.defaultExpectation.paramPtrs != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by ExpectParams functions") + } + + mmGetBalanceStatistics.defaultExpectation.params = &TokenUsageRepositoryMockGetBalanceStatisticsParams{ctx, userID} + mmGetBalanceStatistics.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1) + for _, e := range mmGetBalanceStatistics.expectations { + if minimock.Equal(e.params, mmGetBalanceStatistics.defaultExpectation.params) { + mmGetBalanceStatistics.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetBalanceStatistics.defaultExpectation.params) + } + } + + return mmGetBalanceStatistics +} + +// ExpectCtxParam1 sets up expected param ctx for TokenUsageRepository.GetBalanceStatistics +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) ExpectCtxParam1(ctx context.Context) *mTokenUsageRepositoryMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &TokenUsageRepositoryMockGetBalanceStatisticsExpectation{} + } + + if mmGetBalanceStatistics.defaultExpectation.params != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Expect") + } + + if mmGetBalanceStatistics.defaultExpectation.paramPtrs == nil { + mmGetBalanceStatistics.defaultExpectation.paramPtrs = &TokenUsageRepositoryMockGetBalanceStatisticsParamPtrs{} + } + mmGetBalanceStatistics.defaultExpectation.paramPtrs.ctx = &ctx + mmGetBalanceStatistics.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1) + + return mmGetBalanceStatistics +} + +// ExpectUserIDParam2 sets up expected param userID for TokenUsageRepository.GetBalanceStatistics +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) ExpectUserIDParam2(userID int) *mTokenUsageRepositoryMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &TokenUsageRepositoryMockGetBalanceStatisticsExpectation{} + } + + if mmGetBalanceStatistics.defaultExpectation.params != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Expect") + } + + if mmGetBalanceStatistics.defaultExpectation.paramPtrs == nil { + mmGetBalanceStatistics.defaultExpectation.paramPtrs = &TokenUsageRepositoryMockGetBalanceStatisticsParamPtrs{} + } + mmGetBalanceStatistics.defaultExpectation.paramPtrs.userID = &userID + mmGetBalanceStatistics.defaultExpectation.expectationOrigins.originUserID = minimock.CallerInfo(1) + + return mmGetBalanceStatistics +} + +// Inspect accepts an inspector function that has same arguments as the TokenUsageRepository.GetBalanceStatistics +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Inspect(f func(ctx context.Context, userID int)) *mTokenUsageRepositoryMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.inspectFuncGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("Inspect function is already set for TokenUsageRepositoryMock.GetBalanceStatistics") + } + + mmGetBalanceStatistics.mock.inspectFuncGetBalanceStatistics = f + + return mmGetBalanceStatistics +} + +// Return sets up results that will be returned by TokenUsageRepository.GetBalanceStatistics +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Return(averageCost float64, history []*model.WriteOffHistory, err error) *TokenUsageRepositoryMock { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &TokenUsageRepositoryMockGetBalanceStatisticsExpectation{mock: mmGetBalanceStatistics.mock} + } + mmGetBalanceStatistics.defaultExpectation.results = &TokenUsageRepositoryMockGetBalanceStatisticsResults{averageCost, history, err} + mmGetBalanceStatistics.defaultExpectation.returnOrigin = minimock.CallerInfo(1) + return mmGetBalanceStatistics.mock +} + +// Set uses given function f to mock the TokenUsageRepository.GetBalanceStatistics method +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Set(f func(ctx context.Context, userID int) (averageCost float64, history []*model.WriteOffHistory, err error)) *TokenUsageRepositoryMock { + if mmGetBalanceStatistics.defaultExpectation != nil { + mmGetBalanceStatistics.mock.t.Fatalf("Default expectation is already set for the TokenUsageRepository.GetBalanceStatistics method") + } + + if len(mmGetBalanceStatistics.expectations) > 0 { + mmGetBalanceStatistics.mock.t.Fatalf("Some expectations are already set for the TokenUsageRepository.GetBalanceStatistics method") + } + + mmGetBalanceStatistics.mock.funcGetBalanceStatistics = f + mmGetBalanceStatistics.mock.funcGetBalanceStatisticsOrigin = minimock.CallerInfo(1) + return mmGetBalanceStatistics.mock +} + +// When sets expectation for the TokenUsageRepository.GetBalanceStatistics which will trigger the result defined by the following +// Then helper +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) When(ctx context.Context, userID int) *TokenUsageRepositoryMockGetBalanceStatisticsExpectation { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("TokenUsageRepositoryMock.GetBalanceStatistics mock is already set by Set") + } + + expectation := &TokenUsageRepositoryMockGetBalanceStatisticsExpectation{ + mock: mmGetBalanceStatistics.mock, + params: &TokenUsageRepositoryMockGetBalanceStatisticsParams{ctx, userID}, + expectationOrigins: TokenUsageRepositoryMockGetBalanceStatisticsExpectationOrigins{origin: minimock.CallerInfo(1)}, + } + mmGetBalanceStatistics.expectations = append(mmGetBalanceStatistics.expectations, expectation) + return expectation +} + +// Then sets up TokenUsageRepository.GetBalanceStatistics return parameters for the expectation previously defined by the When method +func (e *TokenUsageRepositoryMockGetBalanceStatisticsExpectation) Then(averageCost float64, history []*model.WriteOffHistory, err error) *TokenUsageRepositoryMock { + e.results = &TokenUsageRepositoryMockGetBalanceStatisticsResults{averageCost, history, err} + return e.mock +} + +// Times sets number of times TokenUsageRepository.GetBalanceStatistics should be invoked +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Times(n uint64) *mTokenUsageRepositoryMockGetBalanceStatistics { + if n == 0 { + mmGetBalanceStatistics.mock.t.Fatalf("Times of TokenUsageRepositoryMock.GetBalanceStatistics mock can not be zero") + } + mm_atomic.StoreUint64(&mmGetBalanceStatistics.expectedInvocations, n) + mmGetBalanceStatistics.expectedInvocationsOrigin = minimock.CallerInfo(1) + return mmGetBalanceStatistics +} + +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) invocationsDone() bool { + if len(mmGetBalanceStatistics.expectations) == 0 && mmGetBalanceStatistics.defaultExpectation == nil && mmGetBalanceStatistics.mock.funcGetBalanceStatistics == nil { + return true + } + + totalInvocations := mm_atomic.LoadUint64(&mmGetBalanceStatistics.mock.afterGetBalanceStatisticsCounter) + expectedInvocations := mm_atomic.LoadUint64(&mmGetBalanceStatistics.expectedInvocations) + + return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations) +} + +// GetBalanceStatistics implements mm_repository.TokenUsageRepository +func (mmGetBalanceStatistics *TokenUsageRepositoryMock) GetBalanceStatistics(ctx context.Context, userID int) (averageCost float64, history []*model.WriteOffHistory, err error) { + mm_atomic.AddUint64(&mmGetBalanceStatistics.beforeGetBalanceStatisticsCounter, 1) + defer mm_atomic.AddUint64(&mmGetBalanceStatistics.afterGetBalanceStatisticsCounter, 1) + + mmGetBalanceStatistics.t.Helper() + + if mmGetBalanceStatistics.inspectFuncGetBalanceStatistics != nil { + mmGetBalanceStatistics.inspectFuncGetBalanceStatistics(ctx, userID) + } + + mm_params := TokenUsageRepositoryMockGetBalanceStatisticsParams{ctx, userID} + + // Record call args + mmGetBalanceStatistics.GetBalanceStatisticsMock.mutex.Lock() + mmGetBalanceStatistics.GetBalanceStatisticsMock.callArgs = append(mmGetBalanceStatistics.GetBalanceStatisticsMock.callArgs, &mm_params) + mmGetBalanceStatistics.GetBalanceStatisticsMock.mutex.Unlock() + + for _, e := range mmGetBalanceStatistics.GetBalanceStatisticsMock.expectations { + if minimock.Equal(*e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.averageCost, e.results.history, e.results.err + } + } + + if mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.Counter, 1) + mm_want := mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.params + mm_want_ptrs := mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.paramPtrs + + mm_got := TokenUsageRepositoryMockGetBalanceStatisticsParams{ctx, userID} + + if mm_want_ptrs != nil { + + if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) { + mmGetBalanceStatistics.t.Errorf("TokenUsageRepositoryMock.GetBalanceStatistics got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx)) + } + + if mm_want_ptrs.userID != nil && !minimock.Equal(*mm_want_ptrs.userID, mm_got.userID) { + mmGetBalanceStatistics.t.Errorf("TokenUsageRepositoryMock.GetBalanceStatistics got unexpected parameter userID, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.originUserID, *mm_want_ptrs.userID, mm_got.userID, minimock.Diff(*mm_want_ptrs.userID, mm_got.userID)) + } + + } else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmGetBalanceStatistics.t.Errorf("TokenUsageRepositoryMock.GetBalanceStatistics got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.results + if mm_results == nil { + mmGetBalanceStatistics.t.Fatal("No results are set for the TokenUsageRepositoryMock.GetBalanceStatistics") + } + return (*mm_results).averageCost, (*mm_results).history, (*mm_results).err + } + if mmGetBalanceStatistics.funcGetBalanceStatistics != nil { + return mmGetBalanceStatistics.funcGetBalanceStatistics(ctx, userID) + } + mmGetBalanceStatistics.t.Fatalf("Unexpected call to TokenUsageRepositoryMock.GetBalanceStatistics. %v %v", ctx, userID) + return +} + +// GetBalanceStatisticsAfterCounter returns a count of finished TokenUsageRepositoryMock.GetBalanceStatistics invocations +func (mmGetBalanceStatistics *TokenUsageRepositoryMock) GetBalanceStatisticsAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmGetBalanceStatistics.afterGetBalanceStatisticsCounter) +} + +// GetBalanceStatisticsBeforeCounter returns a count of TokenUsageRepositoryMock.GetBalanceStatistics invocations +func (mmGetBalanceStatistics *TokenUsageRepositoryMock) GetBalanceStatisticsBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmGetBalanceStatistics.beforeGetBalanceStatisticsCounter) +} + +// Calls returns a list of arguments used in each call to TokenUsageRepositoryMock.GetBalanceStatistics. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmGetBalanceStatistics *mTokenUsageRepositoryMockGetBalanceStatistics) Calls() []*TokenUsageRepositoryMockGetBalanceStatisticsParams { + mmGetBalanceStatistics.mutex.RLock() + + argCopy := make([]*TokenUsageRepositoryMockGetBalanceStatisticsParams, len(mmGetBalanceStatistics.callArgs)) + copy(argCopy, mmGetBalanceStatistics.callArgs) + + mmGetBalanceStatistics.mutex.RUnlock() + + return argCopy +} + +// MinimockGetBalanceStatisticsDone returns true if the count of the GetBalanceStatistics invocations corresponds +// the number of defined expectations +func (m *TokenUsageRepositoryMock) MinimockGetBalanceStatisticsDone() bool { + if m.GetBalanceStatisticsMock.optional { + // Optional methods provide '0 or more' call count restriction. + return true + } + + for _, e := range m.GetBalanceStatisticsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + return m.GetBalanceStatisticsMock.invocationsDone() +} + +// MinimockGetBalanceStatisticsInspect logs each unmet expectation +func (m *TokenUsageRepositoryMock) MinimockGetBalanceStatisticsInspect() { + for _, e := range m.GetBalanceStatisticsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to TokenUsageRepositoryMock.GetBalanceStatistics at\n%s with params: %#v", e.expectationOrigins.origin, *e.params) + } + } + + afterGetBalanceStatisticsCounter := mm_atomic.LoadUint64(&m.afterGetBalanceStatisticsCounter) + // if default expectation was set then invocations count should be greater than zero + if m.GetBalanceStatisticsMock.defaultExpectation != nil && afterGetBalanceStatisticsCounter < 1 { + if m.GetBalanceStatisticsMock.defaultExpectation.params == nil { + m.t.Errorf("Expected call to TokenUsageRepositoryMock.GetBalanceStatistics at\n%s", m.GetBalanceStatisticsMock.defaultExpectation.returnOrigin) + } else { + m.t.Errorf("Expected call to TokenUsageRepositoryMock.GetBalanceStatistics at\n%s with params: %#v", m.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.origin, *m.GetBalanceStatisticsMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcGetBalanceStatistics != nil && afterGetBalanceStatisticsCounter < 1 { + m.t.Errorf("Expected call to TokenUsageRepositoryMock.GetBalanceStatistics at\n%s", m.funcGetBalanceStatisticsOrigin) + } + + if !m.GetBalanceStatisticsMock.invocationsDone() && afterGetBalanceStatisticsCounter > 0 { + m.t.Errorf("Expected %d calls to TokenUsageRepositoryMock.GetBalanceStatistics at\n%s but found %d calls", + mm_atomic.LoadUint64(&m.GetBalanceStatisticsMock.expectedInvocations), m.GetBalanceStatisticsMock.expectedInvocationsOrigin, afterGetBalanceStatisticsCounter) + } +} + // MinimockFinish checks that all mocked methods have been called the expected number of times func (m *TokenUsageRepositoryMock) MinimockFinish() { m.finishOnce.Do(func() { @@ -776,6 +1130,8 @@ func (m *TokenUsageRepositoryMock) MinimockFinish() { m.MinimockCreateInspect() m.MinimockCreateTxInspect() + + m.MinimockGetBalanceStatisticsInspect() } }) } @@ -800,5 +1156,6 @@ func (m *TokenUsageRepositoryMock) minimockDone() bool { done := true return done && m.MinimockCreateDone() && - m.MinimockCreateTxDone() + m.MinimockCreateTxDone() && + m.MinimockGetBalanceStatisticsDone() } diff --git a/internal/mocks/user_service_mock.go b/internal/mocks/user_service_mock.go index 1b1a868..5358af4 100644 --- a/internal/mocks/user_service_mock.go +++ b/internal/mocks/user_service_mock.go @@ -26,6 +26,13 @@ type UserServiceMock struct { beforeGetBalanceCounter uint64 GetBalanceMock mUserServiceMockGetBalance + funcGetBalanceStatistics func(ctx context.Context, userID int) (bp1 *mm_service.BalanceStatistics, err error) + funcGetBalanceStatisticsOrigin string + inspectFuncGetBalanceStatistics func(ctx context.Context, userID int) + afterGetBalanceStatisticsCounter uint64 + beforeGetBalanceStatisticsCounter uint64 + GetBalanceStatisticsMock mUserServiceMockGetBalanceStatistics + funcGetInfo func(ctx context.Context, userID int) (up1 *mm_service.UserInfo, err error) funcGetInfoOrigin string inspectFuncGetInfo func(ctx context.Context, userID int) @@ -52,6 +59,9 @@ func NewUserServiceMock(t minimock.Tester) *UserServiceMock { m.GetBalanceMock = mUserServiceMockGetBalance{mock: m} m.GetBalanceMock.callArgs = []*UserServiceMockGetBalanceParams{} + m.GetBalanceStatisticsMock = mUserServiceMockGetBalanceStatistics{mock: m} + m.GetBalanceStatisticsMock.callArgs = []*UserServiceMockGetBalanceStatisticsParams{} + m.GetInfoMock = mUserServiceMockGetInfo{mock: m} m.GetInfoMock.callArgs = []*UserServiceMockGetInfoParams{} @@ -406,6 +416,349 @@ func (m *UserServiceMock) MinimockGetBalanceInspect() { } } +type mUserServiceMockGetBalanceStatistics struct { + optional bool + mock *UserServiceMock + defaultExpectation *UserServiceMockGetBalanceStatisticsExpectation + expectations []*UserServiceMockGetBalanceStatisticsExpectation + + callArgs []*UserServiceMockGetBalanceStatisticsParams + mutex sync.RWMutex + + expectedInvocations uint64 + expectedInvocationsOrigin string +} + +// UserServiceMockGetBalanceStatisticsExpectation specifies expectation struct of the UserService.GetBalanceStatistics +type UserServiceMockGetBalanceStatisticsExpectation struct { + mock *UserServiceMock + params *UserServiceMockGetBalanceStatisticsParams + paramPtrs *UserServiceMockGetBalanceStatisticsParamPtrs + expectationOrigins UserServiceMockGetBalanceStatisticsExpectationOrigins + results *UserServiceMockGetBalanceStatisticsResults + returnOrigin string + Counter uint64 +} + +// UserServiceMockGetBalanceStatisticsParams contains parameters of the UserService.GetBalanceStatistics +type UserServiceMockGetBalanceStatisticsParams struct { + ctx context.Context + userID int +} + +// UserServiceMockGetBalanceStatisticsParamPtrs contains pointers to parameters of the UserService.GetBalanceStatistics +type UserServiceMockGetBalanceStatisticsParamPtrs struct { + ctx *context.Context + userID *int +} + +// UserServiceMockGetBalanceStatisticsResults contains results of the UserService.GetBalanceStatistics +type UserServiceMockGetBalanceStatisticsResults struct { + bp1 *mm_service.BalanceStatistics + err error +} + +// UserServiceMockGetBalanceStatisticsOrigins contains origins of expectations of the UserService.GetBalanceStatistics +type UserServiceMockGetBalanceStatisticsExpectationOrigins struct { + origin string + originCtx string + originUserID string +} + +// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning +// the test will fail minimock's automatic final call check if the mocked method was not called at least once. +// Optional() makes method check to work in '0 or more' mode. +// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to +// catch the problems when the expected method call is totally skipped during test run. +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Optional() *mUserServiceMockGetBalanceStatistics { + mmGetBalanceStatistics.optional = true + return mmGetBalanceStatistics +} + +// Expect sets up expected params for UserService.GetBalanceStatistics +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Expect(ctx context.Context, userID int) *mUserServiceMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &UserServiceMockGetBalanceStatisticsExpectation{} + } + + if mmGetBalanceStatistics.defaultExpectation.paramPtrs != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by ExpectParams functions") + } + + mmGetBalanceStatistics.defaultExpectation.params = &UserServiceMockGetBalanceStatisticsParams{ctx, userID} + mmGetBalanceStatistics.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1) + for _, e := range mmGetBalanceStatistics.expectations { + if minimock.Equal(e.params, mmGetBalanceStatistics.defaultExpectation.params) { + mmGetBalanceStatistics.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetBalanceStatistics.defaultExpectation.params) + } + } + + return mmGetBalanceStatistics +} + +// ExpectCtxParam1 sets up expected param ctx for UserService.GetBalanceStatistics +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) ExpectCtxParam1(ctx context.Context) *mUserServiceMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &UserServiceMockGetBalanceStatisticsExpectation{} + } + + if mmGetBalanceStatistics.defaultExpectation.params != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Expect") + } + + if mmGetBalanceStatistics.defaultExpectation.paramPtrs == nil { + mmGetBalanceStatistics.defaultExpectation.paramPtrs = &UserServiceMockGetBalanceStatisticsParamPtrs{} + } + mmGetBalanceStatistics.defaultExpectation.paramPtrs.ctx = &ctx + mmGetBalanceStatistics.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1) + + return mmGetBalanceStatistics +} + +// ExpectUserIDParam2 sets up expected param userID for UserService.GetBalanceStatistics +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) ExpectUserIDParam2(userID int) *mUserServiceMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &UserServiceMockGetBalanceStatisticsExpectation{} + } + + if mmGetBalanceStatistics.defaultExpectation.params != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Expect") + } + + if mmGetBalanceStatistics.defaultExpectation.paramPtrs == nil { + mmGetBalanceStatistics.defaultExpectation.paramPtrs = &UserServiceMockGetBalanceStatisticsParamPtrs{} + } + mmGetBalanceStatistics.defaultExpectation.paramPtrs.userID = &userID + mmGetBalanceStatistics.defaultExpectation.expectationOrigins.originUserID = minimock.CallerInfo(1) + + return mmGetBalanceStatistics +} + +// Inspect accepts an inspector function that has same arguments as the UserService.GetBalanceStatistics +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Inspect(f func(ctx context.Context, userID int)) *mUserServiceMockGetBalanceStatistics { + if mmGetBalanceStatistics.mock.inspectFuncGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("Inspect function is already set for UserServiceMock.GetBalanceStatistics") + } + + mmGetBalanceStatistics.mock.inspectFuncGetBalanceStatistics = f + + return mmGetBalanceStatistics +} + +// Return sets up results that will be returned by UserService.GetBalanceStatistics +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Return(bp1 *mm_service.BalanceStatistics, err error) *UserServiceMock { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Set") + } + + if mmGetBalanceStatistics.defaultExpectation == nil { + mmGetBalanceStatistics.defaultExpectation = &UserServiceMockGetBalanceStatisticsExpectation{mock: mmGetBalanceStatistics.mock} + } + mmGetBalanceStatistics.defaultExpectation.results = &UserServiceMockGetBalanceStatisticsResults{bp1, err} + mmGetBalanceStatistics.defaultExpectation.returnOrigin = minimock.CallerInfo(1) + return mmGetBalanceStatistics.mock +} + +// Set uses given function f to mock the UserService.GetBalanceStatistics method +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Set(f func(ctx context.Context, userID int) (bp1 *mm_service.BalanceStatistics, err error)) *UserServiceMock { + if mmGetBalanceStatistics.defaultExpectation != nil { + mmGetBalanceStatistics.mock.t.Fatalf("Default expectation is already set for the UserService.GetBalanceStatistics method") + } + + if len(mmGetBalanceStatistics.expectations) > 0 { + mmGetBalanceStatistics.mock.t.Fatalf("Some expectations are already set for the UserService.GetBalanceStatistics method") + } + + mmGetBalanceStatistics.mock.funcGetBalanceStatistics = f + mmGetBalanceStatistics.mock.funcGetBalanceStatisticsOrigin = minimock.CallerInfo(1) + return mmGetBalanceStatistics.mock +} + +// When sets expectation for the UserService.GetBalanceStatistics which will trigger the result defined by the following +// Then helper +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) When(ctx context.Context, userID int) *UserServiceMockGetBalanceStatisticsExpectation { + if mmGetBalanceStatistics.mock.funcGetBalanceStatistics != nil { + mmGetBalanceStatistics.mock.t.Fatalf("UserServiceMock.GetBalanceStatistics mock is already set by Set") + } + + expectation := &UserServiceMockGetBalanceStatisticsExpectation{ + mock: mmGetBalanceStatistics.mock, + params: &UserServiceMockGetBalanceStatisticsParams{ctx, userID}, + expectationOrigins: UserServiceMockGetBalanceStatisticsExpectationOrigins{origin: minimock.CallerInfo(1)}, + } + mmGetBalanceStatistics.expectations = append(mmGetBalanceStatistics.expectations, expectation) + return expectation +} + +// Then sets up UserService.GetBalanceStatistics return parameters for the expectation previously defined by the When method +func (e *UserServiceMockGetBalanceStatisticsExpectation) Then(bp1 *mm_service.BalanceStatistics, err error) *UserServiceMock { + e.results = &UserServiceMockGetBalanceStatisticsResults{bp1, err} + return e.mock +} + +// Times sets number of times UserService.GetBalanceStatistics should be invoked +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Times(n uint64) *mUserServiceMockGetBalanceStatistics { + if n == 0 { + mmGetBalanceStatistics.mock.t.Fatalf("Times of UserServiceMock.GetBalanceStatistics mock can not be zero") + } + mm_atomic.StoreUint64(&mmGetBalanceStatistics.expectedInvocations, n) + mmGetBalanceStatistics.expectedInvocationsOrigin = minimock.CallerInfo(1) + return mmGetBalanceStatistics +} + +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) invocationsDone() bool { + if len(mmGetBalanceStatistics.expectations) == 0 && mmGetBalanceStatistics.defaultExpectation == nil && mmGetBalanceStatistics.mock.funcGetBalanceStatistics == nil { + return true + } + + totalInvocations := mm_atomic.LoadUint64(&mmGetBalanceStatistics.mock.afterGetBalanceStatisticsCounter) + expectedInvocations := mm_atomic.LoadUint64(&mmGetBalanceStatistics.expectedInvocations) + + return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations) +} + +// GetBalanceStatistics implements mm_service.UserService +func (mmGetBalanceStatistics *UserServiceMock) GetBalanceStatistics(ctx context.Context, userID int) (bp1 *mm_service.BalanceStatistics, err error) { + mm_atomic.AddUint64(&mmGetBalanceStatistics.beforeGetBalanceStatisticsCounter, 1) + defer mm_atomic.AddUint64(&mmGetBalanceStatistics.afterGetBalanceStatisticsCounter, 1) + + mmGetBalanceStatistics.t.Helper() + + if mmGetBalanceStatistics.inspectFuncGetBalanceStatistics != nil { + mmGetBalanceStatistics.inspectFuncGetBalanceStatistics(ctx, userID) + } + + mm_params := UserServiceMockGetBalanceStatisticsParams{ctx, userID} + + // Record call args + mmGetBalanceStatistics.GetBalanceStatisticsMock.mutex.Lock() + mmGetBalanceStatistics.GetBalanceStatisticsMock.callArgs = append(mmGetBalanceStatistics.GetBalanceStatisticsMock.callArgs, &mm_params) + mmGetBalanceStatistics.GetBalanceStatisticsMock.mutex.Unlock() + + for _, e := range mmGetBalanceStatistics.GetBalanceStatisticsMock.expectations { + if minimock.Equal(*e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.bp1, e.results.err + } + } + + if mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.Counter, 1) + mm_want := mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.params + mm_want_ptrs := mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.paramPtrs + + mm_got := UserServiceMockGetBalanceStatisticsParams{ctx, userID} + + if mm_want_ptrs != nil { + + if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) { + mmGetBalanceStatistics.t.Errorf("UserServiceMock.GetBalanceStatistics got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx)) + } + + if mm_want_ptrs.userID != nil && !minimock.Equal(*mm_want_ptrs.userID, mm_got.userID) { + mmGetBalanceStatistics.t.Errorf("UserServiceMock.GetBalanceStatistics got unexpected parameter userID, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.originUserID, *mm_want_ptrs.userID, mm_got.userID, minimock.Diff(*mm_want_ptrs.userID, mm_got.userID)) + } + + } else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmGetBalanceStatistics.t.Errorf("UserServiceMock.GetBalanceStatistics got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmGetBalanceStatistics.GetBalanceStatisticsMock.defaultExpectation.results + if mm_results == nil { + mmGetBalanceStatistics.t.Fatal("No results are set for the UserServiceMock.GetBalanceStatistics") + } + return (*mm_results).bp1, (*mm_results).err + } + if mmGetBalanceStatistics.funcGetBalanceStatistics != nil { + return mmGetBalanceStatistics.funcGetBalanceStatistics(ctx, userID) + } + mmGetBalanceStatistics.t.Fatalf("Unexpected call to UserServiceMock.GetBalanceStatistics. %v %v", ctx, userID) + return +} + +// GetBalanceStatisticsAfterCounter returns a count of finished UserServiceMock.GetBalanceStatistics invocations +func (mmGetBalanceStatistics *UserServiceMock) GetBalanceStatisticsAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmGetBalanceStatistics.afterGetBalanceStatisticsCounter) +} + +// GetBalanceStatisticsBeforeCounter returns a count of UserServiceMock.GetBalanceStatistics invocations +func (mmGetBalanceStatistics *UserServiceMock) GetBalanceStatisticsBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmGetBalanceStatistics.beforeGetBalanceStatisticsCounter) +} + +// Calls returns a list of arguments used in each call to UserServiceMock.GetBalanceStatistics. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmGetBalanceStatistics *mUserServiceMockGetBalanceStatistics) Calls() []*UserServiceMockGetBalanceStatisticsParams { + mmGetBalanceStatistics.mutex.RLock() + + argCopy := make([]*UserServiceMockGetBalanceStatisticsParams, len(mmGetBalanceStatistics.callArgs)) + copy(argCopy, mmGetBalanceStatistics.callArgs) + + mmGetBalanceStatistics.mutex.RUnlock() + + return argCopy +} + +// MinimockGetBalanceStatisticsDone returns true if the count of the GetBalanceStatistics invocations corresponds +// the number of defined expectations +func (m *UserServiceMock) MinimockGetBalanceStatisticsDone() bool { + if m.GetBalanceStatisticsMock.optional { + // Optional methods provide '0 or more' call count restriction. + return true + } + + for _, e := range m.GetBalanceStatisticsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + return m.GetBalanceStatisticsMock.invocationsDone() +} + +// MinimockGetBalanceStatisticsInspect logs each unmet expectation +func (m *UserServiceMock) MinimockGetBalanceStatisticsInspect() { + for _, e := range m.GetBalanceStatisticsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to UserServiceMock.GetBalanceStatistics at\n%s with params: %#v", e.expectationOrigins.origin, *e.params) + } + } + + afterGetBalanceStatisticsCounter := mm_atomic.LoadUint64(&m.afterGetBalanceStatisticsCounter) + // if default expectation was set then invocations count should be greater than zero + if m.GetBalanceStatisticsMock.defaultExpectation != nil && afterGetBalanceStatisticsCounter < 1 { + if m.GetBalanceStatisticsMock.defaultExpectation.params == nil { + m.t.Errorf("Expected call to UserServiceMock.GetBalanceStatistics at\n%s", m.GetBalanceStatisticsMock.defaultExpectation.returnOrigin) + } else { + m.t.Errorf("Expected call to UserServiceMock.GetBalanceStatistics at\n%s with params: %#v", m.GetBalanceStatisticsMock.defaultExpectation.expectationOrigins.origin, *m.GetBalanceStatisticsMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcGetBalanceStatistics != nil && afterGetBalanceStatisticsCounter < 1 { + m.t.Errorf("Expected call to UserServiceMock.GetBalanceStatistics at\n%s", m.funcGetBalanceStatisticsOrigin) + } + + if !m.GetBalanceStatisticsMock.invocationsDone() && afterGetBalanceStatisticsCounter > 0 { + m.t.Errorf("Expected %d calls to UserServiceMock.GetBalanceStatistics at\n%s but found %d calls", + mm_atomic.LoadUint64(&m.GetBalanceStatisticsMock.expectedInvocations), m.GetBalanceStatisticsMock.expectedInvocationsOrigin, afterGetBalanceStatisticsCounter) + } +} + type mUserServiceMockGetInfo struct { optional bool mock *UserServiceMock @@ -1098,6 +1451,8 @@ func (m *UserServiceMock) MinimockFinish() { if !m.minimockDone() { m.MinimockGetBalanceInspect() + m.MinimockGetBalanceStatisticsInspect() + m.MinimockGetInfoInspect() m.MinimockGetStatisticsInspect() @@ -1125,6 +1480,7 @@ func (m *UserServiceMock) minimockDone() bool { done := true return done && m.MinimockGetBalanceDone() && + m.MinimockGetBalanceStatisticsDone() && m.MinimockGetInfoDone() && m.MinimockGetStatisticsDone() } diff --git a/internal/repository/interfaces.go b/internal/repository/interfaces.go index 42333c1..02f1ee1 100644 --- a/internal/repository/interfaces.go +++ b/internal/repository/interfaces.go @@ -37,6 +37,7 @@ type InviteRepository interface { CreateTx(ctx context.Context, tx pgx.Tx, invite *model.InviteCode) error FindByCode(ctx context.Context, code int64) (*model.InviteCode, error) FindActiveByCode(ctx context.Context, code int64) (*model.InviteCode, error) + FindActiveByUserID(ctx context.Context, userID int) (*model.InviteCode, error) DecrementCanBeUsedCountTx(ctx context.Context, tx pgx.Tx, code int64) error DeactivateExpired(ctx context.Context) (int, error) GetUserInvites(ctx context.Context, userID int) ([]*model.InviteCode, error) diff --git a/internal/repository/invite.go b/internal/repository/invite.go index ce275c9..06ce28a 100644 --- a/internal/repository/invite.go +++ b/internal/repository/invite.go @@ -110,6 +110,38 @@ func (r *inviteRepository) FindActiveByCode(ctx context.Context, code int64) (*m return invite, nil } +func (r *inviteRepository) FindActiveByUserID(ctx context.Context, userID int) (*model.InviteCode, error) { + query := r.qb.Select( + "id", "user_id", "code", "can_be_used_count", + "is_active", "created_at", "expires_at", + ).From("invite_codes").Where(sq.And{ + sq.Eq{"user_id": userID}, + sq.Eq{"is_active": true}, + sq.Expr("expires_at > now()"), + sq.Expr("can_be_used_count > 0"), + }).OrderBy("created_at DESC").Limit(1) + + sqlQuery, args, err := query.ToSql() + if err != nil { + return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err) + } + + invite := &model.InviteCode{} + err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan( + &invite.ID, &invite.UserID, &invite.Code, &invite.CanBeUsedCount, + &invite.IsActive, &invite.CreatedAt, &invite.ExpiresAt, + ) + + if errors.Is(err, pgx.ErrNoRows) { + return nil, errs.NewBusinessError(errs.InviteInvalidOrExpired, "no active invite code found") + } + if err != nil { + return nil, errs.NewInternalError(errs.DatabaseError, "failed to find active invite code by user", err) + } + + return invite, nil +} + func (r *inviteRepository) DecrementCanBeUsedCountTx(ctx context.Context, tx pgx.Tx, code int64) error { query := r.qb.Update("invite_codes"). Set("can_be_used_count", sq.Expr("can_be_used_count - 1")). diff --git a/internal/service/interfaces.go b/internal/service/interfaces.go index 2a107ed..c2ca84e 100644 --- a/internal/service/interfaces.go +++ b/internal/service/interfaces.go @@ -25,7 +25,7 @@ type UserService interface { type InviteService interface { Generate(ctx context.Context, userID, maxUses, ttlDays int) (*model.InviteCode, error) - GetInfo(ctx context.Context, code int64) (*model.InviteCode, error) + GetInfo(ctx context.Context, userID int) (*model.InviteCode, error) } type RequestService interface { diff --git a/internal/service/invite.go b/internal/service/invite.go index e2b0f5b..2b92ca9 100644 --- a/internal/service/invite.go +++ b/internal/service/invite.go @@ -63,6 +63,6 @@ func (s *inviteService) Generate(ctx context.Context, userID, maxUses, ttlDays i return invite, nil } -func (s *inviteService) GetInfo(ctx context.Context, code int64) (*model.InviteCode, error) { - return s.inviteRepo.FindByCode(ctx, code) +func (s *inviteService) GetInfo(ctx context.Context, userID int) (*model.InviteCode, error) { + return s.inviteRepo.FindActiveByUserID(ctx, userID) } diff --git a/tests/full_flow_test.go b/tests/full_flow_test.go index c9d9ec7..6cebb87 100644 --- a/tests/full_flow_test.go +++ b/tests/full_flow_test.go @@ -164,15 +164,13 @@ func (s *IntegrationSuite) TestFullFlow_InviteCodeLifecycle() { inviteCode := generateInviteResp.Code getInviteInfoReq := &invitepb.GetInfoRequest{ - Code: inviteCode, + UserId: userID, } inviteInfoResp, err := s.inviteClient.GetInfo(ctx, getInviteInfoReq) s.NoError(err) s.Equal(inviteCode, inviteInfoResp.Code) - s.Equal(userID, inviteInfoResp.UserId) s.Equal(generateInviteResp.MaxUses, inviteInfoResp.CanBeUsedCount) - s.True(inviteInfoResp.IsActive) logoutReq := &authpb.LogoutRequest{ AccessToken: loginResp.AccessToken, diff --git a/tests/invite_handler_test.go b/tests/invite_handler_test.go index 2726ca0..835065d 100644 --- a/tests/invite_handler_test.go +++ b/tests/invite_handler_test.go @@ -26,9 +26,9 @@ func (s *IntegrationSuite) TestInviteHandler_GenerateWithNonExistentUser() { s.Contains([]codes.Code{codes.NotFound, codes.Internal, codes.Unknown}, st.Code()) } -func (s *IntegrationSuite) TestInviteHandler_GetInfoWithInvalidCode() { +func (s *IntegrationSuite) TestInviteHandler_GetInfoWithNonExistentUser() { req := &invitepb.GetInfoRequest{ - Code: "999999999", + UserId: 999999, } resp, err := s.inviteClient.GetInfo(context.Background(), req) @@ -41,17 +41,6 @@ func (s *IntegrationSuite) TestInviteHandler_GetInfoWithInvalidCode() { s.Equal(codes.NotFound, st.Code()) } -func (s *IntegrationSuite) TestInviteHandler_GetInfoWithInvalidCodeFormat() { - req := &invitepb.GetInfoRequest{ - Code: "invalid-code", - } - - resp, err := s.inviteClient.GetInfo(context.Background(), req) - - s.Error(err) - s.Nil(resp) -} - func (s *IntegrationSuite) TestInviteHandler_GenerateAndGetInfoFlow() { ctx := context.Background() @@ -87,16 +76,14 @@ func (s *IntegrationSuite) TestInviteHandler_GenerateAndGetInfoFlow() { s.NotNil(generateResp.ExpiresAt) getInfoReq := &invitepb.GetInfoRequest{ - Code: generateResp.Code, + UserId: validateResp.UserId, } infoResp, err := s.inviteClient.GetInfo(ctx, getInfoReq) s.NoError(err) s.NotNil(infoResp) s.Equal(generateResp.Code, infoResp.Code) - s.Equal(validateResp.UserId, infoResp.UserId) s.Equal(generateResp.MaxUses, infoResp.CanBeUsedCount) - s.True(infoResp.IsActive) } func (s *IntegrationSuite) TestInviteHandler_GenerateWithInvalidTTL() { diff --git a/tests/repository_test.go b/tests/repository_test.go index 97f1ccf..41e0509 100644 --- a/tests/repository_test.go +++ b/tests/repository_test.go @@ -85,6 +85,43 @@ func (s *IntegrationSuite) TestRepository_InviteGetUserInvites() { s.GreaterOrEqual(len(invites), 1) } +func (s *IntegrationSuite) TestRepository_InviteFindActiveByUserID() { + inviteRepo := repository.NewInviteRepository(s.pool) + ctx := context.Background() + + var userID int + err := s.pool.QueryRow(ctx, "SELECT id FROM users LIMIT 1").Scan(&userID) + s.Require().NoError(err) + + _, err = s.pool.Exec(ctx, "UPDATE invite_codes SET is_active = false WHERE user_id = $1", userID) + s.Require().NoError(err) + + invite := &model.InviteCode{ + UserID: userID, + Code: time.Now().UnixNano(), + CanBeUsedCount: 5, + ExpiresAt: time.Now().Add(24 * time.Hour), + } + err = inviteRepo.Create(ctx, invite) + s.Require().NoError(err) + + found, err := inviteRepo.FindActiveByUserID(ctx, userID) + s.NoError(err) + s.NotNil(found) + s.Equal(invite.Code, found.Code) + s.Equal(userID, found.UserID) + s.True(found.IsActive) +} + +func (s *IntegrationSuite) TestRepository_InviteFindActiveByUserIDNotFound() { + inviteRepo := repository.NewInviteRepository(s.pool) + ctx := context.Background() + + found, err := inviteRepo.FindActiveByUserID(ctx, 999999) + s.Error(err) + s.Nil(found) +} + func (s *IntegrationSuite) TestRepository_SessionRevoke() { sessionRepo := repository.NewSessionRepository(s.pool) ctx := context.Background()