github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/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  }