github.com/m3db/m3@v1.5.0/src/dbnode/client/fetch_state_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 // fetchStateEqualsFn allows users to override equality checks 57 // for `fetchState` instances. 58 type fetchStateEqualsFn func(a, b *fetchState) bool 59 60 // fetchStateGetHookFn allows users to override properties on items 61 // retrieved from the backing pools before returning in the Get() 62 // path. 63 type fetchStateGetHookFn func(*fetchState) *fetchState 64 65 // leakcheckFetchStatePoolOpts allows users to override default behaviour. 66 type leakcheckFetchStatePoolOpts struct { 67 DisallowUntrackedPuts bool 68 EqualsFn fetchStateEqualsFn 69 GetHookFn fetchStateGetHookFn 70 } 71 72 // newLeakcheckFetchStatePool returns a new leakcheckFetchStatePool. 73 func newLeakcheckFetchStatePool(opts leakcheckFetchStatePoolOpts, backingPool fetchStatePool) *leakcheckFetchStatePool { 74 if opts.EqualsFn == nil { 75 // NB(prateek): fall-back to == in the worst case 76 opts.EqualsFn = func(a, b *fetchState) bool { 77 return a == b 78 } 79 } 80 return &leakcheckFetchStatePool{opts: opts, fetchStatePool: backingPool} 81 } 82 83 // leakcheckFetchStatePool wraps the underlying fetchStatePool to make it easier to 84 // track leaks/allocs. 85 type leakcheckFetchStatePool struct { 86 sync.Mutex 87 fetchStatePool 88 NumGets int 89 NumPuts int 90 PendingItems []leakcheckFetchState 91 AllGetItems []leakcheckFetchState 92 93 opts leakcheckFetchStatePoolOpts 94 } 95 96 // leakcheckFetchState wraps `fetchState` instances along with their last Get() paths. 97 type leakcheckFetchState struct { 98 Value *fetchState 99 GetStacktrace []byte // GetStacktrace is the stacktrace for the Get() of this item 100 } 101 102 func (p *leakcheckFetchStatePool) Init() { 103 p.Lock() 104 defer p.Unlock() 105 p.fetchStatePool.Init() 106 } 107 108 func (p *leakcheckFetchStatePool) Get() *fetchState { 109 p.Lock() 110 defer p.Unlock() 111 112 e := p.fetchStatePool.Get() 113 if fn := p.opts.GetHookFn; fn != nil { 114 e = fn(e) 115 } 116 117 p.NumGets++ 118 item := leakcheckFetchState{ 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 *leakcheckFetchStatePool) Put(value *fetchState) { 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.fetchStatePool.Put(value) 151 } 152 153 // Check ensures there are no leaks. 154 func (p *leakcheckFetchStatePool) 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 leakcheckFetchStateFn func(e leakcheckFetchState) 163 164 // CheckExtended ensures there are no leaks, and executes the specified fn 165 func (p *leakcheckFetchStatePool) CheckExtended(t *testing.T, fn leakcheckFetchStateFn) { 166 p.Check(t) 167 p.Lock() 168 defer p.Unlock() 169 for _, e := range p.AllGetItems { 170 fn(e) 171 } 172 }