59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
package analyze
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/dundee/gdu/v5/internal/testdir"
|
|
"github.com/dundee/gdu/v5/pkg/fs"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// TestStoredDirUpdateStatsLockedAgainstReaders recomputes a StoredDir's stats
|
|
// while another goroutine reads them through the synchronized scalar accessors
|
|
// (GetSize, GetUsage, GetFlag, GetMtime, GetItemCount). Those readers take the
|
|
// embedded Dir mutex, so updateStats has to write the same fields under that
|
|
// mutex. Run with -race: without the locking the writes in updateStats race the
|
|
// reads here.
|
|
func TestStoredDirUpdateStatsLockedAgainstReaders(t *testing.T) {
|
|
fin := testdir.CreateTestDir()
|
|
defer fin()
|
|
|
|
a := CreateStoredAnalyzer("/tmp/badger")
|
|
dir := a.AnalyzeDir(
|
|
"test_dir", func(_, _ string) bool { return false }, func(_ string) bool { return false },
|
|
).(*StoredDir)
|
|
a.GetDone().Wait()
|
|
|
|
const rounds = 200
|
|
|
|
stop := make(chan struct{})
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
for {
|
|
select {
|
|
case <-stop:
|
|
return
|
|
default:
|
|
}
|
|
_ = dir.GetSize()
|
|
_ = dir.GetUsage()
|
|
_ = dir.GetFlag()
|
|
_ = dir.GetMtime()
|
|
_ = dir.GetItemCount()
|
|
}
|
|
}()
|
|
|
|
for range rounds {
|
|
dir.UpdateStats(make(fs.HardLinkedItems))
|
|
}
|
|
close(stop)
|
|
wg.Wait()
|
|
|
|
// stats stay correct after the concurrent recomputation
|
|
assert.Equal(t, int64(7+4096*3), dir.GetSize())
|
|
assert.Equal(t, int64(5), dir.GetItemCount())
|
|
}
|