github.com/m3db/m3@v1.5.0/src/dbnode/client/aggregate_leakcheckpool_gen_test.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 // This file was automatically generated by genny. 22 // Any changes will be lost if this file is regenerated. 23 // see https://github.com/mauricelam/genny 24 25 package client 26 27 import ( 28 "fmt" 29 "runtime/debug" 30 "sync" 31 "testing" 32 33 "github.com/stretchr/testify/require" 34 ) 35 36 // Copyright (c) 2018 Uber Technologies, Inc. 37 // 38 // Permission is hereby granted, free of charge, to any person obtaining a copy 39 // of this software and associated documentation files (the "Software"), to deal 40 // in the Software without restriction, including without limitation the rights 41 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 42 // copies of the Software, and to permit persons to whom the Software is 43 // furnished to do so, subject to the following conditions: 44 // 45 // The above copyright notice and this permission notice shall be included in 46 // all copies or substantial portions of the Software. 47 // 48 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 50 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 51 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 52 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 54 // THE SOFTWARE. 55 56 // aggregateOpEqualsFn allows users to override equality checks 57 // for `aggregateOp` instances. 58 type aggregateOpEqualsFn func(a, b *aggregateOp) bool 59 60 // aggregateOpGetHookFn allows users to override properties on items 61 // retrieved from the backing pools before returning in the Get() 62 // path. 63 type aggregateOpGetHookFn func(*aggregateOp) *aggregateOp 64 65 // leakcheckAggregateOpPoolOpts allows users to override default behaviour. 66 type leakcheckAggregateOpPoolOpts struct { 67 DisallowUntrackedPuts bool 68 EqualsFn aggregateOpEqualsFn 69 GetHookFn aggregateOpGetHookFn 70 } 71 72 // newLeakcheckAggregateOpPool returns a new leakcheckAggregateOpPool. 73 func newLeakcheckAggregateOpPool(opts leakcheckAggregateOpPoolOpts, backingPool aggregateOpPool) *leakcheckAggregateOpPool { 74 if opts.EqualsFn == nil { 75 // NB(prateek): fall-back to == in the worst case 76 opts.EqualsFn = func(a, b *aggregateOp) bool { 77 return a == b 78 } 79 } 80 return &leakcheckAggregateOpPool{opts: opts, aggregateOpPool: backingPool} 81 } 82 83 // leakcheckAggregateOpPool wraps the underlying aggregateOpPool to make it easier to 84 // track leaks/allocs. 85 type leakcheckAggregateOpPool struct { 86 sync.Mutex 87 aggregateOpPool 88 NumGets int 89 NumPuts int 90 PendingItems []leakcheckAggregateOp 91 AllGetItems []leakcheckAggregateOp 92 93 opts leakcheckAggregateOpPoolOpts 94 } 95 96 // leakcheckAggregateOp wraps `aggregateOp` instances along with their last Get() paths. 97 type leakcheckAggregateOp struct { 98 Value *aggregateOp 99 GetStacktrace []byte // GetStacktrace is the stacktrace for the Get() of this item 100 } 101 102 func (p *leakcheckAggregateOpPool) Init() { 103 p.Lock() 104 defer p.Unlock() 105 p.aggregateOpPool.Init() 106 } 107 108 func (p *leakcheckAggregateOpPool) Get() *aggregateOp { 109 p.Lock() 110 defer p.Unlock() 111 112 e := p.aggregateOpPool.Get() 113 if fn := p.opts.GetHookFn; fn != nil { 114 e = fn(e) 115 } 116 117 p.NumGets++ 118 item := leakcheckAggregateOp{ 119 Value: e, 120 GetStacktrace: debug.Stack(), 121 } 122 p.PendingItems = append(p.PendingItems, item) 123 p.AllGetItems = append(p.AllGetItems, item) 124 125 return e 126 } 127 128 func (p *leakcheckAggregateOpPool) Put(value *aggregateOp) { 129 p.Lock() 130 defer p.Unlock() 131 132 idx := -1 133 for i, item := range p.PendingItems { 134 if p.opts.EqualsFn(item.Value, value) { 135 idx = i 136 break 137 } 138 } 139 140 if idx == -1 && p.opts.DisallowUntrackedPuts { 141 panic(fmt.Errorf("untracked object (%v) returned to pool", value)) 142 } 143 144 if idx != -1 { 145 // update slice 146 p.PendingItems = append(p.PendingItems[:idx], p.PendingItems[idx+1:]...) 147 } 148 p.NumPuts++ 149 150 p.aggregateOpPool.Put(value) 151 } 152 153 // Check ensures there are no leaks. 154 func (p *leakcheckAggregateOpPool) Check(t *testing.T) { 155 p.Lock() 156 defer p.Unlock() 157 158 require.Equal(t, p.NumGets, p.NumPuts) 159 require.Empty(t, p.PendingItems) 160 } 161 162 type leakcheckAggregateOpFn func(e leakcheckAggregateOp) 163 164 // CheckExtended ensures there are no leaks, and executes the specified fn 165 func (p *leakcheckAggregateOpPool) CheckExtended(t *testing.T, fn leakcheckAggregateOpFn) { 166 p.Check(t) 167 p.Lock() 168 defer p.Unlock() 169 for _, e := range p.AllGetItems { 170 fn(e) 171 } 172 }