Browse code

Implement pos for set and add unit tests

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/01/23 12:34:47
Showing 3 changed files
... ...
@@ -8,7 +8,7 @@ import (
8 8
 	"sync"
9 9
 )
10 10
 
11
-type networkSet map[iPNet]iPSet
11
+type networkSet map[iPNet]*iPSet
12 12
 
13 13
 type iPNet struct {
14 14
 	IP   string
... ...
@@ -44,8 +44,8 @@ func RegisterNetwork(network *net.IPNet) error {
44 44
 	}
45 45
 	n := newIPNet(network)
46 46
 
47
-	allocatedIPs[n] = iPSet{}
48
-	availableIPS[n] = iPSet{}
47
+	allocatedIPs[n] = &iPSet{}
48
+	availableIPS[n] = &iPSet{}
49 49
 
50 50
 	return nil
51 51
 }
... ...
@@ -72,13 +72,18 @@ func ReleaseIP(network *net.IPNet, ip *net.IP) error {
72 72
 	lock.Lock()
73 73
 	defer lock.Unlock()
74 74
 
75
-	n := newIPNet(network)
76
-	existing := allocatedIPs[n]
75
+	var (
76
+		first, _  = networkRange(network)
77
+		base      = ipToInt(&first)
78
+		n         = newIPNet(network)
79
+		existing  = allocatedIPs[n]
80
+		available = availableIPS[n]
81
+		i         = ipToInt(ip)
82
+		pos       = i - base
83
+	)
77 84
 
78
-	i := ipToInt(ip)
79
-	existing.Remove(int(i))
80
-	available := availableIPS[n]
81
-	available.Push(int(i))
85
+	existing.Remove(int(pos))
86
+	available.Push(int(pos))
82 87
 
83 88
 	return nil
84 89
 }
