github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/stat/set_test.go (about) 1 // Copyright 2024 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package stat 5 6 import ( 7 "fmt" 8 "math/rand" 9 "sync/atomic" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func TestSet(t *testing.T) { 17 a := assert.New(t) 18 set := newSet(4, false) 19 a.Empty(set.Collect(All)) 20 set.RenderGraphs() 21 22 v0 := set.New("v0", "desc0") 23 a.Equal(v0.Val(), 0) 24 v0.Add(1) 25 a.Equal(v0.Val(), 1) 26 v0.Add(1) 27 a.Equal(v0.Val(), 2) 28 29 vv1 := 0 30 v1 := set.New("v1", "desc1", Simple, func() int { return vv1 }) 31 a.Equal(v1.Val(), 0) 32 vv1 = 11 33 a.Equal(v1.Val(), 11) 34 a.Panics(func() { v1.Add(1) }) 35 36 v2 := set.New("v2", "desc2", Console, func(v int, period time.Duration) string { 37 return fmt.Sprintf("v2 %v %v", v, period) 38 }) 39 v2.Add(100) 40 41 v3 := set.New("v3", "desc3", Link("/v3"), NoGraph, Distribution{}) 42 a.Equal(v3.Val(), 0) 43 v3.Add(10) 44 a.Equal(v3.Val(), 10) 45 v3.Add(20) 46 a.Equal(v3.Val(), 15) 47 v3.Add(20) 48 a.Equal(v3.Val(), 16) 49 v3.Add(30) 50 a.Equal(v3.Val(), 20) 51 v3.Add(30) 52 a.Equal(v3.Val(), 22) 53 v3.Add(30) 54 v3.Add(30) 55 a.Equal(v3.Val(), 24) 56 57 v4 := set.New("v4", "desc4", Rate{}, Graph("graph")) 58 v4.Add(10) 59 a.Equal(v4.Val(), 10) 60 v4.Add(10) 61 a.Equal(v4.Val(), 20) 62 63 a.Panics(func() { set.New("v0", "desc0", float64(1)) }) 64 65 ui := set.Collect(All) 66 a.Equal(len(ui), 5) 67 a.Equal(ui[0], UI{"v2", "desc2", "", Console, "v2 100 1s", 100}) 68 a.Equal(ui[1], UI{"v1", "desc1", "", Simple, "11", 11}) 69 a.Equal(ui[2], UI{"v0", "desc0", "", All, "2", 2}) 70 a.Equal(ui[3], UI{"v3", "desc3", "/v3", All, "24", 24}) 71 a.Equal(ui[4], UI{"v4", "desc4", "", All, "20 (20/sec)", 20}) 72 73 ui1 := set.Collect(Simple) 74 a.Equal(len(ui1), 2) 75 a.Equal(ui1[0].Name, "v2") 76 a.Equal(ui1[1].Name, "v1") 77 78 ui2 := set.Collect(Console) 79 a.Equal(len(ui2), 1) 80 a.Equal(ui2[0].Name, "v2") 81 82 set.RenderGraphs() 83 } 84 85 func TestSetRateFormat(t *testing.T) { 86 a := assert.New(t) 87 set := newSet(4, false) 88 v := set.New("v", "desc", Rate{}) 89 a.Equal(set.Collect(All)[0].Value, "0 (0/hour)") 90 v.Add(1) 91 a.Equal(set.Collect(All)[0].Value, "1 (60/min)") 92 v.Add(99) 93 a.Equal(set.Collect(All)[0].Value, "100 (100/sec)") 94 } 95 96 func TestSetHistoryCounter(t *testing.T) { 97 a := assert.New(t) 98 set := newSet(4, false) 99 v := set.New("v0", "desc0") 100 set.tick() 101 hist := func() []float64 { return set.graphs["v0"].lines["v0"].data[:set.historyPos] } 102 step := func(n int) []float64 { 103 v.Add(n) 104 set.tick() 105 return hist() 106 } 107 a.Equal(hist(), []float64{0}) 108 v.Add(1) 109 v.Add(1) 110 a.Equal(hist(), []float64{0}) 111 set.tick() 112 a.Equal(hist(), []float64{0, 2}) 113 v.Add(3) 114 a.Equal(hist(), []float64{0, 2}) 115 set.tick() 116 a.Equal(hist(), []float64{0, 2, 5}) 117 a.Equal(step(-1), []float64{0, 2, 5, 4}) 118 // Compacted, each new history value will require 2 steps. 119 a.Equal(step(7), []float64{2, 5}) 120 a.Equal(step(-10), []float64{2, 5, 11}) 121 a.Equal(step(2), []float64{2, 5, 11}) 122 a.Equal(step(1), []float64{2, 5, 11, 4}) 123 // 4 steps for each new value. 124 a.Equal(step(1), []float64{5, 11}) 125 a.Equal(step(1), []float64{5, 11}) 126 a.Equal(step(1), []float64{5, 11}) 127 a.Equal(step(1), []float64{5, 11, 8}) 128 } 129 130 func TestSetHistoryRate(t *testing.T) { 131 a := assert.New(t) 132 set := newSet(4, false) 133 v := set.New("v0", "desc0", Rate{}) 134 step := func(n int) []float64 { 135 v.Add(n) 136 set.tick() 137 return set.graphs["v0"].lines["v0"].data[:set.historyPos] 138 } 139 a.Equal(step(3), []float64{3}) 140 a.Equal(step(1), []float64{3, 1}) 141 a.Equal(step(2), []float64{3, 1, 2}) 142 a.Equal(step(5), []float64{3, 1, 2, 5}) 143 a.Equal(step(1), []float64{2, 3.5}) 144 a.Equal(step(2), []float64{2, 3.5, 1.5}) 145 a.Equal(step(2), []float64{2, 3.5, 1.5}) 146 a.Equal(step(4), []float64{2, 3.5, 1.5, 3}) 147 a.Equal(step(1), []float64{2.75, 2.25}) 148 a.Equal(step(2), []float64{2.75, 2.25}) 149 a.Equal(step(3), []float64{2.75, 2.25}) 150 a.Equal(step(4), []float64{2.75, 2.25, 2.5}) 151 } 152 153 func TestSetHistoryDistribution(t *testing.T) { 154 a := assert.New(t) 155 set := newSet(4, false) 156 v := set.New("v0", "desc0", Distribution{}) 157 step := func(n int) [3][]float64 { 158 v.Add(n) 159 set.tick() 160 var history [3][]float64 161 for p, percent := range []int{10, 50, 90} { 162 history[p] = make([]float64, set.historyPos) 163 for i := 0; i < set.historyPos; i++ { 164 hist := set.graphs["v0"].lines["v0"].hist[i] 165 if hist != nil { 166 history[p][i] = hist.Quantile(float64(percent) / 100) 167 } 168 } 169 } 170 return history 171 } 172 a.Equal(step(3), [3][]float64{{3}, {3}, {3}}) 173 a.Equal(step(6), [3][]float64{{3, 6}, {3, 6}, {3, 6}}) 174 a.Equal(step(1), [3][]float64{{3, 6, 1}, {3, 6, 1}, {3, 6, 1}}) 175 a.Equal(step(2), [3][]float64{{3, 6, 1, 2}, {3, 6, 1, 2}, {3, 6, 1, 2}}) 176 a.Equal(step(1), [3][]float64{{3, 1}, {3, 1}, {3, 1}}) 177 a.Equal(step(10), [3][]float64{{3, 1, 1}, {3, 1, 1}, {3, 1, 10}}) 178 } 179 180 func TestSetStress(t *testing.T) { 181 set := newSet(4, false) 182 var stop atomic.Bool 183 var seq atomic.Uint64 184 start := func(f func()) { 185 go func() { 186 for !stop.Load() { 187 f() 188 } 189 }() 190 } 191 for p := 0; p < 2; p++ { 192 for _, opt := range []any{Link(""), NoGraph, Rate{}, Distribution{}} { 193 go func() { 194 v := set.New(fmt.Sprintf("v%v", seq.Add(1)), "desc", opt) 195 for p1 := 0; p1 < 2; p1++ { 196 start(func() { v.Val() }) 197 start(func() { v.Add(rand.Intn(10000)) }) 198 } 199 }() 200 } 201 go func() { 202 var vv atomic.Uint64 203 v := set.New(fmt.Sprintf("v%v", seq.Add(1)), "desc", 204 func() int { return int(vv.Load()) }) 205 for p1 := 0; p1 < 2; p1++ { 206 start(func() { v.Val() }) 207 start(func() { vv.Store(uint64(rand.Intn(10000))) }) 208 } 209 }() 210 start(func() { set.Collect(All) }) 211 start(func() { set.RenderGraphs() }) 212 start(func() { set.tick() }) 213 } 214 time.Sleep(time.Second) 215 stop.Store(true) 216 }