mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
1f3f37b2f8
- Update: portmapper, portallocator, ipallocator
- Remove stale godep dependencies
- Update pkg/iptables and others godep to latest
- Update bridge code and test after above changes
- Merge with latest changes in libnetwork
The code is updated up to docker/master commit SHA 86d66d6273
Signed-off-by: Alessandro Boch <aboch@docker.com>
690 lines
15 KiB
Go
690 lines
15 KiB
Go
package ipallocator
|
||
|
||
import (
|
||
"fmt"
|
||
"math/big"
|
||
"net"
|
||
"testing"
|
||
)
|
||
|
||
func TestConversion(t *testing.T) {
|
||
ip := net.ParseIP("127.0.0.1")
|
||
i := ipToBigInt(ip)
|
||
if i.Cmp(big.NewInt(0x7f000001)) != 0 {
|
||
t.Fatal("incorrect conversion")
|
||
}
|
||
conv := bigIntToIP(i)
|
||
if !ip.Equal(conv) {
|
||
t.Error(conv.String())
|
||
}
|
||
}
|
||
|
||
func TestConversionIPv6(t *testing.T) {
|
||
ip := net.ParseIP("2a00:1450::1")
|
||
ip2 := net.ParseIP("2a00:1450::2")
|
||
ip3 := net.ParseIP("2a00:1450::1:1")
|
||
i := ipToBigInt(ip)
|
||
val, success := big.NewInt(0).SetString("2a001450000000000000000000000001", 16)
|
||
if !success {
|
||
t.Fatal("Hex-String to BigInt conversion failed.")
|
||
}
|
||
if i.Cmp(val) != 0 {
|
||
t.Fatal("incorrent conversion")
|
||
}
|
||
|
||
conv := bigIntToIP(i)
|
||
conv2 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(1)))
|
||
conv3 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(0x10000)))
|
||
|
||
if !ip.Equal(conv) {
|
||
t.Error("2a00:1450::1 should be equal to " + conv.String())
|
||
}
|
||
if !ip2.Equal(conv2) {
|
||
t.Error("2a00:1450::2 should be equal to " + conv2.String())
|
||
}
|
||
if !ip3.Equal(conv3) {
|
||
t.Error("2a00:1450::1:1 should be equal to " + conv3.String())
|
||
}
|
||
}
|
||
|
||
func TestRequestNewIps(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
|
||
var ip net.IP
|
||
var err error
|
||
|
||
for i := 1; i < 10; i++ {
|
||
ip, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if expected := fmt.Sprintf("192.168.0.%d", i); ip.String() != expected {
|
||
t.Fatalf("Expected ip %s got %s", expected, ip.String())
|
||
}
|
||
}
|
||
value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if ip.String() != value {
|
||
t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
|
||
}
|
||
}
|
||
|
||
func TestRequestNewIpV6(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||
}
|
||
|
||
var ip net.IP
|
||
var err error
|
||
for i := 1; i < 10; i++ {
|
||
ip, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if expected := fmt.Sprintf("2a00:1450::%d", i); ip.String() != expected {
|
||
t.Fatalf("Expected ip %s got %s", expected, ip.String())
|
||
}
|
||
}
|
||
value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if ip.String() != value {
|
||
t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
|
||
}
|
||
}
|
||
|
||
func TestReleaseIp(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func TestReleaseIpV6(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||
}
|
||
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func TestGetReleasedIp(t *testing.T) {
|
||
a := New()
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
value := ip.String()
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
for i := 0; i < 253; i++ {
|
||
_, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
err = a.ReleaseIP(network, ip)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
ip, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if ip.String() != value {
|
||
t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
|
||
}
|
||
}
|
||
|
||
func TestGetReleasedIpV6(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
|
||
}
|
||
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
value := ip.String()
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
for i := 0; i < 253; i++ {
|
||
_, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
err = a.ReleaseIP(network, ip)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
ip, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if ip.String() != value {
|
||
t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
|
||
}
|
||
}
|
||
|
||
func TestRequestSpecificIp(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 224},
|
||
}
|
||
|
||
ip := net.ParseIP("192.168.0.5")
|
||
|
||
// Request a "good" IP.
|
||
if _, err := a.RequestIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
// Request the same IP again.
|
||
if _, err := a.RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||
t.Fatalf("Got the same IP twice: %#v", err)
|
||
}
|
||
|
||
// Request an out of range IP.
|
||
if _, err := a.RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
|
||
t.Fatalf("Got an out of range IP: %#v", err)
|
||
}
|
||
}
|
||
|
||
func TestRequestSpecificIpV6(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||
}
|
||
|
||
ip := net.ParseIP("2a00:1450::5")
|
||
|
||
// Request a "good" IP.
|
||
if _, err := a.RequestIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
// Request the same IP again.
|
||
if _, err := a.RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||
t.Fatalf("Got the same IP twice: %#v", err)
|
||
}
|
||
|
||
// Request an out of range IP.
|
||
if _, err := a.RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
|
||
t.Fatalf("Got an out of range IP: %#v", err)
|
||
}
|
||
}
|
||
|
||
func TestIPAllocator(t *testing.T) {
|
||
a := New()
|
||
|
||
expectedIPs := []net.IP{
|
||
0: net.IPv4(127, 0, 0, 1),
|
||
1: net.IPv4(127, 0, 0, 2),
|
||
2: net.IPv4(127, 0, 0, 3),
|
||
3: net.IPv4(127, 0, 0, 4),
|
||
4: net.IPv4(127, 0, 0, 5),
|
||
5: net.IPv4(127, 0, 0, 6),
|
||
}
|
||
|
||
gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
|
||
|
||
network := &net.IPNet{IP: gwIP, Mask: n.Mask}
|
||
// Pool after initialisation (f = free, u = used)
|
||
// 1(f) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
|
||
// ↑
|
||
|
||
// Check that we get 6 IPs, from 127.0.0.1–127.0.0.6, in that
|
||
// order.
|
||
for i := 0; i < 6; i++ {
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
assertIPEquals(t, expectedIPs[i], ip)
|
||
}
|
||
// Before loop begin
|
||
// 1(f) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
|
||
// ↑
|
||
|
||
// After i = 0
|
||
// 1(u) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
|
||
// ↑
|
||
|
||
// After i = 1
|
||
// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(f)
|
||
// ↑
|
||
|
||
// After i = 2
|
||
// 1(u) - 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
|
||
// ↑
|
||
|
||
// After i = 3
|
||
// 1(u) - 2(u) - 3(u) - 4(u) - 5(f) - 6(f)
|
||
// ↑
|
||
|
||
// After i = 4
|
||
// 1(u) - 2(u) - 3(u) - 4(u) - 5(u) - 6(f)
|
||
// ↑
|
||
|
||
// After i = 5
|
||
// 1(u) - 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
|
||
// ↑
|
||
|
||
// Check that there are no more IPs
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err == nil {
|
||
t.Fatalf("There shouldn't be any IP addresses at this point, got %s\n", ip)
|
||
}
|
||
|
||
// Release some IPs in non-sequential order
|
||
if err := a.ReleaseIP(network, expectedIPs[3]); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
// 1(u) - 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
|
||
// ↑
|
||
|
||
if err := a.ReleaseIP(network, expectedIPs[2]); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
// 1(u) - 2(u) - 3(f) - 4(f) - 5(u) - 6(u)
|
||
// ↑
|
||
|
||
if err := a.ReleaseIP(network, expectedIPs[4]); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(u)
|
||
// ↑
|
||
|
||
// Make sure that IPs are reused in sequential order, starting
|
||
// with the first released IP
|
||
newIPs := make([]net.IP, 3)
|
||
for i := 0; i < 3; i++ {
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
newIPs[i] = ip
|
||
}
|
||
assertIPEquals(t, expectedIPs[2], newIPs[0])
|
||
assertIPEquals(t, expectedIPs[3], newIPs[1])
|
||
assertIPEquals(t, expectedIPs[4], newIPs[2])
|
||
|
||
_, err = a.RequestIP(network, nil)
|
||
if err == nil {
|
||
t.Fatal("There shouldn't be any IP addresses at this point")
|
||
}
|
||
}
|
||
|
||
func TestAllocateFirstIP(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 0},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
|
||
firstIP := network.IP.To4().Mask(network.Mask)
|
||
first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
|
||
|
||
ip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
allocated := ipToBigInt(ip)
|
||
|
||
if allocated == first {
|
||
t.Fatalf("allocated ip should not equal first ip: %d == %d", first, allocated)
|
||
}
|
||
}
|
||
|
||
func TestAllocateAllIps(t *testing.T) {
|
||
a := New()
|
||
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
|
||
var (
|
||
current, first net.IP
|
||
err error
|
||
isFirst = true
|
||
)
|
||
|
||
for err == nil {
|
||
current, err = a.RequestIP(network, nil)
|
||
if isFirst {
|
||
first = current
|
||
isFirst = false
|
||
}
|
||
}
|
||
|
||
if err != ErrNoAvailableIPs {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if err := a.ReleaseIP(network, first); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
again, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
assertIPEquals(t, first, again)
|
||
|
||
// ensure that alloc.last == alloc.begin won't result in dead loop
|
||
if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
// Test by making alloc.last the only free ip and ensure we get it back
|
||
// #1. first of the range, (alloc.last == ipToInt(first) already)
|
||
if err := a.ReleaseIP(network, first); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
ret, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
assertIPEquals(t, first, ret)
|
||
|
||
// #2. last of the range, note that current is the last one
|
||
last := net.IPv4(192, 168, 0, 254)
|
||
setLastTo(t, a, network, last)
|
||
|
||
ret, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
assertIPEquals(t, last, ret)
|
||
|
||
// #3. middle of the range
|
||
mid := net.IPv4(192, 168, 0, 7)
|
||
setLastTo(t, a, network, mid)
|
||
|
||
ret, err = a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
assertIPEquals(t, mid, ret)
|
||
}
|
||
|
||
// make sure the pool is full when calling setLastTo.
|
||
// we don't cheat here
|
||
func setLastTo(t *testing.T, a *IPAllocator, network *net.IPNet, ip net.IP) {
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
ret, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
assertIPEquals(t, ip, ret)
|
||
|
||
if err := a.ReleaseIP(network, ip); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func TestAllocateDifferentSubnets(t *testing.T) {
|
||
a := New()
|
||
network1 := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
network2 := &net.IPNet{
|
||
IP: []byte{127, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
network3 := &net.IPNet{
|
||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||
}
|
||
network4 := &net.IPNet{
|
||
IP: []byte{0x2a, 0x00, 0x16, 0x32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||
}
|
||
expectedIPs := []net.IP{
|
||
0: net.IPv4(192, 168, 0, 1),
|
||
1: net.IPv4(192, 168, 0, 2),
|
||
2: net.IPv4(127, 0, 0, 1),
|
||
3: net.IPv4(127, 0, 0, 2),
|
||
4: net.ParseIP("2a00:1450::1"),
|
||
5: net.ParseIP("2a00:1450::2"),
|
||
6: net.ParseIP("2a00:1450::3"),
|
||
7: net.ParseIP("2a00:1632::1"),
|
||
8: net.ParseIP("2a00:1632::2"),
|
||
}
|
||
|
||
ip11, err := a.RequestIP(network1, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip12, err := a.RequestIP(network1, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip21, err := a.RequestIP(network2, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip22, err := a.RequestIP(network2, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip31, err := a.RequestIP(network3, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip32, err := a.RequestIP(network3, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip33, err := a.RequestIP(network3, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip41, err := a.RequestIP(network4, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ip42, err := a.RequestIP(network4, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
assertIPEquals(t, expectedIPs[0], ip11)
|
||
assertIPEquals(t, expectedIPs[1], ip12)
|
||
assertIPEquals(t, expectedIPs[2], ip21)
|
||
assertIPEquals(t, expectedIPs[3], ip22)
|
||
assertIPEquals(t, expectedIPs[4], ip31)
|
||
assertIPEquals(t, expectedIPs[5], ip32)
|
||
assertIPEquals(t, expectedIPs[6], ip33)
|
||
assertIPEquals(t, expectedIPs[7], ip41)
|
||
assertIPEquals(t, expectedIPs[8], ip42)
|
||
}
|
||
|
||
func TestRegisterBadTwice(t *testing.T) {
|
||
a := New()
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 1, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
subnet := &net.IPNet{
|
||
IP: []byte{192, 168, 1, 8},
|
||
Mask: []byte{255, 255, 255, 248},
|
||
}
|
||
|
||
if err := a.RegisterSubnet(network, subnet); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
subnet = &net.IPNet{
|
||
IP: []byte{192, 168, 1, 16},
|
||
Mask: []byte{255, 255, 255, 248},
|
||
}
|
||
if err := a.RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
|
||
t.Fatalf("Expecteded ErrNetworkAlreadyRegistered error, got %v", err)
|
||
}
|
||
}
|
||
|
||
func TestRegisterBadRange(t *testing.T) {
|
||
a := New()
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 1, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
subnet := &net.IPNet{
|
||
IP: []byte{192, 168, 1, 1},
|
||
Mask: []byte{255, 255, 0, 0},
|
||
}
|
||
if err := a.RegisterSubnet(network, subnet); err != ErrBadSubnet {
|
||
t.Fatalf("Expected ErrBadSubnet error, got %v", err)
|
||
}
|
||
}
|
||
|
||
func TestAllocateFromRange(t *testing.T) {
|
||
a := New()
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
// 192.168.1.9 - 192.168.1.14
|
||
subnet := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 8},
|
||
Mask: []byte{255, 255, 255, 248},
|
||
}
|
||
|
||
if err := a.RegisterSubnet(network, subnet); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
expectedIPs := []net.IP{
|
||
0: net.IPv4(192, 168, 0, 9),
|
||
1: net.IPv4(192, 168, 0, 10),
|
||
2: net.IPv4(192, 168, 0, 11),
|
||
3: net.IPv4(192, 168, 0, 12),
|
||
4: net.IPv4(192, 168, 0, 13),
|
||
5: net.IPv4(192, 168, 0, 14),
|
||
}
|
||
for _, ip := range expectedIPs {
|
||
rip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
assertIPEquals(t, ip, rip)
|
||
}
|
||
|
||
if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||
t.Fatalf("Expected ErrNoAvailableIPs error, got %v", err)
|
||
}
|
||
for _, ip := range expectedIPs {
|
||
a.ReleaseIP(network, ip)
|
||
rip, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
assertIPEquals(t, ip, rip)
|
||
}
|
||
}
|
||
|
||
func assertIPEquals(t *testing.T, ip1, ip2 net.IP) {
|
||
if !ip1.Equal(ip2) {
|
||
t.Fatalf("Expected IP %s, got %s", ip1, ip2)
|
||
}
|
||
}
|
||
|
||
func BenchmarkRequestIP(b *testing.B) {
|
||
network := &net.IPNet{
|
||
IP: []byte{192, 168, 0, 1},
|
||
Mask: []byte{255, 255, 255, 0},
|
||
}
|
||
b.ResetTimer()
|
||
|
||
for i := 0; i < b.N; i++ {
|
||
a := New()
|
||
|
||
for j := 0; j < 253; j++ {
|
||
_, err := a.RequestIP(network, nil)
|
||
if err != nil {
|
||
b.Fatal(err)
|
||
}
|
||
}
|
||
}
|
||
}
|