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  }