progress_cache_test.go
⎇
Raw
1package service
2
3import (
4 "sync"
5 "testing"
6)
7
8func TestProgressCacheFlushAndSnapshot(t *testing.T) {
9 c := NewProgressCache()
10 c.Start(1)
11
12 c.AppendLog(1, "line1")
13 c.AppendLog(1, "line2")
14
15 if got := c.Snapshot(1); got != "line1\nline2\n" {
16 t.Errorf("Snapshot = %q, want the full buffer", got)
17 }
18
19 // First flush returns everything appended so far.
20 if first := c.FlushLogs(1); first != "line1\nline2\n" {
21 t.Errorf("first flush = %q, want full buffer", first)
22 }
23 // With nothing new, a flush returns empty (no DB rewrite of the whole log).
24 if again := c.FlushLogs(1); again != "" {
25 t.Errorf("flush with no new logs = %q, want empty", again)
26 }
27 // A later flush returns only the newly appended tail.
28 c.AppendLog(1, "line3")
29 if tail := c.FlushLogs(1); tail != "line3\n" {
30 t.Errorf("incremental flush = %q, want only the new tail", tail)
31 }
32
33 if got := c.Snapshot(999); got != "" {
34 t.Errorf("Snapshot of unknown id = %q, want empty", got)
35 }
36}
37
38// TestProgressCacheConcurrentSnapshot exercises the data-race fix: a reader
39// (Snapshot) and the writer (AppendLog) touch the same strings.Builder, so they
40// must be serialized by the cache lock. Run with -race to catch a regression.
41func TestProgressCacheConcurrentSnapshot(t *testing.T) {
42 c := NewProgressCache()
43 c.Start(1)
44
45 var wg sync.WaitGroup
46 wg.Add(2)
47 go func() {
48 defer wg.Done()
49 for i := 0; i < 2000; i++ {
50 c.AppendLog(1, "log line")
51 }
52 }()
53 go func() {
54 defer wg.Done()
55 for i := 0; i < 2000; i++ {
56 _ = c.Snapshot(1)
57 }
58 }()
59 wg.Wait()
60}
61