Files
2026-06-05 17:26:44 +08:00

109 lines
3.4 KiB
Go

package geo
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestResolverMapsIPAPIResponseToClientInfo(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/203.0.113.20/json/" {
t.Fatalf("path = %q, want /203.0.113.20/json/", r.URL.Path)
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{
"ip":"203.0.113.20",
"country_name":"China",
"region":"Beijing",
"city":"Beijing",
"asn":"AS64512",
"org":"Example Mobile"
}`))
}))
defer server.Close()
resolver := New(server.URL, time.Second)
info, err := resolver.Resolve(context.Background(), "203.0.113.20")
if err != nil {
t.Fatalf("Resolve returned error: %v", err)
}
if info.IP != "203.0.113.20" || info.Country != "China" || info.Region != "Beijing" || info.City != "Beijing" {
t.Fatalf("location info = %#v, want mapped country/region/city", info)
}
if info.ISP != "Example Mobile" || info.ASN != "AS64512" || info.Source != "ipapi.co" {
t.Fatalf("network info = %#v, want mapped org/asn/source", info)
}
}
func TestResolverMapsAlternateProviderNetworkFields(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{
"query":"203.0.113.21",
"country":"China",
"region_name":"Shanghai",
"city":"Shanghai",
"as":"AS64513",
"isp":"Example Unicom"
}`))
}))
defer server.Close()
resolver := New(server.URL, time.Second)
info, err := resolver.Resolve(context.Background(), "203.0.113.21")
if err != nil {
t.Fatalf("Resolve returned error: %v", err)
}
if info.IP != "203.0.113.21" || info.Country != "China" || info.Region != "Shanghai" {
t.Fatalf("location info = %#v, want alternate provider fields", info)
}
if info.ISP != "Example Unicom" || info.ASN != "AS64513" {
t.Fatalf("network info = %#v, want alternate isp/as fields", info)
}
}
func TestChainFallsBackWhenPrimaryResolverFails(t *testing.T) {
primary := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTooManyRequests)
_, _ = w.Write([]byte(`{"error":true,"reason":"rate limited"}`))
}))
defer primary.Close()
fallback := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{
"ip":"39.181.21.1",
"region":"Shanghai",
"city":"Shanghai",
"org":"AS56041 China Mobile communications corporation"
}`))
}))
defer fallback.Close()
resolve := Chain(New(primary.URL, time.Second), New(fallback.URL, time.Second))
info, err := resolve(context.Background(), "39.181.21.1")
if err != nil {
t.Fatalf("resolve returned error: %v", err)
}
if info.ISP != "AS56041 China Mobile communications corporation" || info.Region != "Shanghai" {
t.Fatalf("info = %#v, want fallback network metadata", info)
}
}
func TestResolverReturnsErrorForProviderFailure(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTooManyRequests)
_, _ = w.Write([]byte(`{"error":true,"reason":"rate limited"}`))
}))
defer server.Close()
resolver := New(server.URL, time.Second)
if _, err := resolver.Resolve(context.Background(), "203.0.113.20"); err == nil {
t.Fatal("Resolve succeeded, want error")
}
}