e3bffa5135231b376b52ec7daf3588e7dd60f6a8
[ric-plt/nodeb-rnib.git] / common / rNibPool_test.go
1 //
2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 package common
18
19 import (
20         "github.com/stretchr/testify/assert"
21         "sync"
22         "sync/atomic"
23         "testing"
24         "time"
25 )
26
27 var     max int32
28 var     counter int32
29 var poolGlob *Pool
30 type instance struct{}
31
32 func(instance) up(){
33         tmpc := atomic.AddInt32(&counter, 1)
34         swapped:= false
35         for !swapped {
36                 tmpm := atomic.LoadInt32(&max)
37                 if tmpc >tmpm {
38                         swapped = atomic.CompareAndSwapInt32(&max, tmpm, tmpc)
39                 } else {
40                         break
41                 }
42         }
43 }
44
45 func(instance) down(){
46         atomic.AddInt32(&counter, - 1)
47 }
48
49 func TestPoolMax(t *testing.T){
50         counter = 0
51         max = 0
52         validateMaxLimit(1, 1, t)
53         counter = 0
54         max = 0
55         validateMaxLimit(1, 2, t)
56         counter = 0
57         max = 0
58         validateMaxLimit(5, 10, t)
59 }
60
61 func validateMaxLimit(size int, iterations int, t *testing.T) {
62         poolGlob = NewPool(size, func() interface{} {
63                 inst := instance{}
64                 return inst
65         },
66                 func(obj interface{}) {
67                 },
68         )
69         group := sync.WaitGroup{}
70         for i := 0; i < iterations; i++ {
71                 group.Add(1)
72                 go func() {
73                         getPutInstance()
74                         group.Done()
75                 }()
76         }
77         time.Sleep(time.Second)
78         group.Wait()
79         assert.Equal(t, int32(size), max)
80 }
81
82 func getPutInstance() {
83         inst := poolGlob.Get().(instance)
84         inst.up()
85         time.Sleep(time.Millisecond*10)
86         inst.down()
87         poolGlob.Put(inst)
88 }
89
90 func TestNewPool(t *testing.T){
91         size := 5
92         pool := NewPool(size, func() interface{} {
93                 inst := instance{}
94                 return inst
95         },
96                 func(obj interface{}) {
97                 },
98         )
99         assert.NotNil(t, pool)
100         assert.NotNil(t, pool.New)
101         assert.NotNil(t, pool.Destroy)
102         assert.NotNil(t, pool.pool)
103         assert.Equal(t, cap(pool.pool), size, "the capacity of the pool should be " + string(size))
104 }
105
106 func TestGetCreated(t *testing.T) {
107         pool := NewPool(1, func() interface{} {
108                 inst := instance{}
109                 return inst
110         },
111                 func(obj interface{}) {
112                 },
113         )
114         pool.Get()
115         available, created := pool.Stats()
116         assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
117         assert.Equal(t, 1, created, "number of created objects in the pool should be 1")
118         pool.Close()
119 }
120
121 func TestGetAndPut(t *testing.T) {
122         pool := NewPool(1, func() interface{} {
123                 inst := instance{}
124                 return inst
125         },
126                 func(obj interface{}) {
127                 },
128         )
129         pool.Put(pool.Get())
130         available, created := pool.Stats()
131         assert.Equal(t, 1, available, "number of available objects in the pool should be 1")
132         assert.Equal(t, 1, created, "number of created objects in the pool should be 1")
133         pool.Close()
134 }
135
136 func TestPutOutOfCapacity(t *testing.T) {
137         pool := NewPool(1, func() interface{} {
138                 inst := instance{}
139                 return inst
140         },
141                 func(obj interface{}) {
142                 },
143         )
144         pool.Put(pool.Get())
145         pool.Put(new(instance))
146         available, created := pool.Stats()
147         assert.Equal(t, 1, available, "number of available objects in the pool should be 1")
148         assert.Equal(t, 1, created, "number of created objects in the pool should be 1")
149         pool.Close()
150 }
151
152 func TestNotInitializedPut(t *testing.T) {
153         var poolEmpty Pool
154         poolEmpty.Put(new(instance))
155         available, created := poolEmpty.Stats()
156         assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
157         assert.Equal(t, 0, created, "number of created objects in the pool should be 0")
158 }
159
160 func TestPutNilObject(t *testing.T) {
161         var poolEmpty Pool
162         poolEmpty.Put(nil)
163         available, created := poolEmpty.Stats()
164         assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
165         assert.Equal(t, 0, created, "number of created objects in the pool should be 0")
166 }
167
168 func TestGet(t *testing.T) {
169         pool := NewPool(2, func() interface{} {
170                 inst := instance{}
171                 return inst
172         },
173                 func(obj interface{}) {
174                 },
175         )
176         i1 := pool.Get()
177         i2 := pool.Get()
178         available, created := pool.Stats()
179         assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
180         assert.Equal(t, 2, created, "number of created objects in the pool should be 2")
181         pool.Put(i1)
182         pool.Put(i2)
183         pool.Put(new(instance))
184         available, created = pool.Stats()
185         assert.Equal(t, 2, available, "number of available objects in the pool should be 2")
186         assert.Equal(t, 2, created, "number of created objects in the pool should be 2")
187 }
188
189 func TestClose(t *testing.T) {
190         pool := NewPool(3, func() interface{} {
191                 inst := instance{}
192                 return inst
193         },
194                 func(obj interface{}) {
195                 },
196         )
197         i1 := pool.Get()
198         i2 := pool.Get()
199         i3 := pool.Get()
200         available, created := pool.Stats()
201         assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
202         assert.Equal(t, 3, created, "number of created objects in the pool should be 3")
203         pool.Put(i1)
204         pool.Put(i2)
205         pool.Put(i3)
206         available, created = pool.Stats()
207         assert.Equal(t, 3, available, "number of available objects in the pool should be 3")
208         assert.Equal(t, 3, created, "number of created objects in the pool should be 3")
209         pool.Close()
210         i := pool.Get()
211         assert.Nil(t, i)
212         available, created = pool.Stats()
213         assert.Equal(t, 0, available, "number of available objects in the pool should be 0")
214         assert.Equal(t, 0, created, "number of created objects in the pool should be 0")
215 }
216
217 func TestPoolPutPanicsOnClosedChannel(t *testing.T){
218         pool := NewPool(1, func() interface{} {
219                 inst := instance{}
220                 return inst
221         },
222                 func(obj interface{}) {
223                 },
224         )
225         close(pool.pool)
226         assert.Panics(t, func(){pool.Put(instance{})})
227 }
228
229 func TestPoolClosePanicsOnClosedChannel(t *testing.T) {
230         pool := NewPool(1, func() interface{} {
231                 inst := instance{}
232                 return inst
233         },
234                 func(obj interface{}) {
235                 },
236         )
237         close(pool.pool)
238         assert.Panics(t, func(){pool.Close()})
239 }