refactor: go fix ftw

This commit is contained in:
2026-02-19 17:37:42 +01:00
parent 9185ffa6b5
commit 85882bae14
21 changed files with 82 additions and 98 deletions

View File

@@ -53,13 +53,13 @@ func TestRunSanitizationFuzzTest(t *testing.T) {
sanitizeFunc := func(input string) string {
result := ""
var result strings.Builder
for _, char := range input {
if char != ' ' {
result += string(char)
result.WriteString(string(char))
}
}
return result
return result.String()
}
result := sanitizeFunc("hello world")
@@ -76,13 +76,13 @@ func TestRunSanitizationFuzzTestWithValidation(t *testing.T) {
sanitizeFunc := func(input string) string {
result := ""
var result strings.Builder
for _, char := range input {
if char != ' ' {
result += string(char)
result.WriteString(string(char))
}
}
return result
return result.String()
}
validateFunc := func(input string) bool {
@@ -1673,7 +1673,7 @@ func TestValidateHTTPRequestWithManyHeaders(t *testing.T) {
helper := NewFuzzTestHelper()
req := httptest.NewRequest("GET", "/api/test", nil)
for i := 0; i < 20; i++ {
for i := range 20 {
req.Header.Set(fmt.Sprintf("Header-%d", i), fmt.Sprintf("Value-%d", i))
}

View File

@@ -158,10 +158,3 @@ func FuzzPostRepository(f *testing.F) {
})
})
}
func min(a, b int) int {
if a < b {
return a
}
return b
}

View File

@@ -1364,7 +1364,7 @@ func TestAuthHandler_ConcurrentAccess(t *testing.T) {
concurrency := 10
done := make(chan bool, concurrency)
for i := 0; i < concurrency; i++ {
for range concurrency {
go func() {
req := createLoginRequest(`{"username":"testuser","password":"Password123!"}`)
w := httptest.NewRecorder()
@@ -1376,7 +1376,7 @@ func TestAuthHandler_ConcurrentAccess(t *testing.T) {
}()
}
for i := 0; i < concurrency; i++ {
for range concurrency {
<-done
}
})

View File

@@ -115,10 +115,7 @@ func NewPageHandler(templatesDir string, authService AuthServiceInterface, postR
if start >= len(s) {
return ""
}
end := start + length
if end > len(s) {
end = len(s)
}
end := min(start+length, len(s))
return s[start:end]
},
"upper": strings.ToUpper,

View File

@@ -33,7 +33,7 @@ func (c *SMTPChecker) Name() string {
func (c *SMTPChecker) Check(ctx context.Context) Result {
start := time.Now()
address := fmt.Sprintf("%s:%d", c.config.Host, c.config.Port)
address := net.JoinHostPort(c.config.Host, fmt.Sprintf("%d", c.config.Port))
result := Result{
Status: StatusHealthy,

View File

@@ -635,7 +635,7 @@ func TestIntegration_CompleteAPIEndpoints(t *testing.T) {
ctx.Suite.EmailSender.Reset()
paginationUser := createAuthenticatedUser(t, ctx.AuthService, ctx.Suite.UserRepo, uniqueTestUsername(t, "pagination_edge"), uniqueTestEmail(t, "pagination_edge"))
for i := 0; i < 5; i++ {
for i := range 5 {
testutils.CreatePostWithRepo(t, ctx.Suite.PostRepo, paginationUser.User.ID, fmt.Sprintf("Pagination Post %d", i), fmt.Sprintf("https://example.com/pag%d", i))
}

View File

@@ -50,7 +50,7 @@ func TestIntegration_RateLimiting(t *testing.T) {
rateLimitConfig.AuthLimit = 2
router, _ := setupRateLimitRouter(t, rateLimitConfig)
for i := 0; i < 2; i++ {
for range 2 {
request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`))
request.Header.Set("Content-Type", "application/json")
recorder := httptest.NewRecorder()
@@ -80,7 +80,7 @@ func TestIntegration_RateLimiting(t *testing.T) {
rateLimitConfig.GeneralLimit = 5
router, _ := setupRateLimitRouter(t, rateLimitConfig)
for i := 0; i < 5; i++ {
for range 5 {
request := httptest.NewRequest("GET", "/api/posts", nil)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
@@ -99,7 +99,7 @@ func TestIntegration_RateLimiting(t *testing.T) {
rateLimitConfig.HealthLimit = 3
router, _ := setupRateLimitRouter(t, rateLimitConfig)
for i := 0; i < 3; i++ {
for range 3 {
request := httptest.NewRequest("GET", "/health", nil)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
@@ -118,7 +118,7 @@ func TestIntegration_RateLimiting(t *testing.T) {
rateLimitConfig.MetricsLimit = 2
router, _ := setupRateLimitRouter(t, rateLimitConfig)
for i := 0; i < 2; i++ {
for range 2 {
request := httptest.NewRequest("GET", "/metrics", nil)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
@@ -138,7 +138,7 @@ func TestIntegration_RateLimiting(t *testing.T) {
rateLimitConfig.GeneralLimit = 10
router, _ := setupRateLimitRouter(t, rateLimitConfig)
for i := 0; i < 2; i++ {
for range 2 {
request := httptest.NewRequest("POST", "/api/auth/login", bytes.NewBufferString(`{"username":"test","password":"test"}`))
request.Header.Set("Content-Type", "application/json")
recorder := httptest.NewRecorder()
@@ -165,7 +165,7 @@ func TestIntegration_RateLimiting(t *testing.T) {
suite.EmailSender.Reset()
user := createAuthenticatedUser(t, authService, suite.UserRepo, uniqueTestUsername(t, "ratelimit_auth"), uniqueTestEmail(t, "ratelimit_auth"))
for i := 0; i < 3; i++ {
for range 3 {
request := httptest.NewRequest("GET", "/api/auth/me", nil)
request.Header.Set("Authorization", "Bearer "+user.Token)
request = testutils.WithUserContext(request, middleware.UserIDKey, user.User.ID)

View File

@@ -283,7 +283,7 @@ func TestIntegration_Repositories(t *testing.T) {
}
voters := make([]*database.User, 5)
for i := 0; i < 5; i++ {
for i := range 5 {
voter := &database.User{
Username: fmt.Sprintf("voter_%d", i),
Email: fmt.Sprintf("voter%d@example.com", i),

View File

@@ -283,16 +283,16 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
t.Run("Concurrent writes", func(t *testing.T) {
done := make(chan bool, numGoroutines)
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
go func(id int) {
defer func() {
if r := recover(); r != nil {
t.Errorf("Goroutine %d panicked: %v", id, r)
}
}()
for j := 0; j < numOps; j++ {
for j := range numOps {
entry := &CacheEntry{
Data: []byte(fmt.Sprintf("data-%d-%d", id, j)),
Data: fmt.Appendf(nil, "data-%d-%d", id, j),
Headers: make(http.Header),
Timestamp: time.Now(),
TTL: 5 * time.Minute,
@@ -306,16 +306,16 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
}(i)
}
for i := 0; i < numGoroutines; i++ {
for range numGoroutines {
<-done
}
})
t.Run("Concurrent reads and writes", func(t *testing.T) {
for i := 0; i < 10; i++ {
for i := range 10 {
entry := &CacheEntry{
Data: []byte(fmt.Sprintf("data-%d", i)),
Data: fmt.Appendf(nil, "data-%d", i),
Headers: make(http.Header),
Timestamp: time.Now(),
TTL: 5 * time.Minute,
@@ -325,16 +325,16 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
done := make(chan bool, numGoroutines*2)
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
go func(id int) {
defer func() {
if r := recover(); r != nil {
t.Errorf("Writer goroutine %d panicked: %v", id, r)
}
}()
for j := 0; j < numOps; j++ {
for j := range numOps {
entry := &CacheEntry{
Data: []byte(fmt.Sprintf("write-%d-%d", id, j)),
Data: fmt.Appendf(nil, "write-%d-%d", id, j),
Headers: make(http.Header),
Timestamp: time.Now(),
TTL: 5 * time.Minute,
@@ -346,14 +346,14 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
}(i)
}
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
go func(id int) {
defer func() {
if r := recover(); r != nil {
t.Errorf("Reader goroutine %d panicked: %v", id, r)
}
}()
for j := 0; j < numOps; j++ {
for j := range numOps {
key := fmt.Sprintf("key-%d", j%10)
cache.Get(key)
}
@@ -368,9 +368,9 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
t.Run("Concurrent deletes", func(t *testing.T) {
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
entry := &CacheEntry{
Data: []byte(fmt.Sprintf("data-%d", i)),
Data: fmt.Appendf(nil, "data-%d", i),
Headers: make(http.Header),
Timestamp: time.Now(),
TTL: 5 * time.Minute,
@@ -379,7 +379,7 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
}
done := make(chan bool, numGoroutines)
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
go func(id int) {
defer func() {
if r := recover(); r != nil {
@@ -391,7 +391,7 @@ func TestInMemoryCacheConcurrent(t *testing.T) {
}(i)
}
for i := 0; i < numGoroutines; i++ {
for range numGoroutines {
<-done
}
})

View File

@@ -318,7 +318,7 @@ func TestConcurrentAccess(t *testing.T) {
collector := NewMetricsCollector(monitor)
done := make(chan bool, 10)
for i := 0; i < 10; i++ {
for range 10 {
go func() {
monitor.LogQuery("SELECT * FROM users", 50*time.Millisecond, nil)
collector.RecordRequest(100*time.Millisecond, false)
@@ -326,7 +326,7 @@ func TestConcurrentAccess(t *testing.T) {
}()
}
for i := 0; i < 10; i++ {
for range 10 {
<-done
}
@@ -384,7 +384,7 @@ func TestThreadSafety(t *testing.T) {
numGoroutines := 100
done := make(chan bool, numGoroutines)
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
go func(id int) {
if id%2 == 0 {
@@ -398,7 +398,7 @@ func TestThreadSafety(t *testing.T) {
}(i)
}
for i := 0; i < numGoroutines; i++ {
for range numGoroutines {
<-done
}

View File

@@ -388,7 +388,7 @@ func TestRateLimiterMaxKeys(t *testing.T) {
limiter := NewRateLimiterWithConfig(1*time.Minute, 10, 5, 1*time.Minute, 2*time.Minute)
defer limiter.StopCleanup()
for i := 0; i < 5; i++ {
for i := range 5 {
key := fmt.Sprintf("key-%d", i)
if !limiter.Allow(key) {
t.Errorf("Key %s should be allowed", key)
@@ -435,7 +435,7 @@ func TestRateLimiterRegistry(t *testing.T) {
request := httptest.NewRequest("GET", "/test", nil)
request.RemoteAddr = "127.0.0.1:12345"
for i := 0; i < 50; i++ {
for i := range 50 {
recorder := httptest.NewRecorder()
server1.ServeHTTP(recorder, request)
if recorder.Code != http.StatusOK {
@@ -443,7 +443,7 @@ func TestRateLimiterRegistry(t *testing.T) {
}
}
for i := 0; i < 50; i++ {
for i := range 50 {
recorder2 := httptest.NewRecorder()
server2.ServeHTTP(recorder2, request)
if recorder2.Code != http.StatusOK {
@@ -463,7 +463,7 @@ func TestRateLimiterRegistry(t *testing.T) {
t.Error("101st request to server2 should be rejected (shared limiter reached limit)")
}
for i := 0; i < 50; i++ {
for i := range 50 {
recorder3 := httptest.NewRecorder()
server3.ServeHTTP(recorder3, request)
if recorder3.Code != http.StatusOK {

View File

@@ -458,13 +458,13 @@ func TestIsRapidRequest(t *testing.T) {
ip := "192.168.1.1"
for i := 0; i < 50; i++ {
for i := range 50 {
if isRapidRequest(ip) {
t.Errorf("Request %d should not be considered rapid", i+1)
}
}
for i := 0; i < 110; i++ {
for i := range 110 {
result := isRapidRequest(ip)
if i < 50 {
if result {

View File

@@ -39,7 +39,7 @@ func TestValidationMiddleware(t *testing.T) {
body, _ := json.Marshal(user)
request := httptest.NewRequest("POST", "/users", bytes.NewBuffer(body))
request.Header.Set("Content-Type", "application/json")
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeOf(TestUser{}))
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeFor[TestUser]())
request = request.WithContext(ctx)
recorder := httptest.NewRecorder()
@@ -70,7 +70,7 @@ func TestValidationMiddleware(t *testing.T) {
body, _ := json.Marshal(user)
request := httptest.NewRequest("POST", "/users", bytes.NewBuffer(body))
request.Header.Set("Content-Type", "application/json")
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeOf(TestUser{}))
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeFor[TestUser]())
request = request.WithContext(ctx)
recorder := httptest.NewRecorder()
@@ -117,7 +117,7 @@ func TestValidationMiddleware(t *testing.T) {
body, _ := json.Marshal(user)
request := httptest.NewRequest("POST", "/users", bytes.NewBuffer(body))
request.Header.Set("Content-Type", "application/json")
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeOf(TestUser{}))
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeFor[TestUser]())
request = request.WithContext(ctx)
recorder := httptest.NewRecorder()
@@ -144,7 +144,7 @@ func TestValidationMiddleware(t *testing.T) {
body, _ := json.Marshal(user)
request := httptest.NewRequest("POST", "/users", bytes.NewBuffer(body))
request.Header.Set("Content-Type", "application/json")
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeOf(TestUser{}))
ctx := context.WithValue(request.Context(), DTOTypeKey, reflect.TypeFor[TestUser]())
request = request.WithContext(ctx)
recorder := httptest.NewRecorder()

View File

@@ -156,7 +156,7 @@ func TestPostRepository_GetAll(t *testing.T) {
user := suite.CreateTestUser("testuser2", "test2@example.com", "password123")
for i := 0; i < 5; i++ {
for i := range 5 {
suite.CreateTestPost(user.ID,
"Post "+strconv.Itoa(i),
"https://example.com/"+strconv.Itoa(i),
@@ -178,7 +178,7 @@ func TestPostRepository_GetAll(t *testing.T) {
user := suite.CreateTestUser("testuser3", "test3@example.com", "password123")
for i := 0; i < 5; i++ {
for i := range 5 {
suite.CreateTestPost(user.ID,
"Post "+strconv.Itoa(i),
"https://example.com/"+strconv.Itoa(i),
@@ -328,7 +328,7 @@ func TestPostRepository_Count(t *testing.T) {
user := suite.CreateTestUser("testuser", "test@example.com", "password123")
for i := 0; i < 5; i++ {
for i := range 5 {
suite.CreateTestPost(user.ID,
"Post "+strconv.Itoa(i),
"https://example.com/"+strconv.Itoa(i),
@@ -506,7 +506,7 @@ func TestPostRepository_Search(t *testing.T) {
user := suite.CreateTestUser("testuser2", "test2@example.com", "password123")
for i := 0; i < 5; i++ {
for i := range 5 {
suite.CreateTestPost(user.ID,
"Go Post "+strconv.Itoa(i),
"https://example.com/go"+strconv.Itoa(i),

View File

@@ -621,7 +621,7 @@ func TestUserRepository_GetPosts(t *testing.T) {
user := suite.CreateTestUser("pagination", "pagination@example.com", "password123")
for i := 0; i < 5; i++ {
for i := range 5 {
suite.CreateTestPost(user.ID,
"Post "+strconv.Itoa(i),
"https://example.com/"+strconv.Itoa(i),
@@ -1089,7 +1089,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
done := make(chan bool, 10)
errors := make(chan error, 10)
for i := 0; i < 10; i++ {
for i := range 10 {
go func(id int) {
defer func() { done <- true }()
user := &database.User{
@@ -1099,7 +1099,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
EmailVerified: true,
}
var err error
for retries := 0; retries < 5; retries++ {
for retries := range 5 {
err = suite.UserRepo.Create(user)
if err == nil {
break
@@ -1116,7 +1116,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
}(i)
}
for i := 0; i < 10; i++ {
for range 10 {
<-done
}
close(errors)
@@ -1142,7 +1142,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
user := suite.CreateTestUser("concurrent_update", "update@example.com", "password123")
done := make(chan bool, 5)
for i := 0; i < 5; i++ {
for i := range 5 {
go func(id int) {
defer func() { done <- true }()
user.Username = fmt.Sprintf("updated%d", id)
@@ -1150,7 +1150,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
}(i)
}
for i := 0; i < 5; i++ {
for range 5 {
<-done
}
@@ -1172,7 +1172,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
done := make(chan bool, 2)
go func() {
var err error
for retries := 0; retries < 5; retries++ {
for retries := range 5 {
err = suite.UserRepo.Delete(user1.ID)
if err == nil {
break
@@ -1187,7 +1187,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
}()
go func() {
var err error
for retries := 0; retries < 5; retries++ {
for retries := range 5 {
err = suite.UserRepo.Delete(user2.ID)
if err == nil {
break
@@ -1210,7 +1210,7 @@ func TestUserRepository_ConcurrentAccess(t *testing.T) {
}
if count > 0 {
var err error
for retries := 0; retries < 5; retries++ {
for retries := range 5 {
count, err = suite.UserRepo.Count()
if err == nil && count == 0 {
break

View File

@@ -90,7 +90,7 @@ func TestEmailService_Performance(t *testing.T) {
start := time.Now()
iterations := 1000
for i := 0; i < iterations; i++ {
for range iterations {
service.GenerateVerificationEmailBody(user.Username, "https://example.com/confirm?token=test")
}
duration := time.Since(start)

View File

@@ -8,6 +8,7 @@ import (
"net"
"net/http"
"net/url"
"slices"
"strings"
"sync"
"time"
@@ -339,10 +340,8 @@ func (s *URLMetadataService) validateURLForSSRF(u *url.URL) error {
if err != nil {
return ErrSSRFBlocked
}
for _, ip := range ips {
if isPrivateOrReservedIP(ip) {
return ErrSSRFBlocked
}
if slices.ContainsFunc(ips, isPrivateOrReservedIP) {
return ErrSSRFBlocked
}
return nil
}
@@ -359,13 +358,7 @@ func isLocalhost(hostname string) bool {
"0:0:0:0:0:0:0:0",
}
for _, name := range localhostNames {
if hostname == name {
return true
}
}
return false
return slices.Contains(localhostNames, hostname)
}
func isPrivateOrReservedIP(ip net.IP) bool {

View File

@@ -285,7 +285,7 @@ func (b *VoteRequestBuilder) Build() VoteRequest {
func (f *TestDataFactory) CreateTestUsers(count int) []*database.User {
users := make([]*database.User, count)
for i := 0; i < count; i++ {
for i := range count {
users[i] = f.NewUserBuilder().
WithID(uint(i + 1)).
WithUsername(fmt.Sprintf("user%d", i+1)).
@@ -297,7 +297,7 @@ func (f *TestDataFactory) CreateTestUsers(count int) []*database.User {
func (f *TestDataFactory) CreateTestPosts(count int) []*database.Post {
posts := make([]*database.Post, count)
for i := 0; i < count; i++ {
for i := range count {
posts[i] = f.NewPostBuilder().
WithID(uint(i+1)).
WithTitle(fmt.Sprintf("Post %d", i+1)).
@@ -332,7 +332,7 @@ func (f *TestDataFactory) CreateTestVotes(count int) []*database.Vote {
func (f *TestDataFactory) CreateTestAuthResults(count int) []*AuthResult {
results := make([]*AuthResult, count)
for i := 0; i < count; i++ {
for i := range count {
results[i] = f.NewAuthResultBuilder().
WithUser(f.NewUserBuilder().
WithID(uint(i + 1)).
@@ -346,7 +346,7 @@ func (f *TestDataFactory) CreateTestAuthResults(count int) []*AuthResult {
func (f *TestDataFactory) CreateTestVoteRequests(count int) []VoteRequest {
requests := make([]VoteRequest, count)
for i := 0; i < count; i++ {
for i := range count {
voteType := database.VoteUp
if i%3 == 0 {
voteType = database.VoteDown
@@ -365,8 +365,9 @@ func (f *TestDataFactory) CreateTestVoteRequests(count int) []VoteRequest {
return requests
}
//go:fix inline
func uintPtr(u uint) *uint {
return &u
return new(u)
}
type E2ETestDataFactory struct {
@@ -450,7 +451,7 @@ func (f *E2ETestDataFactory) CreateMultipleUsers(t *testing.T, count int, userna
var users []*TestUser
timestamp := time.Now().UnixNano()
for i := 0; i < count; i++ {
for i := range count {
uniqueID := timestamp + int64(i)
username := fmt.Sprintf("%s%d", usernamePrefix, uniqueID)
email := fmt.Sprintf("%s%d@example.com", emailPrefix, uniqueID)

View File

@@ -123,12 +123,12 @@ func defaultIfEmpty(value, fallback string) string {
}
func extractTokenFromBody(body string) string {
index := strings.Index(body, "token=")
if index == -1 {
_, after, ok := strings.Cut(body, "token=")
if !ok {
return ""
}
tokenPart := body[index+len("token="):]
tokenPart := after
if delimIdx := strings.IndexAny(tokenPart, "&\"'\\\r\n <>"); delimIdx != -1 {
tokenPart = tokenPart[:delimIdx]

View File

@@ -164,7 +164,7 @@ func getErrorField(resp *APIResponse) (string, bool) {
if resp == nil {
return "", false
}
if dataMap, ok := resp.Data.(map[string]interface{}); ok {
if dataMap, ok := resp.Data.(map[string]any); ok {
if errorVal, ok := dataMap["error"].(string); ok {
return errorVal, true
}

View File

@@ -202,7 +202,7 @@ func camelCaseToWords(s string) string {
return result.String()
}
func ValidateStruct(s interface{}) error {
func ValidateStruct(s any) error {
if s == nil {
return nil
}
@@ -210,7 +210,7 @@ func ValidateStruct(s interface{}) error {
val := reflect.ValueOf(s)
typ := reflect.TypeOf(s)
if val.Kind() == reflect.Ptr {
if val.Kind() == reflect.Pointer {
if val.IsNil() {
return nil
}
@@ -252,9 +252,9 @@ func ValidateStruct(s interface{}) error {
}
var tagName, param string
if idx := strings.Index(tag, "="); idx != -1 {
tagName = tag[:idx]
param = tag[idx+1:]
if before, after, ok := strings.Cut(tag, "="); ok {
tagName = before
param = after
} else {
tagName = tag
}