github.com/XiaoMi/Gaea@v1.2.5/util/resource_pool_test.go (about)

     1  /*
     2  Copyright 2017 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/XiaoMi/Gaea/util/sync2"
    26  )
    27  
    28  var lastID, count sync2.AtomicInt64
    29  
    30  type TestResource struct {
    31  	num    int64
    32  	closed bool
    33  }
    34  
    35  func (tr *TestResource) Close() {
    36  	if !tr.closed {
    37  		count.Add(-1)
    38  		tr.closed = true
    39  	}
    40  }
    41  
    42  func PoolFactory() (Resource, error) {
    43  	count.Add(1)
    44  	return &TestResource{lastID.Add(1), false}, nil
    45  }
    46  
    47  func FailFactory() (Resource, error) {
    48  	return nil, errors.New("Failed")
    49  }
    50  
    51  func SlowFailFactory() (Resource, error) {
    52  	time.Sleep(10 * time.Millisecond)
    53  	return nil, errors.New("Failed")
    54  }
    55  
    56  func TestOpen(t *testing.T) {
    57  	ctx := context.Background()
    58  	lastID.Set(0)
    59  	count.Set(0)
    60  	p := NewResourcePool(PoolFactory, 6, 6, time.Second)
    61  	p.SetDynamic(false)
    62  	p.ScaleCapacity(5)
    63  	var resources [10]Resource
    64  
    65  	// Test Get
    66  	for i := 0; i < 5; i++ {
    67  		r, err := p.Get(ctx)
    68  		resources[i] = r
    69  		if err != nil {
    70  			t.Errorf("Unexpected error %v", err)
    71  		}
    72  		if p.Available() != int64(5-i-1) {
    73  			t.Errorf("expecting %d, received %d", 5-i-1, p.Available())
    74  		}
    75  		if p.WaitCount() != 0 {
    76  			t.Errorf("expecting 0, received %d", p.WaitCount())
    77  		}
    78  		if p.WaitTime() != 0 {
    79  			t.Errorf("expecting 0, received %d", p.WaitTime())
    80  		}
    81  		if lastID.Get() != int64(i+1) {
    82  			t.Errorf("Expecting %d, received %d", i+1, lastID.Get())
    83  		}
    84  		if count.Get() != int64(i+1) {
    85  			t.Errorf("Expecting %d, received %d", i+1, count.Get())
    86  		}
    87  	}
    88  
    89  	// Test that Get waits
    90  	ch := make(chan bool)
    91  	go func() {
    92  		for i := 0; i < 5; i++ {
    93  			r, err := p.Get(ctx)
    94  			if err != nil {
    95  				t.Errorf("Get failed: %v", err)
    96  			}
    97  			resources[i] = r
    98  		}
    99  		for i := 0; i < 5; i++ {
   100  			p.Put(resources[i])
   101  		}
   102  		ch <- true
   103  	}()
   104  	for i := 0; i < 5; i++ {
   105  		// Sleep to ensure the goroutine waits
   106  		time.Sleep(10 * time.Millisecond)
   107  		p.Put(resources[i])
   108  	}
   109  	<-ch
   110  	if p.WaitCount() != 5 {
   111  		t.Errorf("Expecting 5, received %d", p.WaitCount())
   112  	}
   113  	if p.WaitTime() == 0 {
   114  		t.Errorf("Expecting non-zero")
   115  	}
   116  	if lastID.Get() != 5 {
   117  		t.Errorf("Expecting 5, received %d", lastID.Get())
   118  	}
   119  
   120  	// Test Close resource
   121  	r, err := p.Get(ctx)
   122  	if err != nil {
   123  		t.Errorf("Unexpected error %v", err)
   124  	}
   125  	r.Close()
   126  	p.Put(nil)
   127  	if count.Get() != 4 {
   128  		t.Errorf("Expecting 4, received %d", count.Get())
   129  	}
   130  	for i := 0; i < 5; i++ {
   131  		r, err := p.Get(ctx)
   132  		if err != nil {
   133  			t.Errorf("Get failed: %v", err)
   134  		}
   135  		resources[i] = r
   136  	}
   137  	for i := 0; i < 5; i++ {
   138  		p.Put(resources[i])
   139  	}
   140  	if count.Get() != 5 {
   141  		t.Errorf("Expecting 5, received %d", count.Get())
   142  	}
   143  	if lastID.Get() != 6 {
   144  		t.Errorf("Expecting 6, received %d", lastID.Get())
   145  	}
   146  
   147  	// ScaleCapacity
   148  	p.ScaleCapacity(3)
   149  	if count.Get() != 3 {
   150  		t.Errorf("Expecting 3, received %d", count.Get())
   151  	}
   152  	if lastID.Get() != 6 {
   153  		t.Errorf("Expecting 6, received %d", lastID.Get())
   154  	}
   155  	if p.Capacity() != 3 {
   156  		t.Errorf("Expecting 3, received %d", p.Capacity())
   157  	}
   158  	if p.Available() != 3 {
   159  		t.Errorf("Expecting 3, received %d", p.Available())
   160  	}
   161  	p.ScaleCapacity(6)
   162  	if p.Capacity() != 6 {
   163  		t.Errorf("Expecting 6, received %d", p.Capacity())
   164  	}
   165  	if p.Available() != 6 {
   166  		t.Errorf("Expecting 6, received %d", p.Available())
   167  	}
   168  	for i := 0; i < 6; i++ {
   169  		r, err := p.Get(ctx)
   170  		if err != nil {
   171  			t.Errorf("Get failed: %v", err)
   172  		}
   173  		resources[i] = r
   174  	}
   175  	for i := 0; i < 6; i++ {
   176  		p.Put(resources[i])
   177  	}
   178  	if count.Get() != 6 {
   179  		t.Errorf("Expecting 5, received %d", count.Get())
   180  	}
   181  	if lastID.Get() != 9 {
   182  		t.Errorf("Expecting 9, received %d", lastID.Get())
   183  	}
   184  
   185  	// Close
   186  	p.Close()
   187  	if p.Capacity() != 0 {
   188  		t.Errorf("Expecting 0, received %d", p.Capacity())
   189  	}
   190  	if p.Available() != 0 {
   191  		t.Errorf("Expecting 0, received %d", p.Available())
   192  	}
   193  	if count.Get() != 0 {
   194  		t.Errorf("Expecting 0, received %d", count.Get())
   195  	}
   196  }
   197  
   198  func TestOpenDynamic(t *testing.T) {
   199  	ctx := context.Background()
   200  	lastID.Set(0)
   201  	count.Set(0)
   202  	p := NewResourcePool(PoolFactory, 6, 10, time.Second)
   203  	p.ScaleCapacity(5)
   204  	p.SetDynamic(true)
   205  	var resources [10]Resource
   206  
   207  	// Test Get
   208  	for i := 0; i < 7; i++ {
   209  		r, err := p.Get(ctx)
   210  		resources[i] = r
   211  		if err != nil {
   212  			t.Errorf("Unexpected error %v", err)
   213  		}
   214  		if i < 5 {
   215  			if p.Available() != int64(5-i-1) {
   216  				t.Errorf("expecting %d, received %d", 5-i-1, p.Available())
   217  			}
   218  		} else {
   219  			if p.Available() != 0 {
   220  				t.Errorf("expecting %d, received %d", 0, p.Available())
   221  			}
   222  		}
   223  
   224  		if p.WaitCount() != 0 {
   225  			t.Errorf("expecting 0, received %d", p.WaitCount())
   226  		}
   227  		if p.WaitTime() != 0 {
   228  			t.Errorf("expecting 0, received %d", p.WaitTime())
   229  		}
   230  		if lastID.Get() != int64(i+1) {
   231  			t.Errorf("Expecting %d, received %d", i+1, lastID.Get())
   232  		}
   233  		if count.Get() != int64(i+1) {
   234  			t.Errorf("Expecting %d, received %d", i+1, count.Get())
   235  		}
   236  	}
   237  
   238  	// Test that Get waits
   239  	ch := make(chan bool)
   240  	go func() {
   241  		for i := 0; i < 7; i++ {
   242  			r, err := p.Get(ctx)
   243  			if err != nil {
   244  				t.Errorf("Get failed: %v", err)
   245  			}
   246  			resources[i] = r
   247  		}
   248  		for i := 0; i < 7; i++ {
   249  			p.Put(resources[i])
   250  		}
   251  		ch <- true
   252  	}()
   253  	for i := 0; i < 7; i++ {
   254  		// Sleep to ensure the goroutine waits
   255  		time.Sleep(10 * time.Millisecond)
   256  		p.Put(resources[i])
   257  	}
   258  	<-ch
   259  	if p.WaitCount() != 4 {
   260  		t.Errorf("Expecting 4, received %d", p.WaitCount())
   261  	}
   262  	if p.WaitTime() == 0 {
   263  		t.Errorf("Expecting non-zero")
   264  	}
   265  	if lastID.Get() != 10 {
   266  		t.Errorf("Expecting 10, received %d", lastID.Get())
   267  	}
   268  
   269  	// Test Close resource
   270  	r, err := p.Get(ctx)
   271  	if err != nil {
   272  		t.Errorf("Unexpected error %v", err)
   273  	}
   274  	r.Close()
   275  	p.Put(nil)
   276  	if count.Get() != 9 {
   277  		t.Errorf("Expecting 9, received %d", count.Get())
   278  	}
   279  	for i := 0; i < 5; i++ {
   280  		r, err := p.Get(ctx)
   281  		if err != nil {
   282  			t.Errorf("Get failed: %v", err)
   283  		}
   284  		resources[i] = r
   285  	}
   286  	for i := 0; i < 5; i++ {
   287  		p.Put(resources[i])
   288  	}
   289  	if count.Get() != 9 {
   290  		t.Errorf("Expecting 9, received %d", count.Get())
   291  	}
   292  	if lastID.Get() != 10 {
   293  		t.Errorf("Expecting 10, received %d", lastID.Get())
   294  	}
   295  }
   296  
   297  func TestShrinking(t *testing.T) {
   298  	ctx := context.Background()
   299  	lastID.Set(0)
   300  	count.Set(0)
   301  	p := NewResourcePool(PoolFactory, 5, 5, time.Second)
   302  	p.SetDynamic(false)
   303  	var resources [10]Resource
   304  	// Leave one empty slot in the pool
   305  	for i := 0; i < 4; i++ {
   306  		r, err := p.Get(ctx)
   307  		if err != nil {
   308  			t.Errorf("Get failed: %v", err)
   309  		}
   310  		resources[i] = r
   311  	}
   312  	done := make(chan bool)
   313  	go func() {
   314  		p.ScaleCapacity(3)
   315  		done <- true
   316  	}()
   317  	expected := `{"Capacity": 3, "Available": 0, "Active": 4, "InUse": 4, "MaxCapacity": 5, "WaitCount": 0, "WaitTime": 0, "IdleTimeout": 1000000000, "IdleClosed": 0}`
   318  	for i := 0; i < 10; i++ {
   319  		time.Sleep(10 * time.Millisecond)
   320  		stats := p.StatsJSON()
   321  		if stats != expected {
   322  			if i == 9 {
   323  				t.Errorf(`expecting '%s', received '%s'`, expected, stats)
   324  			}
   325  		}
   326  	}
   327  	// There are already 2 resources available in the pool.
   328  	// So, returning one should be enough for ScaleCapacity to complete.
   329  	p.Put(resources[3])
   330  	<-done
   331  	// Return the rest of the resources
   332  	for i := 0; i < 3; i++ {
   333  		p.Put(resources[i])
   334  	}
   335  	stats := p.StatsJSON()
   336  	expected = `{"Capacity": 3, "Available": 3, "Active": 3, "InUse": 0, "MaxCapacity": 5, "WaitCount": 0, "WaitTime": 0, "IdleTimeout": 1000000000, "IdleClosed": 0}`
   337  	if stats != expected {
   338  		t.Errorf(`expecting '%s', received '%s'`, expected, stats)
   339  	}
   340  	if count.Get() != 3 {
   341  		t.Errorf("Expecting 3, received %d", count.Get())
   342  	}
   343  
   344  	// Ensure no deadlock if ScaleCapacity is called after we start
   345  	// waiting for a resource
   346  	var err error
   347  	for i := 0; i < 3; i++ {
   348  		resources[i], err = p.Get(ctx)
   349  		if err != nil {
   350  			t.Errorf("Unexpected error %v", err)
   351  		}
   352  	}
   353  	// This will wait because pool is empty
   354  	go func() {
   355  		r, err := p.Get(ctx)
   356  		if err != nil {
   357  			t.Errorf("Unexpected error %v", err)
   358  		}
   359  		p.Put(r)
   360  		done <- true
   361  	}()
   362  
   363  	// This will also wait
   364  	go func() {
   365  		p.ScaleCapacity(2)
   366  		done <- true
   367  	}()
   368  	time.Sleep(10 * time.Millisecond)
   369  
   370  	// This should not hang
   371  	for i := 0; i < 3; i++ {
   372  		p.Put(resources[i])
   373  	}
   374  	<-done
   375  	<-done
   376  	if p.Capacity() != 2 {
   377  		t.Errorf("Expecting 2, received %d", p.Capacity())
   378  	}
   379  	if p.Available() != 2 {
   380  		t.Errorf("Expecting 2, received %d", p.Available())
   381  	}
   382  	if p.WaitCount() != 1 {
   383  		t.Errorf("Expecting 1, received %d", p.WaitCount())
   384  	}
   385  	if count.Get() != 2 {
   386  		t.Errorf("Expecting 2, received %d", count.Get())
   387  	}
   388  
   389  	// Test race condition of ScaleCapacity with itself
   390  	p.ScaleCapacity(3)
   391  	for i := 0; i < 3; i++ {
   392  		resources[i], err = p.Get(ctx)
   393  		if err != nil {
   394  			t.Errorf("Unexpected error %v", err)
   395  		}
   396  	}
   397  	// This will wait because pool is empty
   398  	go func() {
   399  		r, err := p.Get(ctx)
   400  		if err != nil {
   401  			t.Errorf("Unexpected error %v", err)
   402  		}
   403  		p.Put(r)
   404  		done <- true
   405  	}()
   406  	time.Sleep(10 * time.Millisecond)
   407  
   408  	// This will wait till we Put
   409  	go p.ScaleCapacity(2)
   410  	time.Sleep(10 * time.Millisecond)
   411  	go p.ScaleCapacity(4)
   412  	time.Sleep(10 * time.Millisecond)
   413  
   414  	// This should not hang
   415  	for i := 0; i < 3; i++ {
   416  		p.Put(resources[i])
   417  	}
   418  	<-done
   419  
   420  	err = p.ScaleCapacity(-1)
   421  	if err == nil {
   422  		t.Errorf("Expecting error")
   423  	}
   424  	err = p.ScaleCapacity(255555)
   425  	if err == nil {
   426  		t.Errorf("Expecting error")
   427  	}
   428  
   429  	if p.Capacity() != 4 {
   430  		t.Errorf("Expecting 4, received %d", p.Capacity())
   431  	}
   432  	if p.Available() != 4 {
   433  		t.Errorf("Expecting 4, received %d", p.Available())
   434  	}
   435  }
   436  
   437  func TestClosing(t *testing.T) {
   438  	ctx := context.Background()
   439  	lastID.Set(0)
   440  	count.Set(0)
   441  	p := NewResourcePool(PoolFactory, 5, 5, time.Second)
   442  	p.SetDynamic(false)
   443  	var resources [10]Resource
   444  	for i := 0; i < 5; i++ {
   445  		r, err := p.Get(ctx)
   446  		if err != nil {
   447  			t.Errorf("Get failed: %v", err)
   448  		}
   449  		resources[i] = r
   450  	}
   451  	ch := make(chan bool)
   452  	go func() {
   453  		p.Close()
   454  		ch <- true
   455  	}()
   456  
   457  	// Wait for goroutine to call Close
   458  	time.Sleep(10 * time.Millisecond)
   459  	stats := p.StatsJSON()
   460  	expected := `{"Capacity": 0, "Available": 0, "Active": 5, "InUse": 5, "MaxCapacity": 5, "WaitCount": 0, "WaitTime": 0, "IdleTimeout": 1000000000, "IdleClosed": 0}`
   461  	if stats != expected {
   462  		t.Errorf(`expecting '%s', received '%s'`, expected, stats)
   463  	}
   464  
   465  	// Put is allowed when closing
   466  	for i := 0; i < 5; i++ {
   467  		p.Put(resources[i])
   468  	}
   469  
   470  	// Wait for Close to return
   471  	<-ch
   472  
   473  	// ScaleCapacity must be ignored after Close
   474  	err := p.ScaleCapacity(1)
   475  	if err == nil {
   476  		t.Errorf("expecting error")
   477  	}
   478  
   479  	stats = p.StatsJSON()
   480  	expected = `{"Capacity": 0, "Available": 0, "Active": 0, "InUse": 0, "MaxCapacity": 5, "WaitCount": 0, "WaitTime": 0, "IdleTimeout": 1000000000, "IdleClosed": 0}`
   481  	if stats != expected {
   482  		t.Errorf(`expecting '%s', received '%s'`, expected, stats)
   483  	}
   484  	if lastID.Get() != 5 {
   485  		t.Errorf("Expecting 5, received %d", count.Get())
   486  	}
   487  	if count.Get() != 0 {
   488  		t.Errorf("Expecting 0, received %d", count.Get())
   489  	}
   490  }
   491  
   492  func TestIdleTimeout(t *testing.T) {
   493  	ctx := context.Background()
   494  	lastID.Set(0)
   495  	count.Set(0)
   496  	p := NewResourcePool(PoolFactory, 1, 1, 10*time.Millisecond)
   497  	p.SetDynamic(false)
   498  	defer p.Close()
   499  
   500  	r, err := p.Get(ctx)
   501  	if err != nil {
   502  		t.Errorf("Unexpected error %v", err)
   503  	}
   504  	if count.Get() != 1 {
   505  		t.Errorf("Expecting 1, received %d", count.Get())
   506  	}
   507  	if p.IdleClosed() != 0 {
   508  		t.Errorf("Expecting 0, received %d", p.IdleClosed())
   509  	}
   510  	p.Put(r)
   511  	if lastID.Get() != 1 {
   512  		t.Errorf("Expecting 1, received %d", count.Get())
   513  	}
   514  	if count.Get() != 1 {
   515  		t.Errorf("Expecting 1, received %d", count.Get())
   516  	}
   517  	if p.IdleClosed() != 0 {
   518  		t.Errorf("Expecting 0, received %d", p.IdleClosed())
   519  	}
   520  	time.Sleep(20 * time.Millisecond)
   521  
   522  	if count.Get() != 0 {
   523  		t.Errorf("Expecting 0, received %d", count.Get())
   524  	}
   525  	if p.IdleClosed() != 1 {
   526  		t.Errorf("Expecting 1, received %d", p.IdleClosed())
   527  	}
   528  	r, err = p.Get(ctx)
   529  	if err != nil {
   530  		t.Errorf("Unexpected error %v", err)
   531  	}
   532  	if lastID.Get() != 2 {
   533  		t.Errorf("Expecting 2, received %d", count.Get())
   534  	}
   535  	if count.Get() != 1 {
   536  		t.Errorf("Expecting 1, received %d", count.Get())
   537  	}
   538  	if p.IdleClosed() != 1 {
   539  		t.Errorf("Expecting 1, received %d", p.IdleClosed())
   540  	}
   541  
   542  	// sleep to let the idle closer run while all resources are in use
   543  	// then make sure things are still as we expect
   544  	time.Sleep(20 * time.Millisecond)
   545  	if lastID.Get() != 2 {
   546  		t.Errorf("Expecting 2, received %d", count.Get())
   547  	}
   548  	if count.Get() != 1 {
   549  		t.Errorf("Expecting 1, received %d", count.Get())
   550  	}
   551  	if p.IdleClosed() != 1 {
   552  		t.Errorf("Expecting 1, received %d", p.IdleClosed())
   553  	}
   554  	p.Put(r)
   555  	r, err = p.Get(ctx)
   556  	if err != nil {
   557  		t.Errorf("Unexpected error %v", err)
   558  	}
   559  	if lastID.Get() != 2 {
   560  		t.Errorf("Expecting 2, received %d", count.Get())
   561  	}
   562  	if count.Get() != 1 {
   563  		t.Errorf("Expecting 1, received %d", count.Get())
   564  	}
   565  	if p.IdleClosed() != 1 {
   566  		t.Errorf("Expecting 1, received %d", p.IdleClosed())
   567  	}
   568  
   569  	// the idle close thread wakes up every 1/100 of the idle time, so ensure
   570  	// the timeout change applies to newly added resources
   571  	p.SetIdleTimeout(1000 * time.Millisecond)
   572  	p.Put(r)
   573  
   574  	time.Sleep(20 * time.Millisecond)
   575  	if lastID.Get() != 2 {
   576  		t.Errorf("Expecting 2, received %d", count.Get())
   577  	}
   578  	if count.Get() != 1 {
   579  		t.Errorf("Expecting 1, received %d", count.Get())
   580  	}
   581  	if p.IdleClosed() != 1 {
   582  		t.Errorf("Expecting 1, received %d", p.IdleClosed())
   583  	}
   584  
   585  	p.SetIdleTimeout(10 * time.Millisecond)
   586  	time.Sleep(20 * time.Millisecond)
   587  	if lastID.Get() != 2 {
   588  		t.Errorf("Expecting 2, received %d", count.Get())
   589  	}
   590  	if count.Get() != 0 {
   591  		t.Errorf("Expecting 1, received %d", count.Get())
   592  	}
   593  	if p.IdleClosed() != 2 {
   594  		t.Errorf("Expecting 2, received %d", p.IdleClosed())
   595  	}
   596  }
   597  
   598  func TestCreateFail(t *testing.T) {
   599  	ctx := context.Background()
   600  	lastID.Set(0)
   601  	count.Set(0)
   602  	p := NewResourcePool(FailFactory, 5, 5, time.Second)
   603  	p.SetDynamic(false)
   604  	defer p.Close()
   605  	if _, err := p.Get(ctx); err.Error() != "Failed" {
   606  		t.Errorf("Expecting Failed, received %v", err)
   607  	}
   608  	stats := p.StatsJSON()
   609  	expected := `{"Capacity": 5, "Available": 5, "Active": 0, "InUse": 0, "MaxCapacity": 5, "WaitCount": 0, "WaitTime": 0, "IdleTimeout": 1000000000, "IdleClosed": 0}`
   610  	if stats != expected {
   611  		t.Errorf(`expecting '%s', received '%s'`, expected, stats)
   612  	}
   613  }
   614  
   615  func TestSlowCreateFail(t *testing.T) {
   616  	ctx := context.Background()
   617  	lastID.Set(0)
   618  	count.Set(0)
   619  	p := NewResourcePool(SlowFailFactory, 2, 2, time.Second)
   620  	p.SetDynamic(false)
   621  	defer p.Close()
   622  	ch := make(chan bool)
   623  	// The third Get should not wait indefinitely
   624  	for i := 0; i < 3; i++ {
   625  		go func() {
   626  			p.Get(ctx)
   627  			ch <- true
   628  		}()
   629  	}
   630  	for i := 0; i < 3; i++ {
   631  		<-ch
   632  	}
   633  	if p.Available() != 2 {
   634  		t.Errorf("Expecting 2, received %d", p.Available())
   635  	}
   636  }
   637  
   638  func TestTimeout(t *testing.T) {
   639  	ctx := context.Background()
   640  	lastID.Set(0)
   641  	count.Set(0)
   642  	p := NewResourcePool(PoolFactory, 1, 1, time.Second)
   643  	p.SetDynamic(false)
   644  	defer p.Close()
   645  	r, err := p.Get(ctx)
   646  	if err != nil {
   647  		t.Fatal(err)
   648  	}
   649  	newctx, cancel := context.WithTimeout(ctx, 1*time.Millisecond)
   650  	_, err = p.Get(newctx)
   651  	cancel()
   652  	want := "resource pool timed out"
   653  	if err == nil || err.Error() != want {
   654  		t.Errorf("got %v, want %s", err, want)
   655  	}
   656  	p.Put(r)
   657  }
   658  
   659  func TestExpired(t *testing.T) {
   660  	lastID.Set(0)
   661  	count.Set(0)
   662  	p := NewResourcePool(PoolFactory, 1, 1, time.Second)
   663  	p.SetDynamic(false)
   664  	defer p.Close()
   665  	ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-1*time.Second))
   666  	r, err := p.Get(ctx)
   667  	if err == nil {
   668  		p.Put(r)
   669  	}
   670  	cancel()
   671  	want := "resource pool timed out"
   672  	if err == nil || err.Error() != want {
   673  		t.Errorf("got %v, want %s", err, want)
   674  	}
   675  }