Files
jfa-go/jf_activity_test.go
Harvey Tindall d72a5c91cf jf_activity_test: reduce time to run
values were reasonable when testing with a size limit of 20 or
something, now it's ~6000.
2025-12-20 11:58:56 +00:00

137 lines
3.2 KiB
Go

package main
import (
"sync"
"testing"
"time"
"github.com/hrfee/mediabrowser"
)
type MockActivityLogSource struct {
logs []mediabrowser.ActivityLogEntry
lock sync.Mutex
i int
}
func (m *MockActivityLogSource) run(size int, delay time.Duration, finished *bool) {
m.logs = make([]mediabrowser.ActivityLogEntry, size)
for i := range len(m.logs) {
m.logs[i].ID = -1
}
m.i = 0
for i := range len(m.logs) {
m.lock.Lock()
log := mediabrowser.ActivityLogEntry{
ID: int64(i),
Date: mediabrowser.Time{time.Now()},
}
m.logs[i] = log
m.i = i + 1
m.lock.Unlock()
time.Sleep(delay)
}
*finished = true
time.Sleep(delay)
}
func (m *MockActivityLogSource) GetActivityLog(skip, limit int, since time.Time, hasUserID bool) (mediabrowser.ActivityLog, error) {
// This may introduce duplicates, but those are handled fine.
// If we don't do this, things go wrong in a way that seems
// very specific to this test setup, and (imo) is not necessarily
// applicable to a real scenario.
// since = since.Add(-time.Millisecond)
out := make([]mediabrowser.ActivityLogEntry, 0, limit)
count := 0
loopCount := 0
m.lock.Lock()
for i := m.i - 1; count < limit && i >= 0; i-- {
loopCount++
if m.logs[i].Date.After(since) {
out = append(out, m.logs[i])
count++
}
}
m.lock.Unlock()
return mediabrowser.ActivityLog{Items: out}, nil
}
func TestJFActivityLog(t *testing.T) {
t.Parallel()
// FIXME: This test is failing
t.Run("Completeness", func(t *testing.T) {
mock := MockActivityLogSource{}
waitForSync := time.Microsecond
cache := NewJFActivityCache(&mock, waitForSync)
finished := false
count := len(cache.cache) - 10
go mock.run(count, time.Millisecond, &finished)
for {
if err := cache.MaybeSync(); err != nil {
t.Errorf("sync failed: %v", err)
return
}
if cache.dupesInLastSync > 1 {
t.Logf("got %d dupes in last sync\n", cache.dupesInLastSync)
}
if finished {
// Make sure we got everything
time.Sleep(5 * waitForSync)
if err := cache.MaybeSync(); err != nil {
t.Errorf("sync failed: %v", err)
return
}
break
}
}
t.Log(">-\n" + cache.debugString())
if cache.Total != count {
t.Errorf("not all collected: %d < %d", cache.Total, count)
}
})
t.Run("Ordering", func(t *testing.T) {
mock := MockActivityLogSource{}
waitForSync := 300 * time.Microsecond
cache := NewJFActivityCache(&mock, waitForSync)
finished := false
count := len(cache.cache) * 2
go mock.run(count, time.Millisecond, &finished)
for {
if err := cache.MaybeSync(); err != nil {
t.Errorf("sync failed: %v", err)
return
}
if finished {
// Make sure we got everything
time.Sleep(waitForSync)
if err := cache.MaybeSync(); err != nil {
t.Errorf("sync failed: %v", err)
return
}
break
}
}
t.Log(">-\n" + cache.debugString())
i := cache.start
lastID := int64(-1)
t.Logf("cache start=%d, end=%d, total=%d\n", cache.start, cache.end, cache.Total)
for {
if i != cache.start {
if cache.cache[i].ID != lastID-1 {
t.Errorf("next was not previous ID: %d != %d-1 = %d", cache.cache[i].ID, lastID, lastID-1)
return
}
}
lastID = cache.cache[i].ID
if i == cache.end {
break
}
i = (i + 1) % len(cache.cache)
}
})
}