fixes unprotected write to a map in test, adding race condition detection to CI

This commit is contained in:
Marcin Czenko 2025-10-23 05:07:16 +02:00
parent 55051d99e7
commit c261e6807c
No known key found for this signature in database
GPG Key ID: A0449219BDBA98AE
2 changed files with 26 additions and 7 deletions

View File

@ -46,7 +46,7 @@ jobs:
run: go build -v ./... run: go build -v ./...
- name: Run unit tests - name: Run unit tests
run: gotestsum --packages="./communities" -f standard-verbose --rerun-fails -- -v -count=1 run: gotestsum --packages="./communities" -f standard-verbose --rerun-fails -- -race -v -count=1
- name: Check test coverage for communities package - name: Check test coverage for communities package
run: | run: |

View File

@ -5,6 +5,7 @@ package communities_test
import ( import (
"context" "context"
"sync"
"testing" "testing"
"time" "time"
@ -162,14 +163,20 @@ func (suite *CodexArchiveDownloaderTestifySuite) TestMultipleArchives() {
// Track the order in which archives are started (deterministic) // Track the order in which archives are started (deterministic)
var startOrder []string var startOrder []string
var startOrderMu sync.Mutex
downloader.SetOnStartingArchiveDownload(func(hash string, from, to uint64) { downloader.SetOnStartingArchiveDownload(func(hash string, from, to uint64) {
startOrderMu.Lock()
startOrder = append(startOrder, hash) startOrder = append(startOrder, hash)
startOrderMu.Unlock()
}) })
// Track completed archives (non-deterministic due to concurrency) // Track completed archives (non-deterministic due to concurrency)
completedArchives := make(map[string]bool) completedArchives := make(map[string]bool)
var completedArchivesMu sync.Mutex
downloader.SetOnArchiveDownloaded(func(hash string, from, to uint64) { downloader.SetOnArchiveDownloaded(func(hash string, from, to uint64) {
completedArchivesMu.Lock()
completedArchives[hash] = true completedArchives[hash] = true
completedArchivesMu.Unlock()
}) })
// Initial state verification // Initial state verification
@ -189,16 +196,28 @@ func (suite *CodexArchiveDownloaderTestifySuite) TestMultipleArchives() {
assert.True(suite.T(), downloader.IsDownloadComplete(), "Download should be complete") assert.True(suite.T(), downloader.IsDownloadComplete(), "Download should be complete")
assert.Equal(suite.T(), 3, downloader.GetTotalDownloadedArchivesCount(), "Should have downloaded all 3 archives") assert.Equal(suite.T(), 3, downloader.GetTotalDownloadedArchivesCount(), "Should have downloaded all 3 archives")
// Verify all archives were processed // Verify all archives were processed (with proper synchronization)
assert.Len(suite.T(), completedArchives, 3, "Should have completed exactly 3 archives") completedArchivesMu.Lock()
assert.Contains(suite.T(), completedArchives, "archive-1", "Should have completed archive-1") completedLen := len(completedArchives)
assert.Contains(suite.T(), completedArchives, "archive-2", "Should have completed archive-2") hasArchive1 := completedArchives["archive-1"]
assert.Contains(suite.T(), completedArchives, "archive-3", "Should have completed archive-3") hasArchive2 := completedArchives["archive-2"]
hasArchive3 := completedArchives["archive-3"]
completedArchivesMu.Unlock()
assert.Equal(suite.T(), 3, completedLen, "Should have completed exactly 3 archives")
assert.True(suite.T(), hasArchive1, "Should have completed archive-1")
assert.True(suite.T(), hasArchive2, "Should have completed archive-2")
assert.True(suite.T(), hasArchive3, "Should have completed archive-3")
// Verify sorting: archives should be started in most-recent-first order (deterministic) // Verify sorting: archives should be started in most-recent-first order (deterministic)
// This tests the internal sorting logic before concurrency begins // This tests the internal sorting logic before concurrency begins
startOrderMu.Lock()
startOrderCopy := make([]string, len(startOrder))
copy(startOrderCopy, startOrder)
startOrderMu.Unlock()
expectedStartOrder := []string{"archive-3", "archive-2", "archive-1"} expectedStartOrder := []string{"archive-3", "archive-2", "archive-1"}
assert.Equal(suite.T(), expectedStartOrder, startOrder, "Archives should be started in most-recent-first order") assert.Equal(suite.T(), expectedStartOrder, startOrderCopy, "Archives should be started in most-recent-first order")
suite.T().Log("✅ Multiple archives test passed") suite.T().Log("✅ Multiple archives test passed")
suite.T().Logf(" - Completed %d out of %d archives", len(completedArchives), 3) suite.T().Logf(" - Completed %d out of %d archives", len(completedArchives), 3)