github.com/mailgun/holster/v4@v4.20.0/functional/functional_test.go (about) 1 package functional_test 2 3 import ( 4 "bufio" 5 "bytes" 6 "context" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/mailgun/holster/v4/functional" 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestFunctional(t *testing.T) { 16 ctx := context.Background() 17 18 t.Run("Run()", func(t *testing.T) { 19 t.Run("Happy path", func(t *testing.T) { 20 testFunc := func(_ *functional.T) {} 21 pass := functional.Run(ctx, testFunc) 22 assert.True(t, pass) 23 }) 24 25 t.Run("Test fails", func(t *testing.T) { 26 testFunc := func(ft *functional.T) { 27 ft.FailNow() 28 } 29 pass := functional.Run(ctx, testFunc) 30 assert.False(t, pass) 31 }) 32 33 t.Run("Nested test", func(t *testing.T) { 34 t.Run("Passes", func(t *testing.T) { 35 testFunc := func(ft *functional.T) { 36 ft.Run("Subtest 1", func(_ *functional.T) { 37 }) 38 } 39 pass := functional.Run(ctx, testFunc) 40 assert.True(t, pass) 41 }) 42 43 t.Run("Fails", func(t *testing.T) { 44 testFunc := func(ft *functional.T) { 45 ft.Run("Subtest 1", func(ft *functional.T) { 46 ft.FailNow() 47 }) 48 } 49 pass := functional.Run(ctx, testFunc) 50 assert.False(t, pass) 51 }) 52 }) 53 54 t.Run("WithWriter()", func(t *testing.T) { 55 testFunc := func(ft *functional.T) { 56 ft.Log("Foobar") 57 } 58 var buf bytes.Buffer 59 twriter := bufio.NewWriter(&buf) 60 pass := functional.Run(ctx, testFunc, functional.WithWriter(twriter)) 61 assert.True(t, pass) 62 assert.Contains(t, "Foobar", buf.String()) 63 }) 64 65 t.Run("WithArgs()", func(t *testing.T) { 66 args := []string{"A", "B", "C"} 67 testFunc := func(ft *functional.T) { 68 assert.Equal(t, args, ft.Args()) 69 } 70 pass := functional.Run(ctx, testFunc, functional.WithArgs(args...)) 71 assert.True(t, pass) 72 }) 73 74 t.Run("Skip", func(t *testing.T) { 75 var mutex sync.Mutex 76 var before, after bool 77 testFunc := func(ft *functional.T) { 78 mutex.Lock() 79 defer mutex.Unlock() 80 before = true 81 ft.SkipNow() 82 after = true 83 } 84 pass := functional.Run(ctx, testFunc) 85 assert.True(t, pass) 86 87 mutex.Lock() 88 defer mutex.Unlock() 89 assert.True(t, before) 90 assert.False(t, after) 91 }) 92 }) 93 94 t.Run("RunSuite()", func(t *testing.T) { 95 t.Run("Happy path", func(t *testing.T) { 96 var counter int 97 testFunc1 := func(_ *functional.T) { 98 counter++ 99 } 100 testFunc2 := func(_ *functional.T) { 101 counter++ 102 } 103 tests := []functional.TestFunc{testFunc1, testFunc2} 104 pass := functional.RunSuite(ctx, "Foobar suite", tests) 105 assert.True(t, pass) 106 assert.Equal(t, 2, counter) 107 }) 108 109 t.Run("Partial failure", func(t *testing.T) { 110 var counter int 111 testFunc1 := func(_ *functional.T) { 112 counter++ 113 } 114 testFunc2 := func(ft *functional.T) { 115 counter++ 116 ft.FailNow() 117 } 118 tests := []functional.TestFunc{testFunc1, testFunc2} 119 pass := functional.RunSuite(ctx, "Foobar suite", tests) 120 assert.False(t, pass) 121 assert.Equal(t, 2, counter) 122 }) 123 124 t.Run("Complete failure", func(t *testing.T) { 125 var counter int 126 testFunc1 := func(ft *functional.T) { 127 counter++ 128 ft.FailNow() 129 } 130 testFunc2 := func(ft *functional.T) { 131 counter++ 132 ft.FailNow() 133 } 134 tests := []functional.TestFunc{testFunc1, testFunc2} 135 pass := functional.RunSuite(ctx, "Foobar suite", tests) 136 assert.False(t, pass) 137 assert.Equal(t, 2, counter) 138 }) 139 }) 140 141 t.Run("RunBenchmarkTimes()", func(t *testing.T) { 142 t.Run("Happy path", func(t *testing.T) { 143 testCases := []struct { 144 Name string 145 N int 146 Delay time.Duration 147 }{ 148 {Name: "Once", N: 1, Delay: 5 * time.Millisecond}, 149 {Name: "2x", N: 2, Delay: 5 * time.Millisecond}, 150 {Name: "100x", N: 100, Delay: 500 * time.Microsecond}, 151 } 152 153 for _, testCase := range testCases { 154 t.Run(testCase.Name, func(t *testing.T) { 155 var counter int 156 benchmarkFunc := func(fb *functional.B) { 157 for i := 0; i < fb.N; i++ { 158 counter++ 159 time.Sleep(testCase.Delay) 160 } 161 } 162 result := functional.RunBenchmarkTimes(ctx, benchmarkFunc, testCase.N) 163 assert.True(t, result.Pass) 164 assert.False(t, result.StartTime.IsZero()) 165 assert.False(t, result.EndTime.IsZero()) 166 assert.Equal(t, testCase.N, counter) 167 }) 168 } 169 }) 170 171 t.Run("Subtest has same N value", func(t *testing.T) { 172 const expectedN = 100 173 var counterFunc1, counterFunc2a int 174 benchmarkFunc := func(fb *functional.B) { 175 fb.Run("Func1", func(fb *functional.B) { 176 for i := 0; i < fb.N; i++ { 177 counterFunc1++ 178 } 179 }) 180 fb.Run("Func2", func(fb *functional.B) { 181 fb.Run("Func2a", func(fb *functional.B) { 182 for i := 0; i < fb.N; i++ { 183 counterFunc2a++ 184 } 185 }) 186 }) 187 } 188 189 result := functional.RunBenchmarkTimes(ctx, benchmarkFunc, expectedN) 190 assert.True(t, result.Pass) 191 assert.Equal(t, expectedN, counterFunc1) 192 assert.Equal(t, expectedN, counterFunc2a) 193 }) 194 195 t.Run("WithWriter()", func(t *testing.T) { 196 testFunc := func(fb *functional.B) { 197 fb.Log("Foobar") 198 } 199 var buf bytes.Buffer 200 bwriter := bufio.NewWriter(&buf) 201 result := functional.RunBenchmarkTimes(ctx, testFunc, 1, functional.WithWriter(bwriter)) 202 assert.True(t, result.Pass) 203 assert.Contains(t, "Foobar", buf.String()) 204 }) 205 206 t.Run("WithArgs()", func(t *testing.T) { 207 args := []string{"A", "B", "C"} 208 testFunc := func(fb *functional.B) { 209 assert.Equal(t, args, fb.Args()) 210 } 211 result := functional.RunBenchmarkTimes(ctx, testFunc, 1, functional.WithArgs(args...)) 212 assert.True(t, result.Pass) 213 }) 214 215 t.Run("Benchmark fails", func(t *testing.T) { 216 testFunc := func(fb *functional.B) { 217 fb.FailNow() 218 } 219 result := functional.RunBenchmarkTimes(ctx, testFunc, 1) 220 assert.False(t, result.Pass) 221 }) 222 223 t.Run("Nested benchmark", func(t *testing.T) { 224 t.Run("Passes", func(t *testing.T) { 225 benchFunc := func(fb *functional.B) { 226 fb.Run("Subtest 1", func(_ *functional.B) { 227 }) 228 } 229 result := functional.RunBenchmarkTimes(ctx, benchFunc, 1) 230 assert.True(t, result.Pass) 231 }) 232 233 t.Run("Fails", func(t *testing.T) { 234 benchFunc := func(fb *functional.B) { 235 fb.Run("Subtest 1", func(b *functional.B) { 236 b.FailNow() 237 }) 238 } 239 result := functional.RunBenchmarkTimes(ctx, benchFunc, 1) 240 assert.False(t, result.Pass) 241 }) 242 }) 243 244 t.Run("Skip", func(t *testing.T) { 245 var mutex sync.Mutex 246 var before, after bool 247 testFunc := func(fb *functional.B) { 248 mutex.Lock() 249 defer mutex.Unlock() 250 before = true 251 fb.SkipNow() 252 after = true 253 } 254 result := functional.RunBenchmarkTimes(ctx, testFunc, 1) 255 assert.True(t, result.Pass) 256 257 mutex.Lock() 258 defer mutex.Unlock() 259 assert.True(t, before) 260 assert.False(t, after) 261 }) 262 }) 263 264 t.Run("RunBenchmarkSuiteTimes()", func(t *testing.T) { 265 const times = 5 266 267 t.Run("Happy path", func(t *testing.T) { 268 var counter int 269 testFunc1 := func(fb *functional.B) { 270 counter += fb.N 271 } 272 testFunc2 := func(fb *functional.B) { 273 counter += fb.N 274 } 275 tests := []functional.BenchmarkFunc{testFunc1, testFunc2} 276 pass := functional.RunBenchmarkSuiteTimes(ctx, "Foobar suite", times, tests) 277 assert.True(t, pass) 278 assert.Equal(t, 2*times, counter) 279 }) 280 281 t.Run("Partial failure", func(t *testing.T) { 282 var counter int 283 testFunc1 := func(fb *functional.B) { 284 counter += fb.N 285 } 286 testFunc2 := func(fb *functional.B) { 287 counter += fb.N 288 fb.FailNow() 289 } 290 tests := []functional.BenchmarkFunc{testFunc1, testFunc2} 291 pass := functional.RunBenchmarkSuiteTimes(ctx, "Foobar suite", times, tests) 292 assert.False(t, pass) 293 assert.Equal(t, 2*times, counter) 294 }) 295 296 t.Run("Complete failure", func(t *testing.T) { 297 var counter int 298 testFunc1 := func(fb *functional.B) { 299 counter += fb.N 300 fb.FailNow() 301 } 302 testFunc2 := func(fb *functional.B) { 303 counter += fb.N 304 fb.FailNow() 305 } 306 tests := []functional.BenchmarkFunc{testFunc1, testFunc2} 307 pass := functional.RunBenchmarkSuiteTimes(ctx, "Foobar suite", times, tests) 308 assert.False(t, pass) 309 assert.Equal(t, 2*times, counter) 310 }) 311 }) 312 }