package tests import ( "fmt" "sync" "sync/atomic" "time" authpb "git.techease.ru/Smart-search/smart-search-back/pkg/pb/auth" ) func (s *IntegrationSuite) TestConcurrent_Registration_WithSingleInviteCode() { maxUses := 3 inviteCode := s.createActiveInviteCode(maxUses) var wg sync.WaitGroup var successCount int32 var errorCount int32 goroutines := 20 startBarrier := make(chan struct{}) for i := 0; i < goroutines; i++ { wg.Add(1) go func(idx int) { defer wg.Done() <-startBarrier email := fmt.Sprintf("concurrent_reg_%d_%d@example.com", idx, time.Now().UnixNano()) _, err := s.authClient.Register(s.ctx, &authpb.RegisterRequest{ Email: email, Password: "testpassword123", Name: fmt.Sprintf("User %d", idx), Phone: fmt.Sprintf("+1%010d", idx), InviteCode: inviteCode, Ip: "127.0.0.1", UserAgent: "integration-test", }) if err == nil { atomic.AddInt32(&successCount, 1) } else { atomic.AddInt32(&errorCount, 1) } }(i) } close(startBarrier) wg.Wait() s.T().Logf("Registration results - Success: %d, Errors: %d", successCount, errorCount) s.LessOrEqual(int(successCount), maxUses, "Количество успешных регистраций (%d) не должно превышать лимит invite-кода (%d)", successCount, maxUses) remainingUses := s.getInviteCodeUsageCount(inviteCode) s.T().Logf("Remaining invite code uses: %d", remainingUses) s.Equal(maxUses-int(successCount), remainingUses, "Оставшееся количество использований должно соответствовать успешным регистрациям") } func (s *IntegrationSuite) TestConcurrent_Registration_InviteCodeDeactivation() { maxUses := 2 inviteCode := s.createActiveInviteCode(maxUses) s.True(s.isInviteCodeActive(inviteCode), "Invite code должен быть активен изначально") var wg sync.WaitGroup var successCount int32 goroutines := 10 startBarrier := make(chan struct{}) for i := 0; i < goroutines; i++ { wg.Add(1) go func(idx int) { defer wg.Done() <-startBarrier email := fmt.Sprintf("deactivation_test_%d_%d@example.com", idx, time.Now().UnixNano()) _, err := s.authClient.Register(s.ctx, &authpb.RegisterRequest{ Email: email, Password: "testpassword123", Name: fmt.Sprintf("User %d", idx), Phone: fmt.Sprintf("+2%010d", idx), InviteCode: inviteCode, Ip: "127.0.0.1", UserAgent: "integration-test", }) if err == nil { atomic.AddInt32(&successCount, 1) } }(i) } close(startBarrier) wg.Wait() s.T().Logf("Registration success count: %d", successCount) s.LessOrEqual(int(successCount), maxUses, "Не должно быть больше %d успешных регистраций", maxUses) remainingUses := s.getInviteCodeUsageCount(inviteCode) s.GreaterOrEqual(remainingUses, 0, "Количество использований не должно быть отрицательным") } func (s *IntegrationSuite) TestConcurrent_Registration_MultipleInviteCodes() { inviteCode1 := s.createActiveInviteCode(2) inviteCode2 := s.createActiveInviteCode(2) var wg sync.WaitGroup var success1, success2 int32 goroutines := 10 startBarrier := make(chan struct{}) for i := 0; i < goroutines; i++ { wg.Add(1) go func(idx int) { defer wg.Done() <-startBarrier var code int64 if idx%2 == 0 { code = inviteCode1 } else { code = inviteCode2 } email := fmt.Sprintf("multi_invite_%d_%d@example.com", idx, time.Now().UnixNano()) _, err := s.authClient.Register(s.ctx, &authpb.RegisterRequest{ Email: email, Password: "testpassword123", Name: fmt.Sprintf("User %d", idx), Phone: fmt.Sprintf("+3%010d", idx), InviteCode: code, Ip: "127.0.0.1", UserAgent: "integration-test", }) if err == nil { if code == inviteCode1 { atomic.AddInt32(&success1, 1) } else { atomic.AddInt32(&success2, 1) } } }(i) } close(startBarrier) wg.Wait() s.T().Logf("Multi-invite results - Code1: %d, Code2: %d", success1, success2) s.LessOrEqual(int(success1), 2, "Invite code 1 не должен превышать лимит") s.LessOrEqual(int(success2), 2, "Invite code 2 не должен превышать лимит") remaining1 := s.getInviteCodeUsageCount(inviteCode1) remaining2 := s.getInviteCodeUsageCount(inviteCode2) s.Equal(2-int(success1), remaining1, "Остаток invite code 1 должен соответствовать успешным регистрациям") s.Equal(2-int(success2), remaining2, "Остаток invite code 2 должен соответствовать успешным регистрациям") }