github.com/mailgun/holster/v4@v4.20.0/functional/b.go (about)

     1  package functional
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"time"
     7  )
     8  
     9  // Functional benchmark context.
    10  type B struct {
    11  	T
    12  	N    int
    13  	leaf bool
    14  }
    15  
    16  // Functional test code.
    17  type BenchmarkFunc func(b *B)
    18  
    19  func newB(name string, times int, opts ...FunctionalOption) *B {
    20  	b := &B{
    21  		T: T{
    22  			name:      name,
    23  			writer:    os.Stdout,
    24  			errWriter: os.Stderr,
    25  		},
    26  		N:    times,
    27  		leaf: true,
    28  	}
    29  
    30  	for _, opt := range opts {
    31  		opt.Apply(&b.T)
    32  	}
    33  
    34  	return b
    35  }
    36  
    37  func (b *B) Run(name string, fn BenchmarkFunc, opts ...FunctionalOption) TestResult {
    38  	b.leaf = false
    39  	longname := joinName(b.name, name)
    40  	b2 := newB(longname, b.N)
    41  	b2.indent++
    42  	b2.writer = b.writer
    43  	b2.errWriter = b.errWriter
    44  
    45  	b2.invoke(b.T.ctx, fn)
    46  
    47  	if !b2.result.Pass {
    48  		b.result.Pass = false
    49  	}
    50  
    51  	return b.result
    52  }
    53  
    54  func (b *B) ResetTimer() {
    55  	b.result.StartTime = time.Now()
    56  }
    57  
    58  func (b *B) invoke(ctx context.Context, fn BenchmarkFunc) {
    59  	callFn := func() {
    60  		fn(b)
    61  	}
    62  	b.commonInvoke(ctx, callFn, b.postHandler)
    63  }
    64  
    65  func (b *B) postHandler() {
    66  	// Benchmark stats.
    67  	if b.leaf && b.N > 0 {
    68  		elapsed := b.result.EndTime.Sub(b.result.StartTime)
    69  		nsPerOp := float64(elapsed.Nanoseconds()) / float64(b.N)
    70  		perOp := time.Duration(int64(nsPerOp))
    71  		b.Logf("%s\t%d\t%s/op", b.name, b.N, perOp.String())
    72  	}
    73  }