1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

IPAM and Bitseq test cases

This commit contains test cases to verify the changes and to
solidify the library.

Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
This commit is contained in:
Abhinandan Prativadi 2018-03-08 10:39:30 -08:00
parent fe629b6eba
commit a0085a47fd
2 changed files with 149 additions and 34 deletions

View file

@ -192,6 +192,11 @@ func TestGetFirstAvailable(t *testing.T) {
{&sequence{block: 0xffffffff, count: 1, next: &sequence{block: 0xfffffffe, count: 1, next: &sequence{block: 0xffffffff, count: 6}}}, 7, 7, 0},
{&sequence{block: 0xffffffff, count: 2, next: &sequence{block: 0x0, count: 6}}, 8, 0, 0},
{&sequence{block: 0xfffcffff, count: 1, next: &sequence{block: 0x0, count: 6}}, 4, 0, 16},
{&sequence{block: 0xfffcffff, count: 1, next: &sequence{block: 0x0, count: 6}}, 1, 7, 15},
{&sequence{block: 0xfffcffff, count: 1, next: &sequence{block: 0x0, count: 6}}, 1, 6, 10},
{&sequence{block: 0xfffcfffe, count: 1, next: &sequence{block: 0x0, count: 6}}, 3, 7, 31},
{&sequence{block: 0xfffcffff, count: 1, next: &sequence{block: 0xffffffff, count: 6}}, invalidPos, invalidPos, 31},
}
for n, i := range input {
@ -1238,7 +1243,7 @@ func TestIsCorrupted(t *testing.T) {
}
}
func TestSetRollover(t *testing.T) {
func testSetRollover(t *testing.T, serial bool) {
ds, err := randomLocalStore()
if err != nil {
t.Fatal(err)
@ -1253,7 +1258,7 @@ func TestSetRollover(t *testing.T) {
// Allocate first half of the bits
for i := 0; i < numBits/2; i++ {
_, err := hnd.SetAny(true)
_, err := hnd.SetAny(serial)
if err != nil {
t.Fatalf("Unexpected failure on allocation %d: %v\n%s", i, err, hnd)
}
@ -1276,12 +1281,12 @@ func TestSetRollover(t *testing.T) {
}
}
if hnd.Unselected() != uint64(3*numBits/4) {
t.Fatalf("Expected full sequence. Instead found %d free bits.\nSeed: %d.\n%s", hnd.unselected, seed, hnd)
t.Fatalf("Unexpected free bits: found %d free bits.\nSeed: %d.\n%s", hnd.unselected, seed, hnd)
}
//request to allocate for remaining half of the bits
for i := 0; i < numBits/2; i++ {
_, err := hnd.SetAny(true)
_, err := hnd.SetAny(serial)
if err != nil {
t.Fatalf("Unexpected failure on allocation %d: %v\nSeed: %d\n%s", i, err, seed, hnd)
}
@ -1294,7 +1299,7 @@ func TestSetRollover(t *testing.T) {
}
for i := 0; i < numBits/4; i++ {
_, err := hnd.SetAny(true)
_, err := hnd.SetAny(serial)
if err != nil {
t.Fatalf("Unexpected failure on allocation %d: %v\nSeed: %d\n%s", i, err, seed, hnd)
}
@ -1302,7 +1307,7 @@ func TestSetRollover(t *testing.T) {
//Now requesting to allocate the unallocated random bits (qurter of the number of bits) should
//leave no more bits that can be allocated.
if hnd.Unselected() != 0 {
t.Fatalf("Unexpected number of unselected bits %d, Expected %d", hnd.Unselected(), numBits/4)
t.Fatalf("Unexpected number of unselected bits %d, Expected %d", hnd.Unselected(), 0)
}
err = hnd.Destroy()
@ -1310,3 +1315,47 @@ func TestSetRollover(t *testing.T) {
t.Fatal(err)
}
}
func TestSetRollover(t *testing.T) {
testSetRollover(t, false)
}
func TestSetRolloverSerial(t *testing.T) {
testSetRollover(t, true)
}
func TestGetFirstAvailableFromCurrent(t *testing.T) {
input := []struct {
mask *sequence
bytePos uint64
bitPos uint64
start uint64
curr uint64
end uint64
}{
{&sequence{block: 0xffffffff, count: 2048}, invalidPos, invalidPos, 0, 0, 65536},
{&sequence{block: 0x0, count: 8}, 0, 0, 0, 0, 256},
{&sequence{block: 0x80000000, count: 8}, 1, 0, 0, 8, 256},
{&sequence{block: 0xC0000000, count: 8}, 0, 2, 0, 2, 256},
{&sequence{block: 0xE0000000, count: 8}, 0, 3, 0, 0, 256},
{&sequence{block: 0xFFFB1FFF, count: 8}, 2, 0, 14, 0, 256},
{&sequence{block: 0xFFFFFFFE, count: 8}, 3, 7, 0, 0, 256},
{&sequence{block: 0xffffffff, count: 1, next: &sequence{block: 0x00000000, count: 1, next: &sequence{block: 0xffffffff, count: 14}}}, 4, 0, 0, 32, 512},
{&sequence{block: 0xfffeffff, count: 1, next: &sequence{block: 0xffffffff, count: 15}}, 1, 7, 0, 16, 512},
{&sequence{block: 0xfffeffff, count: 15, next: &sequence{block: 0xffffffff, count: 1}}, 5, 7, 0, 16, 512},
{&sequence{block: 0xfffeffff, count: 15, next: &sequence{block: 0xffffffff, count: 1}}, 9, 7, 0, 48, 512},
{&sequence{block: 0xffffffff, count: 2, next: &sequence{block: 0xffffffef, count: 14}}, 19, 3, 0, 124, 512},
{&sequence{block: 0xfffeffff, count: 15, next: &sequence{block: 0x0fffffff, count: 1}}, 60, 0, 0, 480, 512},
{&sequence{block: 0xffffffff, count: 1, next: &sequence{block: 0xfffeffff, count: 14, next: &sequence{block: 0xffffffff, count: 1}}}, 17, 7, 0, 124, 512},
{&sequence{block: 0xfffffffb, count: 1, next: &sequence{block: 0xffffffff, count: 14, next: &sequence{block: 0xffffffff, count: 1}}}, 3, 5, 0, 124, 512},
{&sequence{block: 0xfffffffb, count: 1, next: &sequence{block: 0xfffeffff, count: 14, next: &sequence{block: 0xffffffff, count: 1}}}, 13, 7, 0, 80, 512},
}
for n, i := range input {
bytePos, bitPos, _ := getAvailableFromCurrent(i.mask, i.start, i.curr, i.end)
if bytePos != i.bytePos || bitPos != i.bitPos {
t.Fatalf("Error in (%d) getFirstAvailable(). Expected (%d, %d). Got (%d, %d)", n, i.bytePos, i.bitPos, bytePos, bitPos)
}
}
}

View file

@ -8,6 +8,7 @@ import (
"math/rand"
"net"
"strconv"
"sync"
"testing"
"time"
@ -30,7 +31,10 @@ func init() {
}
// OptionBoltdbWithRandomDBFile function returns a random dir for local store backend
func randomLocalStore() (datastore.DataStore, error) {
func randomLocalStore(needStore bool) (datastore.DataStore, error) {
if !needStore {
return nil, nil
}
tmp, err := ioutil.TempFile("", "libnetwork-")
if err != nil {
return nil, fmt.Errorf("Error creating temp file: %v", err)
@ -50,17 +54,13 @@ func randomLocalStore() (datastore.DataStore, error) {
})
}
func getAllocator() (*Allocator, error) {
func getAllocator(store bool) (*Allocator, error) {
ipamutils.InitNetworks(nil)
ds, err := randomLocalStore()
ds, err := randomLocalStore(store)
if err != nil {
return nil, err
}
a, err := NewAllocator(ds, nil)
if err != nil {
return nil, err
}
return a, nil
return NewAllocator(ds, nil)
}
func TestInt2IP2IntConversion(t *testing.T) {
@ -170,7 +170,7 @@ func TestPoolDataMarshal(t *testing.T) {
}
func TestSubnetsMarshal(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -217,7 +217,7 @@ func TestSubnetsMarshal(t *testing.T) {
}
func TestAddSubnets(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -286,7 +286,7 @@ func TestAddSubnets(t *testing.T) {
func TestAddReleasePoolID(t *testing.T) {
var k0, k1, k2 SubnetKey
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -448,7 +448,7 @@ func TestAddReleasePoolID(t *testing.T) {
}
func TestPredefinedPool(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -476,7 +476,7 @@ func TestPredefinedPool(t *testing.T) {
}
func TestRemoveSubnet(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -519,7 +519,7 @@ func TestRemoveSubnet(t *testing.T) {
}
func TestGetSameAddress(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -549,7 +549,7 @@ func TestGetSameAddress(t *testing.T) {
}
func TestGetAddressSubPoolEqualPool(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -566,7 +566,7 @@ func TestGetAddressSubPoolEqualPool(t *testing.T) {
}
func TestRequestReleaseAddressFromSubPool(t *testing.T) {
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -697,8 +697,9 @@ func TestRequestReleaseAddressFromSubPool(t *testing.T) {
func TestSerializeRequestReleaseAddressFromSubPool(t *testing.T) {
opts := map[string]string{
ipamapi.AllocSerialPrefix: "true"}
a, err := getAllocator()
ipamapi.AllocSerialPrefix: "true",
}
a, err := getAllocator(false)
if err != nil {
t.Fatal(err)
}
@ -848,7 +849,7 @@ func TestRequestSyntaxCheck(t *testing.T) {
err error
)
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -950,7 +951,7 @@ func TestRelease(t *testing.T) {
subnet = "192.168.0.0/23"
)
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -1057,7 +1058,7 @@ func assertNRequests(t *testing.T, subnet string, numReq int, lastExpectedIP str
)
lastIP := net.ParseIP(lastExpectedIP)
a, err := getAllocator()
a, err := getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -1088,24 +1089,24 @@ func benchmarkRequest(b *testing.B, a *Allocator, subnet string) {
}
func benchMarkRequest(subnet string, b *testing.B) {
a, _ := getAllocator()
a, _ := getAllocator(true)
for n := 0; n < b.N; n++ {
benchmarkRequest(b, a, subnet)
}
}
func BenchmarkRequest_24(b *testing.B) {
a, _ := getAllocator()
a, _ := getAllocator(true)
benchmarkRequest(b, a, "10.0.0.0/24")
}
func BenchmarkRequest_16(b *testing.B) {
a, _ := getAllocator()
a, _ := getAllocator(true)
benchmarkRequest(b, a, "10.0.0.0/16")
}
func BenchmarkRequest_8(b *testing.B) {
a, _ := getAllocator()
a, _ := getAllocator(true)
benchmarkRequest(b, a, "10.0.0.0/8")
}
@ -1115,7 +1116,7 @@ func TestAllocateRandomDeallocate(t *testing.T) {
}
func testAllocateRandomDeallocate(t *testing.T, pool, subPool string, num int) {
ds, err := randomLocalStore()
ds, err := randomLocalStore(true)
if err != nil {
t.Fatal(err)
}
@ -1184,7 +1185,7 @@ func testAllocateRandomDeallocate(t *testing.T, pool, subPool string, num int) {
func TestRetrieveFromStore(t *testing.T) {
num := 200
ds, err := randomLocalStore()
ds, err := randomLocalStore(true)
if err != nil {
t.Fatal(err)
}
@ -1319,7 +1320,7 @@ func runParallelTests(t *testing.T, instance int) {
// The first instance creates the allocator, gives the start
// and finally checks the pools each instance was assigned
if instance == first {
allocator, err = getAllocator()
allocator, err = getAllocator(true)
if err != nil {
t.Fatal(err)
}
@ -1362,6 +1363,71 @@ func runParallelTests(t *testing.T, instance int) {
}
}
func TestRequestReleaseAddressDuplicate(t *testing.T) {
a, err := getAllocator(false)
if err != nil {
t.Fatal(err)
}
type IP struct {
ip *net.IPNet
ref int
}
ips := []IP{}
allocatedIPs := []*net.IPNet{}
a.addrSpaces["rosso"] = &addrSpace{
id: dsConfigKey + "/" + "rosso",
ds: a.addrSpaces[localAddressSpace].ds,
alloc: a.addrSpaces[localAddressSpace].alloc,
scope: a.addrSpaces[localAddressSpace].scope,
subnets: map[SubnetKey]*PoolData{},
}
var wg sync.WaitGroup
opts := map[string]string{
ipamapi.AllocSerialPrefix: "true",
}
var l sync.Mutex
poolID, _, _, err := a.RequestPool("rosso", "198.168.0.0/23", "", nil, false)
if err != nil {
t.Fatal(err)
}
for err == nil {
var c *net.IPNet
if c, _, err = a.RequestAddress(poolID, nil, opts); err == nil {
l.Lock()
ips = append(ips, IP{c, 1})
l.Unlock()
allocatedIPs = append(allocatedIPs, c)
if len(allocatedIPs) > 500 {
i := rand.Intn(len(allocatedIPs) - 1)
wg.Add(1)
go func(ip *net.IPNet) {
if err = a.ReleaseAddress(poolID, ip.IP); err != nil {
t.Fatal(err)
}
l.Lock()
ips = append(ips, IP{ip, -1})
l.Unlock()
wg.Done()
}(allocatedIPs[i])
allocatedIPs = append(allocatedIPs[:i], allocatedIPs[i+1:]...)
}
}
}
wg.Wait()
refMap := make(map[string]int)
for _, ip := range ips {
refMap[ip.ip.String()] = refMap[ip.ip.String()] + ip.ref
if refMap[ip.ip.String()] < 0 {
t.Fatalf("IP %s was previously released", ip.ip.String())
}
if refMap[ip.ip.String()] > 1 {
t.Fatalf("IP %s was previously allocated", ip.ip.String())
}
}
}
func TestParallelPredefinedRequest1(t *testing.T) {
runParallelTests(t, 0)
}