github.com/m3db/m3@v1.5.0/src/x/generics/leakcheckpool/pool_test.go (about) 1 // Copyright (c) 2018 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 package leakcheckpool 22 23 import ( 24 "testing" 25 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 ) 29 30 type getFn func() elemType 31 type putFn func(elemType) 32 33 type testElemTypePool struct { 34 getFn getFn 35 putFn putFn 36 } 37 38 func (e *testElemTypePool) Init() { panic("not implemented") } 39 func (e *testElemTypePool) Get() elemType { return e.getFn() } 40 func (e *testElemTypePool) Put(v elemType) { e.putFn(v) } 41 42 func TestInit(t *testing.T) { 43 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{}, &testElemTypePool{}) 44 assert.Panics(t, func() { 45 debugPool.Init() 46 }) 47 } 48 49 func TestGetPut(t *testing.T) { 50 var ( 51 empty elemType 52 ) 53 54 getFn := func() elemType { return empty } 55 putFn := func(elemType) {} 56 57 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{}, &testElemTypePool{getFn: getFn, putFn: putFn}) 58 val := debugPool.Get() 59 require.Equal(t, empty, val) 60 61 debugPool.Lock() 62 require.Equal(t, 1, debugPool.NumGets) 63 require.Equal(t, 1, len(debugPool.AllGetItems)) 64 require.Equal(t, empty, debugPool.AllGetItems[0].Value) 65 require.Equal(t, 1, len(debugPool.PendingItems)) 66 require.Equal(t, empty, debugPool.PendingItems[0].Value) 67 debugPool.Unlock() 68 69 debugPool.Put(empty) 70 debugPool.Lock() 71 require.Equal(t, 1, debugPool.NumGets) 72 require.Equal(t, 1, debugPool.NumPuts) 73 require.Equal(t, 1, len(debugPool.AllGetItems)) 74 require.Equal(t, empty, debugPool.AllGetItems[0].Value) 75 require.Equal(t, 0, len(debugPool.PendingItems)) 76 debugPool.Unlock() 77 } 78 79 func TestDisallowUnalloc(t *testing.T) { 80 putFn := func(v elemType) { 81 panic("should never get here") 82 } 83 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{ 84 DisallowUntrackedPuts: true, 85 }, &testElemTypePool{putFn: putFn}) 86 87 var ( 88 empty elemType 89 ) 90 require.Panics(t, func() { 91 debugPool.Put(empty) 92 }) 93 } 94 95 func TestAllowUnalloc(t *testing.T) { 96 var ( 97 empty elemType 98 call int 99 ) 100 putFn := func(v elemType) { 101 call++ 102 require.Equal(t, empty, v) 103 } 104 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{}, &testElemTypePool{putFn: putFn}) 105 106 require.NotPanics(t, func() { 107 debugPool.Put(empty) 108 }) 109 require.Equal(t, 1, call) 110 111 debugPool.Lock() 112 require.Equal(t, 0, debugPool.NumGets) 113 require.Equal(t, 1, debugPool.NumPuts) 114 require.Equal(t, 0, len(debugPool.AllGetItems)) 115 require.Equal(t, 0, len(debugPool.PendingItems)) 116 debugPool.Unlock() 117 } 118 119 func TestStacksDiffer(t *testing.T) { 120 var ( 121 empty elemType 122 ) 123 124 getFn := func() elemType { 125 return empty 126 } 127 128 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{}, &testElemTypePool{getFn: getFn}) 129 v1 := debugPool.Get() 130 v2 := debugPool.Get() 131 132 debugPool.Lock() 133 require.Equal(t, 2, debugPool.NumGets) 134 require.Equal(t, 2, len(debugPool.AllGetItems)) 135 require.Equal(t, v1, debugPool.AllGetItems[0].Value) 136 require.Equal(t, v2, debugPool.AllGetItems[1].Value) 137 require.Equal(t, 2, len(debugPool.PendingItems)) 138 require.Equal(t, v1, debugPool.PendingItems[0].Value) 139 require.Equal(t, v2, debugPool.PendingItems[1].Value) 140 require.NotEqual(t, debugPool.AllGetItems[0].GetStacktrace, debugPool.AllGetItems[1].GetStacktrace) 141 debugPool.Unlock() 142 } 143 144 func TestCheck(t *testing.T) { 145 var ( 146 empty elemType 147 ) 148 149 getFn := func() elemType { return empty } 150 putFn := func(elemType) {} 151 152 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{}, &testElemTypePool{getFn: getFn, putFn: putFn}) 153 defer debugPool.Check(t) 154 val := debugPool.Get() 155 require.Equal(t, empty, val) 156 debugPool.Put(val) 157 } 158 159 func TestCheckExtended(t *testing.T) { 160 var ( 161 empty elemType 162 ) 163 164 getFn := func() elemType { return empty } 165 putFn := func(elemType) {} 166 167 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{}, &testElemTypePool{getFn: getFn, putFn: putFn}) 168 defer debugPool.CheckExtended(t, func(e leakcheckElemType) { 169 require.Equal(t, empty, e.Value, string(e.GetStacktrace)) 170 }) 171 val := debugPool.Get() 172 debugPool.Put(val) 173 } 174 175 func TestGetHookFn(t *testing.T) { 176 var ( 177 x = elemType(1) 178 ) 179 180 getFn := func() elemType { return x } 181 putFn := func(elemType) {} 182 183 debugPool := newLeakcheckElemTypePool(leakcheckElemTypePoolOpts{ 184 GetHookFn: func(e elemType) elemType { return nil }, 185 }, &testElemTypePool{getFn: getFn, putFn: putFn}) 186 defer debugPool.Check(t) 187 val := debugPool.Get() 188 require.Nil(t, val) 189 require.NotNil(t, x) 190 debugPool.Put(val) 191 }