github.phpd.cn/cilium/cilium@v1.6.12/pkg/idpool/idpool_test.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build !privileged_tests 16 17 package idpool 18 19 import ( 20 "sort" 21 "sync" 22 "testing" 23 24 "github.com/cilium/cilium/pkg/checker" 25 26 . "gopkg.in/check.v1" 27 ) 28 29 func Test(t *testing.T) { 30 TestingT(t) 31 } 32 33 type IDPoolTestSuite struct{} 34 35 var _ = Suite(&IDPoolTestSuite{}) 36 37 func (s *IDPoolTestSuite) TestLeaseAvailableID(c *C) { 38 minID, maxID := 1, 5 39 p := NewIDPool(ID(minID), ID(maxID)) 40 41 leaseAllIDs(p, minID, maxID, c) 42 } 43 44 func (s *IDPoolTestSuite) TestInsertIDs(c *C) { 45 minID, maxID := 2, 6 46 p := NewIDPool(ID(minID), ID(maxID)) 47 48 // Insert IDs beyond minID, maxID range. 49 for i := minID - 1; i <= maxID+1; i++ { 50 c.Assert(p.Insert(ID(i)), Equals, i < minID || i > maxID) 51 c.Assert(p.Insert(ID(i)), Equals, false) 52 } 53 54 leaseAllIDs(p, minID-1, maxID+1, c) 55 } 56 57 func (s *IDPoolTestSuite) TestInsertRemoveIDs(c *C) { 58 minID, maxID := 1, 5 59 p := NewIDPool(ID(minID), ID(maxID)) 60 61 // Remove all IDs. 62 for i := minID; i <= maxID; i++ { 63 c.Assert(p.Remove(ID(i)), Equals, true) 64 c.Assert(p.Remove(ID(i)), Equals, false) 65 } 66 // We should be out of IDs. 67 id := p.LeaseAvailableID() 68 c.Assert(id, Equals, NoID) 69 70 // Re-insert all IDs. 71 for i := minID; i <= maxID; i++ { 72 c.Assert(p.Insert(ID(i)), Equals, true) 73 c.Assert(p.Insert(ID(i)), Equals, false) 74 } 75 76 // Remove odd-numbered IDs. 77 for i := minID; i <= maxID; i++ { 78 if i%2 != 0 { 79 c.Assert(p.Remove(ID(i)), Equals, true) 80 } 81 } 82 83 // Only even-numbered IDs should be left. 84 evenIDs := make([]int, 0) 85 actualIDs := make([]int, 0) 86 for i := minID; i <= maxID; i++ { 87 if i%2 == 0 { 88 id := p.LeaseAvailableID() 89 c.Assert(id, Not(Equals), NoID) 90 actualIDs = append(actualIDs, int(id)) 91 evenIDs = append(evenIDs, i) 92 } 93 } 94 // We should be out of IDs. 95 id = p.LeaseAvailableID() 96 c.Assert(id, Equals, NoID) 97 98 sort.Ints(actualIDs) 99 c.Assert(actualIDs, checker.DeepEquals, evenIDs) 100 } 101 102 func (s *IDPoolTestSuite) TestReleaseID(c *C) { 103 minID, maxID := 1, 5 104 p := NewIDPool(ID(minID), ID(maxID)) 105 106 // Lease all ids and release them. 107 for i := minID; i <= maxID; i++ { 108 id := p.LeaseAvailableID() 109 c.Assert(id, Not(Equals), NoID) 110 } 111 // We should be out of IDs. 112 id := p.LeaseAvailableID() 113 c.Assert(id, Equals, NoID) 114 115 for i := minID; i <= maxID; i++ { 116 c.Assert(p.Release(ID(i)), Equals, true) 117 c.Assert(p.Release(ID(i)), Equals, false) 118 } 119 120 // Lease all ids. This time, remove them before 121 // releasing them. 122 leaseAllIDs(p, minID, maxID, c) 123 for i := minID; i <= maxID; i++ { 124 c.Assert(p.Remove(ID(i)), Equals, false) 125 } 126 // Release should not have any effect. 127 for i := minID; i <= maxID; i++ { 128 c.Assert(p.Release(ID(i)), Equals, false) 129 } 130 } 131 132 func (s *IDPoolTestSuite) TestOperationsOnAvailableIDs(c *C) { 133 minID, maxID := 1, 5 134 135 // Leasing available IDs should move its state to leased. 136 p0 := NewIDPool(ID(minID), ID(maxID)) 137 leaseAllIDs(p0, minID, maxID, c) 138 // Check all IDs are in leased state. 139 for i := minID; i <= maxID; i++ { 140 c.Assert(p0.Release(ID(i)), Equals, true) 141 } 142 leaseAllIDs(p0, minID, maxID, c) 143 144 // Releasing available IDs should not have any effect. 145 p1 := NewIDPool(ID(minID), ID(maxID)) 146 for i := minID; i <= maxID; i++ { 147 c.Assert(p1.Release(ID(i)), Equals, false) 148 } 149 leaseAllIDs(p1, minID, maxID, c) 150 151 // Using available IDs should not have any effect. 152 p2 := NewIDPool(ID(minID), ID(maxID)) 153 for i := minID; i <= maxID; i++ { 154 c.Assert(p2.Use(ID(i)), Equals, false) 155 } 156 leaseAllIDs(p2, minID, maxID, c) 157 158 // Inserting available IDs should not have any effect. 159 p3 := NewIDPool(ID(minID), ID(maxID)) 160 for i := minID; i <= maxID; i++ { 161 c.Assert(p3.Insert(ID(i)), Equals, false) 162 } 163 leaseAllIDs(p3, minID, maxID, c) 164 165 // Removing available IDs should make them unavailable. 166 p4 := NewIDPool(ID(minID), ID(maxID)) 167 for i := minID; i <= maxID; i++ { 168 c.Assert(p4.Remove(ID(i)), Equals, true) 169 } 170 leaseAllIDs(p4, minID, minID-1, c) 171 for i := minID; i <= maxID; i++ { 172 c.Assert(p4.Release(ID(i)), Equals, false) 173 } 174 } 175 176 func (s *IDPoolTestSuite) TestOperationsOnLeasedIDs(c *C) { 177 minID, maxID := 1, 5 178 var poolWithAllIDsLeased = func() *IDPool { 179 p := NewIDPool(ID(minID), ID(maxID)) 180 leaseAllIDs(p, minID, maxID, c) 181 return p 182 } 183 184 // Releasing leased IDs should make it available again. 185 p0 := poolWithAllIDsLeased() 186 for i := minID; i <= maxID; i++ { 187 c.Assert(p0.Release(ID(i)), Equals, true) 188 } 189 leaseAllIDs(p0, minID, maxID, c) 190 191 // Using leased IDs should make it unavailable again. 192 p1 := poolWithAllIDsLeased() 193 for i := minID; i <= maxID; i++ { 194 c.Assert(p1.Use(ID(i)), Equals, true) 195 // It should no longer be leased. 196 c.Assert(p1.Use(ID(i)), Equals, false) 197 } 198 leaseAllIDs(p1, minID, minID-1, c) 199 200 // Inserting leased IDs should not have any effect. 201 p2 := poolWithAllIDsLeased() 202 for i := minID; i <= maxID; i++ { 203 c.Assert(p2.Insert(ID(i)), Equals, false) 204 } 205 // The IDs should still be leased. 206 for i := minID; i <= maxID; i++ { 207 c.Assert(p2.Release(ID(i)), Equals, true) 208 } 209 leaseAllIDs(p2, minID, maxID, c) 210 211 // Removing leased IDs should make them unavailable. 212 p3 := poolWithAllIDsLeased() 213 for i := minID; i <= maxID; i++ { 214 c.Assert(p3.Remove(ID(i)), Equals, false) 215 } 216 // The IDs should not be leased anymore. 217 for i := minID; i <= maxID; i++ { 218 c.Assert(p3.Use(ID(i)), Equals, false) 219 } 220 // They should be unavailable. 221 leaseAllIDs(p3, minID, minID-1, c) 222 } 223 224 func (s *IDPoolTestSuite) TestOperationsOnUnavailableIDs(c *C) { 225 minID, maxID := 1, 5 226 var poolWithAllIDsUnavailable = func() *IDPool { 227 p := NewIDPool(ID(minID), ID(maxID)) 228 for i := minID; i <= maxID; i++ { 229 c.Assert(p.Remove(ID(i)), Equals, true) 230 } 231 return p 232 } 233 234 // Releasing unavailable IDs should not have any effect. 235 p1 := poolWithAllIDsUnavailable() 236 for i := minID; i <= maxID; i++ { 237 c.Assert(p1.Release(ID(i)), Equals, false) 238 } 239 leaseAllIDs(p1, minID, minID-1, c) 240 241 // Using unavailable IDs should not have any effect. 242 p2 := poolWithAllIDsUnavailable() 243 for i := minID; i <= maxID; i++ { 244 c.Assert(p2.Use(ID(i)), Equals, false) 245 } 246 leaseAllIDs(p2, minID, minID-1, c) 247 248 // Inserting unavailable IDs should make them available. 249 p3 := poolWithAllIDsUnavailable() 250 for i := minID; i <= maxID; i++ { 251 c.Assert(p3.Insert(ID(i)), Equals, true) 252 } 253 // They should not be leased. 254 for i := minID; i <= maxID; i++ { 255 c.Assert(p3.Use(ID(i)), Equals, false) 256 c.Assert(p3.Release(ID(i)), Equals, false) 257 } 258 leaseAllIDs(p3, minID, maxID, c) 259 260 // Removing unavailable IDs should not have any effect. 261 p4 := poolWithAllIDsUnavailable() 262 for i := minID; i <= maxID; i++ { 263 c.Assert(p4.Remove(ID(i)), Equals, false) 264 } 265 leaseAllIDs(p4, minID, minID-1, c) 266 } 267 268 func leaseAllIDs(p *IDPool, minID int, maxID int, c *C) { 269 expected := make([]int, 0) 270 actual := make([]int, 0) 271 for i := minID; i <= maxID; i++ { 272 id := p.LeaseAvailableID() 273 c.Assert(id, Not(Equals), NoID) 274 actual = append(actual, int(id)) 275 expected = append(expected, i) 276 } 277 // We should be out of IDs. 278 id := p.LeaseAvailableID() 279 c.Assert(id, Equals, NoID) 280 281 // Unique ids must have been leased. 282 sort.Ints(actual) 283 c.Assert(actual, checker.DeepEquals, expected) 284 } 285 286 func (s *IDPoolTestSuite) BenchmarkRemoveIDs(c *C) { 287 minID, maxID := 1, c.N 288 p := NewIDPool(ID(minID), ID(maxID)) 289 290 c.ResetTimer() 291 for i := minID; i <= maxID; i++ { 292 c.Assert(p.Remove(ID(i)), Equals, true) 293 } 294 } 295 296 func (s *IDPoolTestSuite) BenchmarkLeaseIDs(c *C) { 297 minID, maxID := 1, c.N 298 p := NewIDPool(ID(minID), ID(maxID)) 299 300 c.ResetTimer() 301 for i := 1; i <= c.N; i++ { 302 id := p.LeaseAvailableID() 303 c.Assert(p.Release(ID(id)), Equals, true) 304 } 305 } 306 307 func (s *IDPoolTestSuite) BenchmarkUseAndRelease(c *C) { 308 minID, maxID := 1, c.N 309 p := NewIDPool(ID(minID), ID(maxID)) 310 311 c.ResetTimer() 312 for i := 1; i <= c.N; i++ { 313 id := p.LeaseAvailableID() 314 c.Assert(p.Use(ID(id)), Equals, true) 315 } 316 317 for i := 1; i <= c.N; i++ { 318 c.Assert(p.Insert(ID(i)), Equals, true) 319 } 320 } 321 322 func (s *IDPoolTestSuite) TestAllocateID(c *C) { 323 minID, maxID := 1, 6000 324 p := NewIDPool(ID(minID), ID(maxID)) 325 326 allocated := make(chan ID, 100) 327 var allocators sync.WaitGroup 328 329 for i := 0; i < 256; i++ { 330 allocators.Add(1) 331 go func() { 332 for i := 1; i <= maxID; i++ { 333 id := p.AllocateID() 334 c.Assert(id, Not(Equals), NoID) 335 allocated <- id 336 } 337 allocators.Done() 338 }() 339 } 340 341 go func() { 342 allocators.Wait() 343 close(allocated) 344 }() 345 346 for id := range allocated { 347 c.Assert(p.Insert(id), Equals, true) 348 } 349 }