github.com/cilium/cilium@v1.16.2/pkg/spanstat/spanstat_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package spanstat 5 6 import ( 7 "fmt" 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestSpanStatStart(t *testing.T) { 16 span1 := Start() 17 span1.EndError(nil) 18 require.NotEqual(t, time.Duration(0), span1.Total()) 19 } 20 21 func TestSpanStat(t *testing.T) { 22 span1 := SpanStat{} 23 24 // no spans measured yet 25 require.Equal(t, time.Duration(0), span1.Total()) 26 require.Equal(t, time.Duration(0), span1.SuccessTotal()) 27 require.Equal(t, time.Duration(0), span1.FailureTotal()) 28 29 // End() without Start() 30 span1.End(true) 31 require.Equal(t, time.Duration(0), span1.Total()) 32 require.Equal(t, time.Duration(0), span1.SuccessTotal()) 33 require.Equal(t, time.Duration(0), span1.FailureTotal()) 34 35 // Start() but no end yet 36 span1.Start() 37 require.Equal(t, time.Duration(0), span1.Total()) 38 require.Equal(t, time.Duration(0), span1.SuccessTotal()) 39 require.Equal(t, time.Duration(0), span1.FailureTotal()) 40 41 // First span measured with End() 42 span1.End(true) 43 spanTotal1 := span1.Total() 44 spanSuccessTotal1 := span1.SuccessTotal() 45 spanFailureTotal1 := span1.FailureTotal() 46 require.NotEqual(t, time.Duration(0), span1.Total()) 47 require.NotEqual(t, time.Duration(0), span1.SuccessTotal()) 48 require.Equal(t, time.Duration(0), span1.FailureTotal()) 49 require.Equal(t, span1.Total(), span1.SuccessTotal()+span1.FailureTotal()) 50 51 // End() without a prior Start(), no change 52 span1.End(true) 53 require.Equal(t, spanTotal1, span1.Total()) 54 require.Equal(t, spanSuccessTotal1, span1.SuccessTotal()) 55 require.Equal(t, spanFailureTotal1, span1.FailureTotal()) 56 57 span1.Start() 58 time.Sleep(time.Millisecond * 100) 59 span1.End(false) // ensure second measure is different from first. 60 require.NotEqual(t, spanTotal1, span1.Total()) 61 require.Equal(t, spanSuccessTotal1, span1.SuccessTotal()) 62 require.NotEqual(t, spanFailureTotal1, span1.FailureTotal()) 63 require.Equal(t, span1.Total(), span1.SuccessTotal()+span1.FailureTotal()) 64 65 span1.Reset() 66 require.Equal(t, time.Duration(0), span1.Total()) 67 require.Equal(t, time.Duration(0), span1.SuccessTotal()) 68 require.Equal(t, time.Duration(0), span1.FailureTotal()) 69 } 70 71 func TestSpanStatSeconds(t *testing.T) { 72 span1 := Start() 73 require.NotEqual(t, float64(0), span1.Seconds()) 74 } 75 76 func TestSpanStatSecondsRaceCondition(t *testing.T) { 77 span1 := Start() 78 var wg sync.WaitGroup 79 80 for i := 0; i < 10; i++ { 81 wg.Add(1) 82 go func(span *SpanStat) { 83 defer wg.Done() 84 require.NotEqual(t, float64(0), span1.Seconds()) 85 }(span1) 86 } 87 wg.Wait() 88 } 89 90 func TestSpanStatRaceCondition(t *testing.T) { 91 type fields struct { 92 runFunc func(span *SpanStat) float64 93 } 94 tests := []struct { 95 name string 96 fields fields 97 }{ 98 { 99 name: "End function", 100 fields: fields{ 101 runFunc: func(span *SpanStat) float64 { 102 return span.End(true).Seconds() 103 }, 104 }, 105 }, 106 { 107 name: "EndError function", 108 fields: fields{ 109 runFunc: func(span *SpanStat) float64 { 110 return span.EndError(fmt.Errorf("dummy error")).Seconds() 111 }, 112 }, 113 }, 114 { 115 name: "Seconds function", 116 fields: fields{ 117 runFunc: func(span *SpanStat) float64 { 118 return span.Seconds() 119 }, 120 }, 121 }, 122 { 123 name: "Total function", 124 fields: fields{ 125 runFunc: func(span *SpanStat) float64 { 126 return span.Total().Seconds() + 1 127 }, 128 }, 129 }, 130 { 131 name: "FailureTotal function", 132 fields: fields{ 133 runFunc: func(span *SpanStat) float64 { 134 return span.FailureTotal().Seconds() + 1 135 }, 136 }, 137 }, 138 { 139 name: "SuccessTotal function", 140 fields: fields{ 141 runFunc: func(span *SpanStat) float64 { 142 return span.SuccessTotal().Seconds() + 1 143 }, 144 }, 145 }, 146 { 147 name: "Reset function", 148 fields: fields{ 149 runFunc: func(span *SpanStat) float64 { 150 span.Reset() 151 return 1 152 }, 153 }, 154 }, 155 } 156 157 for _, tt := range tests { 158 t.Run(tt.name, func(t *testing.T) { 159 span := Start() 160 var wg sync.WaitGroup 161 162 for i := 0; i < 5; i++ { 163 wg.Add(1) 164 go func(span *SpanStat) { 165 defer wg.Done() 166 require.NotEqual(t, tt.fields.runFunc(span), float64(0)) 167 }(span) 168 } 169 wg.Wait() 170 }) 171 } 172 }