325 lines
8.4 KiB
Go
325 lines
8.4 KiB
Go
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
// Use of this source code is governed by a Apache2.0-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package xdb
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseIP(t *testing.T) {
|
|
var ips = []string{"29.34.191.255", "2c0f:fff0::", "2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"}
|
|
for _, ip := range ips {
|
|
bytes, err := ParseIP(ip)
|
|
if err != nil {
|
|
t.Errorf("check ip `%s`: %s\n", IP2String(bytes), err)
|
|
}
|
|
|
|
nip := IP2String(bytes)
|
|
fmt.Printf("checkip: (%s / %s), isEqual: %v\n", ip, nip, ip == nip)
|
|
}
|
|
}
|
|
|
|
func TestIPCompare(t *testing.T) {
|
|
var ipPairs = [][]string{
|
|
{"1.2.3.4", "1.2.3.5"},
|
|
{"58.250.36.41", "58.250.30.41"},
|
|
{"2c10::", "2e00::"},
|
|
{"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"},
|
|
{"fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "fe00::"},
|
|
}
|
|
|
|
for _, pairs := range ipPairs {
|
|
fmt.Printf("IPCompare(%s, %s): %d\n", pairs[0], pairs[1], IPCompare([]byte(pairs[0]), []byte(pairs[1])))
|
|
}
|
|
}
|
|
|
|
func TestIPAddOne(t *testing.T) {
|
|
var ipPairs = [][]string{
|
|
{"1.2.3.4", "1.2.3.5"},
|
|
{"2.3.4.5", "2.3.4.6"},
|
|
{"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "fe00::"},
|
|
{"2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "3000::"},
|
|
{"2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "3000::1"},
|
|
}
|
|
|
|
for _, pairs := range ipPairs {
|
|
sip, err := ParseIP(pairs[0])
|
|
if err != nil {
|
|
t.Errorf("parse ip `%s`: %s\n", pairs[0], err)
|
|
}
|
|
|
|
eip, err := ParseIP(pairs[1])
|
|
if err != nil {
|
|
t.Errorf("parse ip `%s`: %s\n", pairs[1], err)
|
|
}
|
|
|
|
fmt.Printf("IPAddOne(%s) = %s ? %d\n",
|
|
pairs[0], pairs[1], IPCompare(IPAddOne(sip), eip))
|
|
}
|
|
}
|
|
|
|
func TestIPAddOne2(t *testing.T) {
|
|
var ip = []byte{0, 1, 2, 3}
|
|
nip := IPAddOne(ip)
|
|
fmt.Printf("nip: %+v, ip:%+v", ip, nip)
|
|
}
|
|
|
|
func TestIPSubOne(t *testing.T) {
|
|
var ipPairs = [][]string{
|
|
{"1.2.3.4", "1.2.3.5"},
|
|
{"2.3.4.5", "2.3.4.6"},
|
|
{"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "fe00::"},
|
|
{"2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "3000::"},
|
|
{"2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "3000::1"},
|
|
}
|
|
|
|
for _, pairs := range ipPairs {
|
|
sip, err := ParseIP(pairs[0])
|
|
if err != nil {
|
|
t.Errorf("parse ip `%s`: %s\n", pairs[0], err)
|
|
}
|
|
|
|
eip, err := ParseIP(pairs[1])
|
|
if err != nil {
|
|
t.Errorf("parse ip `%s`: %s\n", pairs[1], err)
|
|
}
|
|
|
|
fmt.Printf("IPSubOne(%s) = %s ? %d\n",
|
|
pairs[1], pairs[0], IPCompare(IPSubOne(eip), sip))
|
|
}
|
|
}
|
|
|
|
func TestIPSubOne2(t *testing.T) {
|
|
var ip = []byte{0, 1, 2, 3}
|
|
nip := IPSubOne(ip)
|
|
fmt.Printf("nip: %+v, ip:%+v", ip, nip)
|
|
}
|
|
|
|
func TestIPSub(t *testing.T) {
|
|
var strToSub = "1.2.3.4"
|
|
bytesToSub, err := ParseIP(strToSub)
|
|
if err != nil {
|
|
t.Fatalf("failed to parse ip %s", strToSub)
|
|
}
|
|
var intToSub = int(binary.BigEndian.Uint32(bytesToSub))
|
|
t.Logf("to sub ip: %d -> %s", intToSub, strToSub)
|
|
|
|
counter := 0
|
|
buf := make([]byte, 4)
|
|
for i := 0; i < 0x2FFFFFFF; i++ {
|
|
binary.BigEndian.PutUint32(buf, uint32(i))
|
|
subVal, err := IPSub(buf, bytesToSub)
|
|
if err != nil {
|
|
t.Fatalf("failed to IPSub(%s,%s): %s", IP2String(buf), strToSub, err)
|
|
}
|
|
|
|
// do it as two integers
|
|
byteSub := int(binary.BigEndian.Uint32(subVal))
|
|
intSub := i + intToSub
|
|
if byteSub != intSub {
|
|
t.Fatal("byte and int sub value are not the same")
|
|
}
|
|
|
|
counter++
|
|
}
|
|
|
|
t.Logf("test done with %d ips", counter)
|
|
}
|
|
|
|
func TestIPHalf(t *testing.T) {
|
|
var buf = make([]byte, 4)
|
|
for i := 0; i < 0xFFFFFFFF; i++ {
|
|
binary.BigEndian.PutUint32(buf, uint32(i))
|
|
half := IPHalf(buf)
|
|
|
|
// do it as two integers
|
|
byteMiddle := binary.BigEndian.Uint32(half)
|
|
intMidle := i >> 1
|
|
if byteMiddle != uint32(intMidle) {
|
|
t.Fatal("byte middle and int middle are not the same")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSubOverflow(t *testing.T) {
|
|
var ip1Str = "255.255.255.250"
|
|
ip1Bytes, err := ParseIP(ip1Str)
|
|
if err != nil {
|
|
t.Fatalf("failed to ParseIP(%s): %s", ip1Str, err)
|
|
}
|
|
|
|
var buff = make([]byte, 4)
|
|
for i := 0; i < 10; i++ {
|
|
binary.BigEndian.PutUint32(buff, uint32(i))
|
|
ipSub, err := IPSub(ip1Bytes, buff)
|
|
if err != nil {
|
|
t.Fatalf("failed to IPSub(%s, %s): %s", ip1Str, IP2String(buff), err)
|
|
}
|
|
|
|
t.Logf("IPSub(%s, %s) = %+v", ip1Str, IP2String(buff), ipSub)
|
|
}
|
|
}
|
|
|
|
func TestIPMiddle(t *testing.T) {
|
|
var sIPStr = "0.0.0.0"
|
|
sBytes, err := ParseIP(sIPStr)
|
|
if err != nil {
|
|
t.Fatalf("failed to parse ip %s", sIPStr)
|
|
}
|
|
var sInt = int(binary.BigEndian.Uint32(sBytes))
|
|
t.Logf("start ip: %d -> %s", sInt, sIPStr)
|
|
|
|
counter := 0
|
|
buf := make([]byte, 4)
|
|
for i := 0; i < 0x0FFFFFFF; i++ {
|
|
binary.BigEndian.PutUint32(buf, uint32(i))
|
|
midVal, err := IPMiddle(sBytes, buf)
|
|
if err != nil {
|
|
t.Fatalf("failed to IPMiddle(%s,%s): %s", sIPStr, IP2String(buf), err)
|
|
}
|
|
|
|
// do it as two integers
|
|
byteMid := int(binary.BigEndian.Uint32(midVal))
|
|
intMid := (sInt + i) >> 1
|
|
if byteMid != intMid {
|
|
t.Fatal("byte and int middle value are not the same")
|
|
}
|
|
|
|
counter++
|
|
}
|
|
|
|
t.Logf("test done with %d ips", counter)
|
|
}
|
|
|
|
func TestSplitSegmentV4(t *testing.T) {
|
|
// var str = "1.1.0.0|1.3.3.24|中国|广东|深圳|电信"
|
|
// var str = "0.0.0.0|1.255.225.254|0|0|0|内网IP|内网IP"
|
|
// var str = "29.0.0.0|29.34.191.255|美国|0|0|0|0"
|
|
var str = "28.201.224.0|29.34.191.255|美国|0|0|0|0"
|
|
seg, err := SegmentFrom(str, NewRegion)
|
|
if err != nil {
|
|
t.Fatalf("failed to parser segment '%s': %s", str, err)
|
|
}
|
|
|
|
fmt.Printf("idx: src, seg: %s\n", seg.String())
|
|
var segList = seg.Split()
|
|
err = CheckSegments(segList)
|
|
if err != nil {
|
|
t.Fatalf("check segments: %s", err.Error())
|
|
}
|
|
|
|
for i, s := range segList {
|
|
fmt.Printf("idx: %3d, seg: %s\n", i, s.String())
|
|
}
|
|
}
|
|
|
|
func TestRegionFiltering(t *testing.T) {
|
|
var line = "2001:1203:31:8000::|2001:1203:31:bfff:ffff:ffff:ffff:ffff||墨西哥|瓜纳华托州||||专线用户|"
|
|
seg, err := SegmentFrom(line, NewRegion)
|
|
if err != nil {
|
|
t.Fatalf("failed to parse segment '%s': %s", line, err)
|
|
}
|
|
|
|
fReg, err := seg.Region.Filtering([]int{1, 2, 4, 6})
|
|
if err != nil {
|
|
t.Fatalf("failed to filter region '%s': %s", seg.Region, err)
|
|
}
|
|
|
|
fmt.Printf("region: %s, filtered: %s\n", seg.Region, fReg)
|
|
}
|
|
|
|
func TestSplitSegmentV6(t *testing.T) {
|
|
var str = "fec0::|ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff||瑞士|弗里堡州||||专线用户|IANA"
|
|
seg, err := SegmentFrom(str, NewRegion)
|
|
if err != nil {
|
|
t.Fatalf("failed to parser segment '%s': %s", str, err)
|
|
}
|
|
|
|
fmt.Printf("idx: src, seg: %s\n", seg.String())
|
|
var segList = seg.Split()
|
|
err = CheckSegments(segList)
|
|
if err != nil {
|
|
t.Fatalf("check segments: %s", err.Error())
|
|
}
|
|
|
|
for i, s := range segList {
|
|
fmt.Printf("idx: %3d, seg: %s\n", i, s.String())
|
|
}
|
|
}
|
|
|
|
func TestIterateSegments(t *testing.T) {
|
|
handle, err := os.OpenFile("../../../data/sample/segments.tests.mixed", os.O_RDONLY, 0600)
|
|
if err != nil {
|
|
t.Fatalf("failed to open tests file: %s", err)
|
|
}
|
|
|
|
_, _, _ = IterateSegments(handle, true, func(l string) {
|
|
// fmt.Printf("load segment: `%s`\n", l)
|
|
}, nil, NewRegion, func(seg *Segment) error {
|
|
fmt.Printf("get segment: `%s`\n", seg)
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func TestStringTokenizer(t *testing.T) {
|
|
var strList = []string{
|
|
"24.231.126.0/24|14537 2914 29866|IGP",
|
|
"24.231.126.0|24.231.126.255|14537 2914 29866|IGP",
|
|
}
|
|
|
|
var counter = 0
|
|
for _, str := range strList {
|
|
tokens := StringTokenizer(str, "|", func(s string, start int) bool {
|
|
// fmt.Printf("%s[idx=%d, |]=%s\n", str, start, s)
|
|
if counter == 0 {
|
|
if strings.Index(s, "/") > 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
counter++
|
|
return counter < 2
|
|
})
|
|
fmt.Printf("%d tokens: %s\n", len(tokens), strings.Join(tokens, ", "))
|
|
}
|
|
}
|
|
|
|
func TestCIDR2Range(t *testing.T) {
|
|
var strList = [][3]string{
|
|
{"43.247.92.0/22", "43.247.92.0", "43.247.95.255"},
|
|
{"64.252.86.39/29", "64.252.86.32", "64.252.86.39"},
|
|
{"103.37.44.0/22", "103.37.44.0", "103.37.47.255"},
|
|
{"111.223.12.0/22", "111.223.12.0", "111.223.15.255"},
|
|
{"43.248.80.0/20", "43.248.80.0", "43.248.95.255"},
|
|
{"192.168.100.0/22", "192.168.100.0", "192.168.103.255"},
|
|
{"2403:3380::/32", "2403:3380::", "2403:3380:ffff:ffff:ffff:ffff:ffff:ffff"},
|
|
{"2001:db8:85a3::/64", "2001:db8:85a3::", "2001:db8:85a3:0:ffff:ffff:ffff:ffff"},
|
|
{"2001:db8:abcd::/48", "2001:db8:abcd::", "2001:db8:abcd:ffff:ffff:ffff:ffff:ffff"},
|
|
}
|
|
|
|
for _, item := range strList {
|
|
sip, eip, err := CIDR2Range(item[0])
|
|
if err != nil {
|
|
t.Fatalf("CIDR2Range: %s", err)
|
|
}
|
|
|
|
sStr := IP2String(sip)
|
|
eStr := IP2String(eip)
|
|
if sStr != item[1] {
|
|
t.Fatalf("start ip %s != %s", sStr, item[1])
|
|
}
|
|
|
|
if eStr != item[2] {
|
|
t.Fatalf("end ip %s != %s", eStr, item[2])
|
|
}
|
|
|
|
fmt.Printf("cidr=%s: {sip=%s, eip=%s}\n", item[0], sStr, eStr)
|
|
}
|
|
}
|