...

Source file src/github.com/go-openapi/validate/pools_debug.go

Documentation: github.com/go-openapi/validate

     1  //go:build validatedebug
     2  
     3  package validate
     4  
     5  import (
     6  	"fmt"
     7  	"runtime"
     8  	"sync"
     9  	"testing"
    10  
    11  	"github.com/go-openapi/spec"
    12  )
    13  
    14  // This version of the pools is to be used for debugging and testing, with build tag "validatedebug".
    15  //
    16  // In this mode, the pools are tracked for allocation and redemption of borrowed objects, so we can
    17  // verify a few behaviors of the validators. The debug pools panic when an invalid usage pattern is detected.
    18  
    19  var pools allPools
    20  
    21  func init() {
    22  	resetPools()
    23  }
    24  
    25  func resetPools() {
    26  	// NOTE: for testing purpose, we might want to reset pools after calling Validate twice.
    27  	// The pool is corrupted in that case: calling Put twice inserts a duplicate in the pool
    28  	// and further calls to Get are mishandled.
    29  
    30  	pools = allPools{
    31  		poolOfSchemaValidators: schemaValidatorsPool{
    32  			Pool: &sync.Pool{
    33  				New: func() any {
    34  					s := &SchemaValidator{}
    35  
    36  					return s
    37  				},
    38  			},
    39  			debugMap:  make(map[*SchemaValidator]status),
    40  			allocMap:  make(map[*SchemaValidator]string),
    41  			redeemMap: make(map[*SchemaValidator]string),
    42  		},
    43  		poolOfObjectValidators: objectValidatorsPool{
    44  			Pool: &sync.Pool{
    45  				New: func() any {
    46  					s := &objectValidator{}
    47  
    48  					return s
    49  				},
    50  			},
    51  			debugMap:  make(map[*objectValidator]status),
    52  			allocMap:  make(map[*objectValidator]string),
    53  			redeemMap: make(map[*objectValidator]string),
    54  		},
    55  		poolOfSliceValidators: sliceValidatorsPool{
    56  			Pool: &sync.Pool{
    57  				New: func() any {
    58  					s := &schemaSliceValidator{}
    59  
    60  					return s
    61  				},
    62  			},
    63  			debugMap:  make(map[*schemaSliceValidator]status),
    64  			allocMap:  make(map[*schemaSliceValidator]string),
    65  			redeemMap: make(map[*schemaSliceValidator]string),
    66  		},
    67  		poolOfItemsValidators: itemsValidatorsPool{
    68  			Pool: &sync.Pool{
    69  				New: func() any {
    70  					s := &itemsValidator{}
    71  
    72  					return s
    73  				},
    74  			},
    75  			debugMap:  make(map[*itemsValidator]status),
    76  			allocMap:  make(map[*itemsValidator]string),
    77  			redeemMap: make(map[*itemsValidator]string),
    78  		},
    79  		poolOfBasicCommonValidators: basicCommonValidatorsPool{
    80  			Pool: &sync.Pool{
    81  				New: func() any {
    82  					s := &basicCommonValidator{}
    83  
    84  					return s
    85  				},
    86  			},
    87  			debugMap:  make(map[*basicCommonValidator]status),
    88  			allocMap:  make(map[*basicCommonValidator]string),
    89  			redeemMap: make(map[*basicCommonValidator]string),
    90  		},
    91  		poolOfHeaderValidators: headerValidatorsPool{
    92  			Pool: &sync.Pool{
    93  				New: func() any {
    94  					s := &HeaderValidator{}
    95  
    96  					return s
    97  				},
    98  			},
    99  			debugMap:  make(map[*HeaderValidator]status),
   100  			allocMap:  make(map[*HeaderValidator]string),
   101  			redeemMap: make(map[*HeaderValidator]string),
   102  		},
   103  		poolOfParamValidators: paramValidatorsPool{
   104  			Pool: &sync.Pool{
   105  				New: func() any {
   106  					s := &ParamValidator{}
   107  
   108  					return s
   109  				},
   110  			},
   111  			debugMap:  make(map[*ParamValidator]status),
   112  			allocMap:  make(map[*ParamValidator]string),
   113  			redeemMap: make(map[*ParamValidator]string),
   114  		},
   115  		poolOfBasicSliceValidators: basicSliceValidatorsPool{
   116  			Pool: &sync.Pool{
   117  				New: func() any {
   118  					s := &basicSliceValidator{}
   119  
   120  					return s
   121  				},
   122  			},
   123  			debugMap:  make(map[*basicSliceValidator]status),
   124  			allocMap:  make(map[*basicSliceValidator]string),
   125  			redeemMap: make(map[*basicSliceValidator]string),
   126  		},
   127  		poolOfNumberValidators: numberValidatorsPool{
   128  			Pool: &sync.Pool{
   129  				New: func() any {
   130  					s := &numberValidator{}
   131  
   132  					return s
   133  				},
   134  			},
   135  			debugMap:  make(map[*numberValidator]status),
   136  			allocMap:  make(map[*numberValidator]string),
   137  			redeemMap: make(map[*numberValidator]string),
   138  		},
   139  		poolOfStringValidators: stringValidatorsPool{
   140  			Pool: &sync.Pool{
   141  				New: func() any {
   142  					s := &stringValidator{}
   143  
   144  					return s
   145  				},
   146  			},
   147  			debugMap:  make(map[*stringValidator]status),
   148  			allocMap:  make(map[*stringValidator]string),
   149  			redeemMap: make(map[*stringValidator]string),
   150  		},
   151  		poolOfSchemaPropsValidators: schemaPropsValidatorsPool{
   152  			Pool: &sync.Pool{
   153  				New: func() any {
   154  					s := &schemaPropsValidator{}
   155  
   156  					return s
   157  				},
   158  			},
   159  			debugMap:  make(map[*schemaPropsValidator]status),
   160  			allocMap:  make(map[*schemaPropsValidator]string),
   161  			redeemMap: make(map[*schemaPropsValidator]string),
   162  		},
   163  		poolOfFormatValidators: formatValidatorsPool{
   164  			Pool: &sync.Pool{
   165  				New: func() any {
   166  					s := &formatValidator{}
   167  
   168  					return s
   169  				},
   170  			},
   171  			debugMap:  make(map[*formatValidator]status),
   172  			allocMap:  make(map[*formatValidator]string),
   173  			redeemMap: make(map[*formatValidator]string),
   174  		},
   175  		poolOfTypeValidators: typeValidatorsPool{
   176  			Pool: &sync.Pool{
   177  				New: func() any {
   178  					s := &typeValidator{}
   179  
   180  					return s
   181  				},
   182  			},
   183  			debugMap:  make(map[*typeValidator]status),
   184  			allocMap:  make(map[*typeValidator]string),
   185  			redeemMap: make(map[*typeValidator]string),
   186  		},
   187  		poolOfSchemas: schemasPool{
   188  			Pool: &sync.Pool{
   189  				New: func() any {
   190  					s := &spec.Schema{}
   191  
   192  					return s
   193  				},
   194  			},
   195  			debugMap:  make(map[*spec.Schema]status),
   196  			allocMap:  make(map[*spec.Schema]string),
   197  			redeemMap: make(map[*spec.Schema]string),
   198  		},
   199  		poolOfResults: resultsPool{
   200  			Pool: &sync.Pool{
   201  				New: func() any {
   202  					s := &Result{}
   203  
   204  					return s
   205  				},
   206  			},
   207  			debugMap:  make(map[*Result]status),
   208  			allocMap:  make(map[*Result]string),
   209  			redeemMap: make(map[*Result]string),
   210  		},
   211  	}
   212  }
   213  
   214  const (
   215  	statusFresh status = iota + 1
   216  	statusRecycled
   217  	statusRedeemed
   218  )
   219  
   220  func (s status) String() string {
   221  	switch s {
   222  	case statusFresh:
   223  		return "fresh"
   224  	case statusRecycled:
   225  		return "recycled"
   226  	case statusRedeemed:
   227  		return "redeemed"
   228  	default:
   229  		panic(fmt.Errorf("invalid status: %d", s))
   230  	}
   231  }
   232  
   233  type (
   234  	// Debug
   235  	status uint8
   236  
   237  	allPools struct {
   238  		// memory pools for all validator objects.
   239  		//
   240  		// Each pool can be borrowed from and redeemed to.
   241  		poolOfSchemaValidators      schemaValidatorsPool
   242  		poolOfObjectValidators      objectValidatorsPool
   243  		poolOfSliceValidators       sliceValidatorsPool
   244  		poolOfItemsValidators       itemsValidatorsPool
   245  		poolOfBasicCommonValidators basicCommonValidatorsPool
   246  		poolOfHeaderValidators      headerValidatorsPool
   247  		poolOfParamValidators       paramValidatorsPool
   248  		poolOfBasicSliceValidators  basicSliceValidatorsPool
   249  		poolOfNumberValidators      numberValidatorsPool
   250  		poolOfStringValidators      stringValidatorsPool
   251  		poolOfSchemaPropsValidators schemaPropsValidatorsPool
   252  		poolOfFormatValidators      formatValidatorsPool
   253  		poolOfTypeValidators        typeValidatorsPool
   254  		poolOfSchemas               schemasPool
   255  		poolOfResults               resultsPool
   256  	}
   257  
   258  	schemaValidatorsPool struct {
   259  		*sync.Pool
   260  		debugMap  map[*SchemaValidator]status
   261  		allocMap  map[*SchemaValidator]string
   262  		redeemMap map[*SchemaValidator]string
   263  		mx        sync.Mutex
   264  	}
   265  
   266  	objectValidatorsPool struct {
   267  		*sync.Pool
   268  		debugMap  map[*objectValidator]status
   269  		allocMap  map[*objectValidator]string
   270  		redeemMap map[*objectValidator]string
   271  		mx        sync.Mutex
   272  	}
   273  
   274  	sliceValidatorsPool struct {
   275  		*sync.Pool
   276  		debugMap  map[*schemaSliceValidator]status
   277  		allocMap  map[*schemaSliceValidator]string
   278  		redeemMap map[*schemaSliceValidator]string
   279  		mx        sync.Mutex
   280  	}
   281  
   282  	itemsValidatorsPool struct {
   283  		*sync.Pool
   284  		debugMap  map[*itemsValidator]status
   285  		allocMap  map[*itemsValidator]string
   286  		redeemMap map[*itemsValidator]string
   287  		mx        sync.Mutex
   288  	}
   289  
   290  	basicCommonValidatorsPool struct {
   291  		*sync.Pool
   292  		debugMap  map[*basicCommonValidator]status
   293  		allocMap  map[*basicCommonValidator]string
   294  		redeemMap map[*basicCommonValidator]string
   295  		mx        sync.Mutex
   296  	}
   297  
   298  	headerValidatorsPool struct {
   299  		*sync.Pool
   300  		debugMap  map[*HeaderValidator]status
   301  		allocMap  map[*HeaderValidator]string
   302  		redeemMap map[*HeaderValidator]string
   303  		mx        sync.Mutex
   304  	}
   305  
   306  	paramValidatorsPool struct {
   307  		*sync.Pool
   308  		debugMap  map[*ParamValidator]status
   309  		allocMap  map[*ParamValidator]string
   310  		redeemMap map[*ParamValidator]string
   311  		mx        sync.Mutex
   312  	}
   313  
   314  	basicSliceValidatorsPool struct {
   315  		*sync.Pool
   316  		debugMap  map[*basicSliceValidator]status
   317  		allocMap  map[*basicSliceValidator]string
   318  		redeemMap map[*basicSliceValidator]string
   319  		mx        sync.Mutex
   320  	}
   321  
   322  	numberValidatorsPool struct {
   323  		*sync.Pool
   324  		debugMap  map[*numberValidator]status
   325  		allocMap  map[*numberValidator]string
   326  		redeemMap map[*numberValidator]string
   327  		mx        sync.Mutex
   328  	}
   329  
   330  	stringValidatorsPool struct {
   331  		*sync.Pool
   332  		debugMap  map[*stringValidator]status
   333  		allocMap  map[*stringValidator]string
   334  		redeemMap map[*stringValidator]string
   335  		mx        sync.Mutex
   336  	}
   337  
   338  	schemaPropsValidatorsPool struct {
   339  		*sync.Pool
   340  		debugMap  map[*schemaPropsValidator]status
   341  		allocMap  map[*schemaPropsValidator]string
   342  		redeemMap map[*schemaPropsValidator]string
   343  		mx        sync.Mutex
   344  	}
   345  
   346  	formatValidatorsPool struct {
   347  		*sync.Pool
   348  		debugMap  map[*formatValidator]status
   349  		allocMap  map[*formatValidator]string
   350  		redeemMap map[*formatValidator]string
   351  		mx        sync.Mutex
   352  	}
   353  
   354  	typeValidatorsPool struct {
   355  		*sync.Pool
   356  		debugMap  map[*typeValidator]status
   357  		allocMap  map[*typeValidator]string
   358  		redeemMap map[*typeValidator]string
   359  		mx        sync.Mutex
   360  	}
   361  
   362  	schemasPool struct {
   363  		*sync.Pool
   364  		debugMap  map[*spec.Schema]status
   365  		allocMap  map[*spec.Schema]string
   366  		redeemMap map[*spec.Schema]string
   367  		mx        sync.Mutex
   368  	}
   369  
   370  	resultsPool struct {
   371  		*sync.Pool
   372  		debugMap  map[*Result]status
   373  		allocMap  map[*Result]string
   374  		redeemMap map[*Result]string
   375  		mx        sync.Mutex
   376  	}
   377  )
   378  
   379  func (p *schemaValidatorsPool) BorrowValidator() *SchemaValidator {
   380  	s := p.Get().(*SchemaValidator)
   381  
   382  	p.mx.Lock()
   383  	defer p.mx.Unlock()
   384  	x, ok := p.debugMap[s]
   385  	if !ok {
   386  		p.debugMap[s] = statusFresh
   387  	} else {
   388  		if x != statusRedeemed {
   389  			panic("recycled schema should have been redeemed")
   390  		}
   391  		p.debugMap[s] = statusRecycled
   392  	}
   393  	p.allocMap[s] = caller()
   394  
   395  	return s
   396  }
   397  
   398  func (p *schemaValidatorsPool) RedeemValidator(s *SchemaValidator) {
   399  	// NOTE: s might be nil. In that case, Put is a noop.
   400  	p.mx.Lock()
   401  	defer p.mx.Unlock()
   402  	x, ok := p.debugMap[s]
   403  	if !ok {
   404  		panic("redeemed schema should have been allocated")
   405  	}
   406  	if x != statusRecycled && x != statusFresh {
   407  		panic("redeemed schema should have been allocated from a fresh or recycled pointer")
   408  	}
   409  	p.debugMap[s] = statusRedeemed
   410  	p.redeemMap[s] = caller()
   411  	p.Put(s)
   412  }
   413  
   414  func (p *objectValidatorsPool) BorrowValidator() *objectValidator {
   415  	s := p.Get().(*objectValidator)
   416  
   417  	p.mx.Lock()
   418  	defer p.mx.Unlock()
   419  	x, ok := p.debugMap[s]
   420  	if !ok {
   421  		p.debugMap[s] = statusFresh
   422  	} else {
   423  		if x != statusRedeemed {
   424  			panic("recycled object should have been redeemed")
   425  		}
   426  		p.debugMap[s] = statusRecycled
   427  	}
   428  	p.allocMap[s] = caller()
   429  
   430  	return s
   431  }
   432  
   433  func (p *objectValidatorsPool) RedeemValidator(s *objectValidator) {
   434  	p.mx.Lock()
   435  	defer p.mx.Unlock()
   436  	x, ok := p.debugMap[s]
   437  	if !ok {
   438  		panic("redeemed object should have been allocated")
   439  	}
   440  	if x != statusRecycled && x != statusFresh {
   441  		panic("redeemed object should have been allocated from a fresh or recycled pointer")
   442  	}
   443  	p.debugMap[s] = statusRedeemed
   444  	p.redeemMap[s] = caller()
   445  	p.Put(s)
   446  }
   447  
   448  func (p *sliceValidatorsPool) BorrowValidator() *schemaSliceValidator {
   449  	s := p.Get().(*schemaSliceValidator)
   450  
   451  	p.mx.Lock()
   452  	defer p.mx.Unlock()
   453  	x, ok := p.debugMap[s]
   454  	if !ok {
   455  		p.debugMap[s] = statusFresh
   456  	} else {
   457  		if x != statusRedeemed {
   458  			panic("recycled schemaSliceValidator should have been redeemed")
   459  		}
   460  		p.debugMap[s] = statusRecycled
   461  	}
   462  	p.allocMap[s] = caller()
   463  
   464  	return s
   465  }
   466  
   467  func (p *sliceValidatorsPool) RedeemValidator(s *schemaSliceValidator) {
   468  	p.mx.Lock()
   469  	defer p.mx.Unlock()
   470  	x, ok := p.debugMap[s]
   471  	if !ok {
   472  		panic("redeemed schemaSliceValidator should have been allocated")
   473  	}
   474  	if x != statusRecycled && x != statusFresh {
   475  		panic("redeemed schemaSliceValidator should have been allocated from a fresh or recycled pointer")
   476  	}
   477  	p.debugMap[s] = statusRedeemed
   478  	p.redeemMap[s] = caller()
   479  	p.Put(s)
   480  }
   481  
   482  func (p *itemsValidatorsPool) BorrowValidator() *itemsValidator {
   483  	s := p.Get().(*itemsValidator)
   484  
   485  	p.mx.Lock()
   486  	defer p.mx.Unlock()
   487  	x, ok := p.debugMap[s]
   488  	if !ok {
   489  		p.debugMap[s] = statusFresh
   490  	} else {
   491  		if x != statusRedeemed {
   492  			panic("recycled itemsValidator should have been redeemed")
   493  		}
   494  		p.debugMap[s] = statusRecycled
   495  	}
   496  	p.allocMap[s] = caller()
   497  
   498  	return s
   499  }
   500  
   501  func (p *itemsValidatorsPool) RedeemValidator(s *itemsValidator) {
   502  	p.mx.Lock()
   503  	defer p.mx.Unlock()
   504  	x, ok := p.debugMap[s]
   505  	if !ok {
   506  		panic("redeemed itemsValidator should have been allocated")
   507  	}
   508  	if x != statusRecycled && x != statusFresh {
   509  		panic("redeemed itemsValidator should have been allocated from a fresh or recycled pointer")
   510  	}
   511  	p.debugMap[s] = statusRedeemed
   512  	p.redeemMap[s] = caller()
   513  	p.Put(s)
   514  }
   515  
   516  func (p *basicCommonValidatorsPool) BorrowValidator() *basicCommonValidator {
   517  	s := p.Get().(*basicCommonValidator)
   518  
   519  	p.mx.Lock()
   520  	defer p.mx.Unlock()
   521  	x, ok := p.debugMap[s]
   522  	if !ok {
   523  		p.debugMap[s] = statusFresh
   524  	} else {
   525  		if x != statusRedeemed {
   526  			panic("recycled basicCommonValidator should have been redeemed")
   527  		}
   528  		p.debugMap[s] = statusRecycled
   529  	}
   530  	p.allocMap[s] = caller()
   531  
   532  	return s
   533  }
   534  
   535  func (p *basicCommonValidatorsPool) RedeemValidator(s *basicCommonValidator) {
   536  	p.mx.Lock()
   537  	defer p.mx.Unlock()
   538  	x, ok := p.debugMap[s]
   539  	if !ok {
   540  		panic("redeemed basicCommonValidator should have been allocated")
   541  	}
   542  	if x != statusRecycled && x != statusFresh {
   543  		panic("redeemed basicCommonValidator should have been allocated from a fresh or recycled pointer")
   544  	}
   545  	p.debugMap[s] = statusRedeemed
   546  	p.redeemMap[s] = caller()
   547  	p.Put(s)
   548  }
   549  
   550  func (p *headerValidatorsPool) BorrowValidator() *HeaderValidator {
   551  	s := p.Get().(*HeaderValidator)
   552  
   553  	p.mx.Lock()
   554  	defer p.mx.Unlock()
   555  	x, ok := p.debugMap[s]
   556  	if !ok {
   557  		p.debugMap[s] = statusFresh
   558  	} else {
   559  		if x != statusRedeemed {
   560  			panic("recycled HeaderValidator should have been redeemed")
   561  		}
   562  		p.debugMap[s] = statusRecycled
   563  	}
   564  	p.allocMap[s] = caller()
   565  
   566  	return s
   567  }
   568  
   569  func (p *headerValidatorsPool) RedeemValidator(s *HeaderValidator) {
   570  	p.mx.Lock()
   571  	defer p.mx.Unlock()
   572  	x, ok := p.debugMap[s]
   573  	if !ok {
   574  		panic("redeemed header should have been allocated")
   575  	}
   576  	if x != statusRecycled && x != statusFresh {
   577  		panic("redeemed header should have been allocated from a fresh or recycled pointer")
   578  	}
   579  	p.debugMap[s] = statusRedeemed
   580  	p.redeemMap[s] = caller()
   581  	p.Put(s)
   582  }
   583  
   584  func (p *paramValidatorsPool) BorrowValidator() *ParamValidator {
   585  	s := p.Get().(*ParamValidator)
   586  
   587  	p.mx.Lock()
   588  	defer p.mx.Unlock()
   589  	x, ok := p.debugMap[s]
   590  	if !ok {
   591  		p.debugMap[s] = statusFresh
   592  	} else {
   593  		if x != statusRedeemed {
   594  			panic("recycled param should have been redeemed")
   595  		}
   596  		p.debugMap[s] = statusRecycled
   597  	}
   598  	p.allocMap[s] = caller()
   599  
   600  	return s
   601  }
   602  
   603  func (p *paramValidatorsPool) RedeemValidator(s *ParamValidator) {
   604  	p.mx.Lock()
   605  	defer p.mx.Unlock()
   606  	x, ok := p.debugMap[s]
   607  	if !ok {
   608  		panic("redeemed param should have been allocated")
   609  	}
   610  	if x != statusRecycled && x != statusFresh {
   611  		panic("redeemed param should have been allocated from a fresh or recycled pointer")
   612  	}
   613  	p.debugMap[s] = statusRedeemed
   614  	p.redeemMap[s] = caller()
   615  	p.Put(s)
   616  }
   617  
   618  func (p *basicSliceValidatorsPool) BorrowValidator() *basicSliceValidator {
   619  	s := p.Get().(*basicSliceValidator)
   620  
   621  	p.mx.Lock()
   622  	defer p.mx.Unlock()
   623  	x, ok := p.debugMap[s]
   624  	if !ok {
   625  		p.debugMap[s] = statusFresh
   626  	} else {
   627  		if x != statusRedeemed {
   628  			panic("recycled basicSliceValidator should have been redeemed")
   629  		}
   630  		p.debugMap[s] = statusRecycled
   631  	}
   632  	p.allocMap[s] = caller()
   633  
   634  	return s
   635  }
   636  
   637  func (p *basicSliceValidatorsPool) RedeemValidator(s *basicSliceValidator) {
   638  	p.mx.Lock()
   639  	defer p.mx.Unlock()
   640  	x, ok := p.debugMap[s]
   641  	if !ok {
   642  		panic("redeemed basicSliceValidator should have been allocated")
   643  	}
   644  	if x != statusRecycled && x != statusFresh {
   645  		panic("redeemed basicSliceValidator should have been allocated from a fresh or recycled pointer")
   646  	}
   647  	p.debugMap[s] = statusRedeemed
   648  	p.redeemMap[s] = caller()
   649  	p.Put(s)
   650  }
   651  
   652  func (p *numberValidatorsPool) BorrowValidator() *numberValidator {
   653  	s := p.Get().(*numberValidator)
   654  
   655  	p.mx.Lock()
   656  	defer p.mx.Unlock()
   657  	x, ok := p.debugMap[s]
   658  	if !ok {
   659  		p.debugMap[s] = statusFresh
   660  	} else {
   661  		if x != statusRedeemed {
   662  			panic("recycled number should have been redeemed")
   663  		}
   664  		p.debugMap[s] = statusRecycled
   665  	}
   666  	p.allocMap[s] = caller()
   667  
   668  	return s
   669  }
   670  
   671  func (p *numberValidatorsPool) RedeemValidator(s *numberValidator) {
   672  	p.mx.Lock()
   673  	defer p.mx.Unlock()
   674  	x, ok := p.debugMap[s]
   675  	if !ok {
   676  		panic("redeemed number should have been allocated")
   677  	}
   678  	if x != statusRecycled && x != statusFresh {
   679  		panic("redeemed number should have been allocated from a fresh or recycled pointer")
   680  	}
   681  	p.debugMap[s] = statusRedeemed
   682  	p.redeemMap[s] = caller()
   683  	p.Put(s)
   684  }
   685  
   686  func (p *stringValidatorsPool) BorrowValidator() *stringValidator {
   687  	s := p.Get().(*stringValidator)
   688  
   689  	p.mx.Lock()
   690  	defer p.mx.Unlock()
   691  	x, ok := p.debugMap[s]
   692  	if !ok {
   693  		p.debugMap[s] = statusFresh
   694  	} else {
   695  		if x != statusRedeemed {
   696  			panic("recycled string should have been redeemed")
   697  		}
   698  		p.debugMap[s] = statusRecycled
   699  	}
   700  	p.allocMap[s] = caller()
   701  
   702  	return s
   703  }
   704  
   705  func (p *stringValidatorsPool) RedeemValidator(s *stringValidator) {
   706  	p.mx.Lock()
   707  	defer p.mx.Unlock()
   708  	x, ok := p.debugMap[s]
   709  	if !ok {
   710  		panic("redeemed string should have been allocated")
   711  	}
   712  	if x != statusRecycled && x != statusFresh {
   713  		panic("redeemed string should have been allocated from a fresh or recycled pointer")
   714  	}
   715  	p.debugMap[s] = statusRedeemed
   716  	p.redeemMap[s] = caller()
   717  	p.Put(s)
   718  }
   719  
   720  func (p *schemaPropsValidatorsPool) BorrowValidator() *schemaPropsValidator {
   721  	s := p.Get().(*schemaPropsValidator)
   722  
   723  	p.mx.Lock()
   724  	defer p.mx.Unlock()
   725  	x, ok := p.debugMap[s]
   726  	if !ok {
   727  		p.debugMap[s] = statusFresh
   728  	} else {
   729  		if x != statusRedeemed {
   730  			panic("recycled param should have been redeemed")
   731  		}
   732  		p.debugMap[s] = statusRecycled
   733  	}
   734  	p.allocMap[s] = caller()
   735  
   736  	return s
   737  }
   738  
   739  func (p *schemaPropsValidatorsPool) RedeemValidator(s *schemaPropsValidator) {
   740  	p.mx.Lock()
   741  	defer p.mx.Unlock()
   742  	x, ok := p.debugMap[s]
   743  	if !ok {
   744  		panic("redeemed schemaProps should have been allocated")
   745  	}
   746  	if x != statusRecycled && x != statusFresh {
   747  		panic("redeemed schemaProps should have been allocated from a fresh or recycled pointer")
   748  	}
   749  	p.debugMap[s] = statusRedeemed
   750  	p.redeemMap[s] = caller()
   751  	p.Put(s)
   752  }
   753  
   754  func (p *formatValidatorsPool) BorrowValidator() *formatValidator {
   755  	s := p.Get().(*formatValidator)
   756  
   757  	p.mx.Lock()
   758  	defer p.mx.Unlock()
   759  	x, ok := p.debugMap[s]
   760  	if !ok {
   761  		p.debugMap[s] = statusFresh
   762  	} else {
   763  		if x != statusRedeemed {
   764  			panic("recycled format should have been redeemed")
   765  		}
   766  		p.debugMap[s] = statusRecycled
   767  	}
   768  	p.allocMap[s] = caller()
   769  
   770  	return s
   771  }
   772  
   773  func (p *formatValidatorsPool) RedeemValidator(s *formatValidator) {
   774  	p.mx.Lock()
   775  	defer p.mx.Unlock()
   776  	x, ok := p.debugMap[s]
   777  	if !ok {
   778  		panic("redeemed format should have been allocated")
   779  	}
   780  	if x != statusRecycled && x != statusFresh {
   781  		panic("redeemed format should have been allocated from a fresh or recycled pointer")
   782  	}
   783  	p.debugMap[s] = statusRedeemed
   784  	p.redeemMap[s] = caller()
   785  	p.Put(s)
   786  }
   787  
   788  func (p *typeValidatorsPool) BorrowValidator() *typeValidator {
   789  	s := p.Get().(*typeValidator)
   790  
   791  	p.mx.Lock()
   792  	defer p.mx.Unlock()
   793  	x, ok := p.debugMap[s]
   794  	if !ok {
   795  		p.debugMap[s] = statusFresh
   796  	} else {
   797  		if x != statusRedeemed {
   798  			panic("recycled type should have been redeemed")
   799  		}
   800  		p.debugMap[s] = statusRecycled
   801  	}
   802  	p.allocMap[s] = caller()
   803  
   804  	return s
   805  }
   806  
   807  func (p *typeValidatorsPool) RedeemValidator(s *typeValidator) {
   808  	p.mx.Lock()
   809  	defer p.mx.Unlock()
   810  	x, ok := p.debugMap[s]
   811  	if !ok {
   812  		panic("redeemed type should have been allocated")
   813  	}
   814  	if x != statusRecycled && x != statusFresh {
   815  		panic(fmt.Errorf("redeemed type should have been allocated from a fresh or recycled pointer. Got status %s, already redeamed at: %s", x, p.redeemMap[s]))
   816  	}
   817  	p.debugMap[s] = statusRedeemed
   818  	p.redeemMap[s] = caller()
   819  	p.Put(s)
   820  }
   821  
   822  func (p *schemasPool) BorrowSchema() *spec.Schema {
   823  	s := p.Get().(*spec.Schema)
   824  
   825  	p.mx.Lock()
   826  	defer p.mx.Unlock()
   827  	x, ok := p.debugMap[s]
   828  	if !ok {
   829  		p.debugMap[s] = statusFresh
   830  	} else {
   831  		if x != statusRedeemed {
   832  			panic("recycled spec.Schema should have been redeemed")
   833  		}
   834  		p.debugMap[s] = statusRecycled
   835  	}
   836  	p.allocMap[s] = caller()
   837  
   838  	return s
   839  }
   840  
   841  func (p *schemasPool) RedeemSchema(s *spec.Schema) {
   842  	p.mx.Lock()
   843  	defer p.mx.Unlock()
   844  	x, ok := p.debugMap[s]
   845  	if !ok {
   846  		panic("redeemed spec.Schema should have been allocated")
   847  	}
   848  	if x != statusRecycled && x != statusFresh {
   849  		panic("redeemed spec.Schema should have been allocated from a fresh or recycled pointer")
   850  	}
   851  	p.debugMap[s] = statusRedeemed
   852  	p.redeemMap[s] = caller()
   853  	p.Put(s)
   854  }
   855  
   856  func (p *resultsPool) BorrowResult() *Result {
   857  	s := p.Get().(*Result).cleared()
   858  
   859  	p.mx.Lock()
   860  	defer p.mx.Unlock()
   861  	x, ok := p.debugMap[s]
   862  	if !ok {
   863  		p.debugMap[s] = statusFresh
   864  	} else {
   865  		if x != statusRedeemed {
   866  			panic("recycled result should have been redeemed")
   867  		}
   868  		p.debugMap[s] = statusRecycled
   869  	}
   870  	p.allocMap[s] = caller()
   871  
   872  	return s
   873  }
   874  
   875  func (p *resultsPool) RedeemResult(s *Result) {
   876  	if s == emptyResult {
   877  		if len(s.Errors) > 0 || len(s.Warnings) > 0 {
   878  			panic("empty result should not mutate")
   879  		}
   880  		return
   881  	}
   882  	p.mx.Lock()
   883  	defer p.mx.Unlock()
   884  	x, ok := p.debugMap[s]
   885  	if !ok {
   886  		panic("redeemed Result should have been allocated")
   887  	}
   888  	if x != statusRecycled && x != statusFresh {
   889  		panic("redeemed Result should have been allocated from a fresh or recycled pointer")
   890  	}
   891  	p.debugMap[s] = statusRedeemed
   892  	p.redeemMap[s] = caller()
   893  	p.Put(s)
   894  }
   895  
   896  func (p *allPools) allIsRedeemed(t testing.TB) bool {
   897  	outcome := true
   898  	for k, v := range p.poolOfSchemaValidators.debugMap {
   899  		if v == statusRedeemed {
   900  			continue
   901  		}
   902  		t.Logf("schemaValidator should be redeemed. Allocated by: %s", p.poolOfSchemaValidators.allocMap[k])
   903  		outcome = false
   904  	}
   905  	for k, v := range p.poolOfObjectValidators.debugMap {
   906  		if v == statusRedeemed {
   907  			continue
   908  		}
   909  		t.Logf("objectValidator should be redeemed. Allocated by: %s", p.poolOfObjectValidators.allocMap[k])
   910  		outcome = false
   911  	}
   912  	for k, v := range p.poolOfSliceValidators.debugMap {
   913  		if v == statusRedeemed {
   914  			continue
   915  		}
   916  		t.Logf("sliceValidator should be redeemed. Allocated by: %s", p.poolOfSliceValidators.allocMap[k])
   917  		outcome = false
   918  	}
   919  	for k, v := range p.poolOfItemsValidators.debugMap {
   920  		if v == statusRedeemed {
   921  			continue
   922  		}
   923  		t.Logf("itemsValidator should be redeemed. Allocated by: %s", p.poolOfItemsValidators.allocMap[k])
   924  		outcome = false
   925  	}
   926  	for k, v := range p.poolOfBasicCommonValidators.debugMap {
   927  		if v == statusRedeemed {
   928  			continue
   929  		}
   930  		t.Logf("basicCommonValidator should be redeemed. Allocated by: %s", p.poolOfBasicCommonValidators.allocMap[k])
   931  		outcome = false
   932  	}
   933  	for k, v := range p.poolOfHeaderValidators.debugMap {
   934  		if v == statusRedeemed {
   935  			continue
   936  		}
   937  		t.Logf("headerValidator should be redeemed. Allocated by: %s", p.poolOfHeaderValidators.allocMap[k])
   938  		outcome = false
   939  	}
   940  	for k, v := range p.poolOfParamValidators.debugMap {
   941  		if v == statusRedeemed {
   942  			continue
   943  		}
   944  		t.Logf("paramValidator should be redeemed. Allocated by: %s", p.poolOfParamValidators.allocMap[k])
   945  		outcome = false
   946  	}
   947  	for k, v := range p.poolOfBasicSliceValidators.debugMap {
   948  		if v == statusRedeemed {
   949  			continue
   950  		}
   951  		t.Logf("basicSliceValidator should be redeemed. Allocated by: %s", p.poolOfBasicSliceValidators.allocMap[k])
   952  		outcome = false
   953  	}
   954  	for k, v := range p.poolOfNumberValidators.debugMap {
   955  		if v == statusRedeemed {
   956  			continue
   957  		}
   958  		t.Logf("numberValidator should be redeemed. Allocated by: %s", p.poolOfNumberValidators.allocMap[k])
   959  		outcome = false
   960  	}
   961  	for k, v := range p.poolOfStringValidators.debugMap {
   962  		if v == statusRedeemed {
   963  			continue
   964  		}
   965  		t.Logf("stringValidator should be redeemed. Allocated by: %s", p.poolOfStringValidators.allocMap[k])
   966  		outcome = false
   967  	}
   968  	for k, v := range p.poolOfSchemaPropsValidators.debugMap {
   969  		if v == statusRedeemed {
   970  			continue
   971  		}
   972  		t.Logf("schemaPropsValidator should be redeemed. Allocated by: %s", p.poolOfSchemaPropsValidators.allocMap[k])
   973  		outcome = false
   974  	}
   975  	for k, v := range p.poolOfFormatValidators.debugMap {
   976  		if v == statusRedeemed {
   977  			continue
   978  		}
   979  		t.Logf("formatValidator should be redeemed. Allocated by: %s", p.poolOfFormatValidators.allocMap[k])
   980  		outcome = false
   981  	}
   982  	for k, v := range p.poolOfTypeValidators.debugMap {
   983  		if v == statusRedeemed {
   984  			continue
   985  		}
   986  		t.Logf("typeValidator should be redeemed. Allocated by: %s", p.poolOfTypeValidators.allocMap[k])
   987  		outcome = false
   988  	}
   989  	for k, v := range p.poolOfSchemas.debugMap {
   990  		if v == statusRedeemed {
   991  			continue
   992  		}
   993  		t.Logf("schemas should be redeemed. Allocated by: %s", p.poolOfSchemas.allocMap[k])
   994  		outcome = false
   995  	}
   996  	for k, v := range p.poolOfResults.debugMap {
   997  		if v == statusRedeemed {
   998  			continue
   999  		}
  1000  		t.Logf("result should be redeemed. Allocated by: %s", p.poolOfResults.allocMap[k])
  1001  		outcome = false
  1002  	}
  1003  
  1004  	return outcome
  1005  }
  1006  
  1007  func caller() string {
  1008  	pc, _, _, _ := runtime.Caller(3) //nolint:dogsled
  1009  	from, line := runtime.FuncForPC(pc).FileLine(pc)
  1010  
  1011  	return fmt.Sprintf("%s:%d", from, line)
  1012  }
  1013  

View as plain text