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