Feature: support fakeip

This commit is contained in:
Dreamacro
2019-05-03 00:05:14 +08:00
parent 762f227512
commit f352f4479e
9 changed files with 180 additions and 4 deletions

50
component/fakeip/pool.go Normal file
View File

@ -0,0 +1,50 @@
package fakeip
import (
"errors"
"net"
)
// Pool is a implementation about fake ip generator without storage
type Pool struct {
max uint32
min uint32
offset uint32
}
// Get return a new fake ip
func (p *Pool) Get() net.IP {
ip := uintToIP(p.min + p.offset)
p.offset = (p.offset + 1) % (p.max - p.min)
return ip
}
func ipToUint(ip net.IP) uint32 {
v := uint32(ip[0]) << 24
v += uint32(ip[1]) << 16
v += uint32(ip[2]) << 8
v += uint32(ip[3])
return v
}
func uintToIP(v uint32) net.IP {
return net.IPv4(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
// New return Pool instance
func New(ipnet *net.IPNet) (*Pool, error) {
min := ipToUint(ipnet.IP) + 1
ones, bits := ipnet.Mask.Size()
total := 1<<uint(bits-ones) - 2
if total <= 0 {
return nil, errors.New("ipnet don't have valid ip")
}
max := min + uint32(total)
return &Pool{
min: min,
max: max,
}, nil
}

View File

@ -0,0 +1,44 @@
package fakeip
import (
"net"
"testing"
)
func TestPool_Basic(t *testing.T) {
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
pool, _ := New(ipnet)
first := pool.Get()
last := pool.Get()
if !first.Equal(net.IP{192, 168, 0, 1}) {
t.Error("should get right first ip, instead of", first.String())
}
if !last.Equal(net.IP{192, 168, 0, 2}) {
t.Error("should get right last ip, instead of", first.String())
}
}
func TestPool_Cycle(t *testing.T) {
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
pool, _ := New(ipnet)
first := pool.Get()
pool.Get()
same := pool.Get()
if !first.Equal(same) {
t.Error("should return same ip", first.String())
}
}
func TestPool_Error(t *testing.T) {
_, ipnet, _ := net.ParseCIDR("192.168.0.1/31")
_, err := New(ipnet)
if err == nil {
t.Error("should return err")
}
}