// 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 ( "testing" ) func TestVersionFromHeader(t *testing.T) { // Structure20 -> always IPv4 (legacy format) h := &Header{Version: Structure20} v, err := VersionFromHeader(h) if err != nil { t.Fatalf("VersionFromHeader(Structure20) unexpected error: %s", err) } if v != IPv4 { t.Fatalf("VersionFromHeader(Structure20) = %s, want IPv4", v) } // Structure30 + IPv4VersionNo h = &Header{Version: Structure30, IPVersion: IPv4VersionNo} v, err = VersionFromHeader(h) if err != nil { t.Fatalf("VersionFromHeader(Structure30,IPv4) unexpected error: %s", err) } if v != IPv4 { t.Fatalf("VersionFromHeader(Structure30,IPv4) = %s, want IPv4", v) } // Structure30 + IPv6VersionNo h = &Header{Version: Structure30, IPVersion: IPv6VersionNo} v, err = VersionFromHeader(h) if err != nil { t.Fatalf("VersionFromHeader(Structure30,IPv6) unexpected error: %s", err) } if v != IPv6 { t.Fatalf("VersionFromHeader(Structure30,IPv6) = %s, want IPv6", v) } // invalid structure version h = &Header{Version: 999} _, err = VersionFromHeader(h) if err == nil { t.Fatal("VersionFromHeader(invalid version) should return error") } // Structure30 + invalid IP version h = &Header{Version: Structure30, IPVersion: 999} _, err = VersionFromHeader(h) if err == nil { t.Fatal("VersionFromHeader(Structure30,invalid IPVersion) should return error") } } func TestVersionFromName(t *testing.T) { tests := []struct { name string want *Version ok bool }{ {"v4", IPv4, true}, {"V4", IPv4, true}, {"ipv4", IPv4, true}, {"IPv4", IPv4, true}, {"v6", IPv6, true}, {"V6", IPv6, true}, {"ipv6", IPv6, true}, {"IPv6", IPv6, true}, {"ipv4", IPv4, true}, {"IPV6", IPv6, true}, {"", nil, false}, {"invalid", nil, false}, {"v7", nil, false}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { v, err := VersionFromName(tc.name) if tc.ok { if err != nil { t.Fatalf("VersionFromName(%q) unexpected error: %s", tc.name, err) } if v != tc.want { t.Fatalf("VersionFromName(%q) = %s, want %s", tc.name, v, tc.want) } } else { if err == nil { t.Fatalf("VersionFromName(%q) should return error", tc.name) } } }) } } func TestVersionFromIP(t *testing.T) { tests := []struct { ip string want *Version ok bool }{ {"1.2.3.4", IPv4, true}, {"0.0.0.0", IPv4, true}, {"255.255.255.255", IPv4, true}, {"::1", IPv6, true}, {"240e:3b7::1", IPv6, true}, {"", nil, false}, {"not-an-ip", nil, false}, } for _, tc := range tests { t.Run(tc.ip, func(t *testing.T) { v, err := VersionFromIP(tc.ip) if tc.ok { if err != nil { t.Fatalf("VersionFromIP(%q) unexpected error: %s", tc.ip, err) } if v != tc.want { t.Fatalf("VersionFromIP(%q) = %s, want %s", tc.ip, v, tc.want) } } else { if err == nil { t.Fatalf("VersionFromIP(%q) should return error", tc.ip) } } }) } } func TestIPv6Compare(t *testing.T) { // IPv6.IPCompare uses bytes.Compare directly, no byte-order swapping needed tests := []struct { name string ip1 []byte ip2 []byte want int }{ {"equal", []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 0}, {"less_b0", []byte{0x1f, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -1}, {"greater_b0", []byte{0x21, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 1}, {"zero_vs_max", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, -1}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got := IPv6.IPCompare(tc.ip1, tc.ip2) if got != tc.want { t.Fatalf("IPv6.IPCompare(%v, %v) = %d, want %d", tc.ip1, tc.ip2, got, tc.want) } }) } }