... ...
@@ -86,29 +91,43 @@ func ReleaseIP(network *net.IPNet, ip *net.IP) error {
86 86
 func getNextIp(network *net.IPNet) (*net.IP, error) {
87 87
 	var (
88 88
 		n         = newIPNet(network)
89
+		ownIP     = ipToInt(&network.IP)
89 90
 		available = availableIPS[n]
90
-		next      = available.Pop()
91 91
 		allocated = allocatedIPs[n]
92
-		ownIP     = int(ipToInt(&network.IP))
92
+
93
+		first, _ = networkRange(network)
94
+		base     = ipToInt(&first)
95
+
96
+		pos = int32(available.Pop())
93 97
 	)
94 98
 
95
-	if next != 0 {
96
-		ip := intToIP(int32(next))
97
-		allocated.Push(int(next))
99
+	// We pop and push the position not the ip
100
+	if pos != 0 {
101
+		ip := intToIP(int32(base + pos))
102
+		allocated.Push(int(pos))
103
+
98 104
 		return ip, nil
99 105
 	}
100
-	size := int(networkSize(network.Mask))
101
-	next = allocated.PullBack() + 1
102 106
 
103
-	// size -1 for the broadcast address, -1 for the gateway address
104
-	for i := 0; i < size-2; i++ {
107
+	var (
108
+		size = int(networkSize(network.Mask))
109
+		max  = int32(size - 2) // size -1 for the broadcast address, -1 for the gateway address
110
+	)
111
+
112
+	if pos = int32(allocated.PullBack()); pos == 0 {
113
+		pos = 1
114
+	}
115
+
116
+	for i := int32(0); i < max; i++ {
117
+		next := int32(base + pos)
118
+		pos = pos%max + 1
119
+
105 120
 		if next == ownIP {
106
-			next++
107 121
 			continue
108 122
 		}
109 123
 
110
-		ip := intToIP(int32(next))
111
-		allocated.Push(next)
124
+		ip := intToIP(next)
125
+		allocated.Push(int(pos))
112 126
 
113 127
 		return ip, nil
114 128
 	}
... ...
@@ -117,6 +136,7 @@ func getNextIp(network *net.IPNet) (*net.IP, error) {
117 117
 
118 118
 func registerIP(network *net.IPNet, ip *net.IP) error {
119 119
 	existing := allocatedIPs[newIPNet(network)]
120
+	// checking position not ip
120 121
 	if existing.Exists(int(ipToInt(ip))) {
121 122
 		return ErrIPAlreadyAllocated
122 123
 	}
... ...
@@ -1,11 +1,18 @@
1 1
 package ipallocator
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"net"
5 6
 	"testing"
6 7
 )
7 8
 
9
+func reset() {
10
+	allocatedIPs = networkSet{}
11
+	availableIPS = networkSet{}
12
+}
13
+
8 14
 func TestRegisterNetwork(t *testing.T) {
15
+	defer reset()
9 16
 	network := &net.IPNet{
10 17
 		IP:   []byte{192, 168, 0, 1},
11 18
 		Mask: []byte{255, 255, 255, 0},
... ...
@@ -24,3 +31,133 @@ func TestRegisterNetwork(t *testing.T) {
24 24
 		t.Fatal("IPNet should exist in available IPs")
25 25
 	}
26 26
 }
27
+
28
+func TestRegisterTwoNetworks(t *testing.T) {
29
+	defer reset()
30
+	network := &net.IPNet{
31
+		IP:   []byte{192, 168, 0, 1},
32
+		Mask: []byte{255, 255, 255, 0},
33
+	}
34
+
35
+	if err := RegisterNetwork(network); err != nil {
36
+		t.Fatal(err)
37
+	}
38
+
39
+	network2 := &net.IPNet{
40
+		IP:   []byte{10, 1, 42, 1},
41
+		Mask: []byte{255, 255, 255, 0},
42
+	}
43
+
44
+	if err := RegisterNetwork(network2); err != nil {
45
+		t.Fatal(err)
46
+	}
47
+}
48
+
49
+func TestRegisterNetworkThatExists(t *testing.T) {
50
+	defer reset()
51
+	network := &net.IPNet{
52
+		IP:   []byte{192, 168, 0, 1},
53
+		Mask: []byte{255, 255, 255, 0},
54
+	}
55
+
56
+	if err := RegisterNetwork(network); err != nil {
57
+		t.Fatal(err)
58
+	}
59
+
60
+	if err := RegisterNetwork(network); err != ErrNetworkAlreadyRegisterd {
61
+		t.Fatalf("Expected error of %s got %s", ErrNetworkAlreadyRegisterd, err)
62
+	}
63
+}
64
+
65
+func TestRequestNewIps(t *testing.T) {
66
+	defer reset()
67
+	network := &net.IPNet{
68
+		IP:   []byte{192, 168, 0, 1},
69
+		Mask: []byte{255, 255, 255, 0},
70
+	}
71
+
72
+	if err := RegisterNetwork(network); err != nil {
73
+		t.Fatal(err)
74
+	}
75
+
76
+	for i := 2; i < 10; i++ {
77
+		ip, err := RequestIP(network, nil)
78
+		if err != nil {
79
+			t.Fatal(err)
80
+		}
81
+
82
+		if expected := fmt.Sprintf("192.168.0.%d", i); ip.String() != expected {
83
+			t.Fatalf("Expected ip %s got %s", expected, ip.String())
84
+		}
85
+	}
86
+}
87
+
88
+func TestReleaseIp(t *testing.T) {
89
+	defer reset()
90
+	network := &net.IPNet{
91
+		IP:   []byte{192, 168, 0, 1},
92
+		Mask: []byte{255, 255, 255, 0},
93
+	}
94
+
95
+	if err := RegisterNetwork(network); err != nil {
96
+		t.Fatal(err)
97
+	}
98
+
99
+	ip, err := RequestIP(network, nil)
100
+	if err != nil {
101
+		t.Fatal(err)
102
+	}
103
+
104
+	if err := ReleaseIP(network, ip); err != nil {
105
+		t.Fatal(err)
106
+	}
107
+}
108
+
109
+func TestGetReleasedIp(t *testing.T) {
110
+	defer reset()
111
+	network := &net.IPNet{
112
+		IP:   []byte{192, 168, 0, 1},
113
+		Mask: []byte{255, 255, 255, 0},
114
+	}
115
+
116
+	if err := RegisterNetwork(network); err != nil {
117
+		t.Fatal(err)
118
+	}
119
+
120
+	ip, err := RequestIP(network, nil)
121
+	if err != nil {
122
+		t.Fatal(err)
123
+	}
124
+
125
+	value := ip.String()
126
+	if err := ReleaseIP(network, ip); err != nil {
127
+		t.Fatal(err)
128
+	}
129
+
130
+	ip, err = RequestIP(network, nil)
131
+	if err != nil {
132
+		t.Fatal(err)
133
+	}
134
+
135
+	if ip.String() != value {
136
+		t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
137
+	}
138
+}
139
+
140
+func TestRequesetSpecificIp(t *testing.T) {
141
+	defer reset()
142
+	network := &net.IPNet{
143
+		IP:   []byte{192, 168, 0, 1},
144
+		Mask: []byte{255, 255, 255, 0},
145
+	}
146
+
147
+	if err := RegisterNetwork(network); err != nil {
148
+		t.Fatal(err)
149
+	}
150
+
151
+	ip := net.ParseIP("192.168.1.5")
152
+
153
+	if _, err := RequestIP(network, &ip); err != nil {
154
+		t.Fatal(err)
155
+	}
156
+}
... ...
@@ -82,8 +82,3 @@ func (s *iPSet) Remove(elem int) {
82 82
 		}
83 83
 	}
84 84
 }
85
-
86
-// Len returns the length of the list.
87
-func (s *iPSet) Len() int {
88
-	return len(s.set)
89
-}