blob: e3bffa5135231b376b52ec7daf3588e7dd60f6a8 [file] [log] [blame]
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package common
import (
"github.com/stretchr/testify/assert"
"sync"
"sync/atomic"
"testing"
"time"
)
var max int32
var counter int32
var poolGlob *Pool
type instance struct{}
func(instance) up(){
tmpc := atomic.AddInt32(&counter, 1)
swapped:= false
for !swapped {
tmpm := atomic.LoadInt32(&max)
if tmpc >tmpm {
swapped = atomic.CompareAndSwapInt32(&max, tmpm, tmpc)
} else {
break
}
}
}
func(instance) down(){
atomic.AddInt32(&counter, - 1)
}
func TestPoolMax(t *testing.T){
counter = 0
max = 0
validateMaxLimit(1, 1, t)
counter = 0
max = 0
validateMaxLimit(1, 2, t)
counter = 0
max = 0
validateMaxLimit(5, 10, t)
}
func validateMaxLimit(size int, iterations int, t *testing.T) {
poolGlob = NewPool(size, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
group := sync.WaitGroup{}
for i := 0; i < iterations; i++ {
group.Add(1)
go func() {
getPutInstance()
group.Done()
}()
}
time.Sleep(time.Second)
group.Wait()
assert.Equal(t, int32(size), max)
}
func getPutInstance() {
inst := poolGlob.Get().(instance)
inst.up()
time.Sleep(time.Millisecond*10)
inst.down()
poolGlob.Put(inst)
}
func TestNewPool(t *testing.T){
size := 5
pool := NewPool(size, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
assert.NotNil(t, pool)
assert.NotNil(t, pool.New)
assert.NotNil(t, pool.Destroy)
assert.NotNil(t, pool.pool)
assert.Equal(t, cap(pool.pool), size, "the capacity of the pool should be " + string(size))
}
func TestGetCreated(t *testing.T) {
pool := NewPool(1, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
pool.Get()
available, created := pool.Stats()
assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
assert.Equal(t, 1, created, "number of created objects in the pool should be 1")
pool.Close()
}
func TestGetAndPut(t *testing.T) {
pool := NewPool(1, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
pool.Put(pool.Get())
available, created := pool.Stats()
assert.Equal(t, 1, available, "number of available objects in the pool should be 1")
assert.Equal(t, 1, created, "number of created objects in the pool should be 1")
pool.Close()
}
func TestPutOutOfCapacity(t *testing.T) {
pool := NewPool(1, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
pool.Put(pool.Get())
pool.Put(new(instance))
available, created := pool.Stats()
assert.Equal(t, 1, available, "number of available objects in the pool should be 1")
assert.Equal(t, 1, created, "number of created objects in the pool should be 1")
pool.Close()
}
func TestNotInitializedPut(t *testing.T) {
var poolEmpty Pool
poolEmpty.Put(new(instance))
available, created := poolEmpty.Stats()
assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
assert.Equal(t, 0, created, "number of created objects in the pool should be 0")
}
func TestPutNilObject(t *testing.T) {
var poolEmpty Pool
poolEmpty.Put(nil)
available, created := poolEmpty.Stats()
assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
assert.Equal(t, 0, created, "number of created objects in the pool should be 0")
}
func TestGet(t *testing.T) {
pool := NewPool(2, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
i1 := pool.Get()
i2 := pool.Get()
available, created := pool.Stats()
assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
assert.Equal(t, 2, created, "number of created objects in the pool should be 2")
pool.Put(i1)
pool.Put(i2)
pool.Put(new(instance))
available, created = pool.Stats()
assert.Equal(t, 2, available, "number of available objects in the pool should be 2")
assert.Equal(t, 2, created, "number of created objects in the pool should be 2")
}
func TestClose(t *testing.T) {
pool := NewPool(3, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
i1 := pool.Get()
i2 := pool.Get()
i3 := pool.Get()
available, created := pool.Stats()
assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
assert.Equal(t, 3, created, "number of created objects in the pool should be 3")
pool.Put(i1)
pool.Put(i2)
pool.Put(i3)
available, created = pool.Stats()
assert.Equal(t, 3, available, "number of available objects in the pool should be 3")
assert.Equal(t, 3, created, "number of created objects in the pool should be 3")
pool.Close()
i := pool.Get()
assert.Nil(t, i)
available, created = pool.Stats()
assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
assert.Equal(t, 0, created, "number of created objects in the pool should be 0")
}
func TestPoolPutPanicsOnClosedChannel(t *testing.T){
pool := NewPool(1, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
close(pool.pool)
assert.Panics(t, func(){pool.Put(instance{})})
}
func TestPoolClosePanicsOnClosedChannel(t *testing.T) {
pool := NewPool(1, func() interface{} {
inst := instance{}
return inst
},
func(obj interface{}) {
},
)
close(pool.pool)
assert.Panics(t, func(){pool.Close()})
}