carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package geoip
2
3import (
4 "archive/tar"
5 "bytes"
6 "compress/gzip"
7 "errors"
8 "io"
9 "testing"
10 "time"
11)
12
13func gz(t *testing.T, b []byte) []byte {
14 var buf bytes.Buffer
15 w := gzip.NewWriter(&buf)
16 w.Write(b)
17 w.Close()
18 return buf.Bytes()
19}
20
21func targz(t *testing.T, members map[string][]byte, order []string) []byte {
22 var buf bytes.Buffer
23 zw := gzip.NewWriter(&buf)
24 tw := tar.NewWriter(zw)
25 for _, name := range order {
26 body := members[name]
27 tw.WriteHeader(&tar.Header{Name: name, Mode: 0o644, Size: int64(len(body)), Typeflag: tar.TypeReg})
28 tw.Write(body)
29 }
30 tw.Close()
31 zw.Close()
32 return buf.Bytes()
33}
34
35func TestCappedReader(t *testing.T) {
36 if b, err := io.ReadAll(CappedReader(bytes.NewReader(make([]byte, 100)), 100)); err != nil || len(b) != 100 {
37 t.Fatalf("exactly max = %d %v", len(b), err)
38 }
39 if _, err := io.ReadAll(CappedReader(bytes.NewReader(make([]byte, 101)), 100)); !errors.Is(err, ErrTooLarge) {
40 t.Fatalf("max+1 = %v", err)
41 }
42}
43
44func TestGunzipStopsAtTheCap(t *testing.T) {
45 r, err := GunzipReader(bytes.NewReader(gz(t, make([]byte, 10<<20))), 1<<20)
46 if err != nil {
47 t.Fatal(err)
48 }
49 n, err := io.Copy(io.Discard, r)
50 if !errors.Is(err, ErrTooLarge) || n > 1<<20+1 {
51 t.Fatalf("bomb read %d bytes, err %v", n, err)
52 }
53}
54
55func TestTarGzMMDBCountsSkippedMembers(t *testing.T) {
56 arc := targz(t, map[string][]byte{"GeoLite2-City_20261006/README.txt": make([]byte, 2<<20), "GeoLite2-City_20261006/GeoLite2-City.mmdb": []byte("the database")},
57 []string{"GeoLite2-City_20261006/README.txt", "GeoLite2-City_20261006/GeoLite2-City.mmdb"})
58 r, err := TarGzMMDB(bytes.NewReader(arc), 4<<20)
59 if err != nil {
60 t.Fatal(err)
61 }
62 if b, _ := io.ReadAll(r); string(b) != "the database" {
63 t.Fatalf("member = %q", b)
64 }
65 if _, err := TarGzMMDB(bytes.NewReader(arc), 1<<20); !errors.Is(err, ErrTooLarge) {
66 t.Fatalf("padding past the cap = %v, want ErrTooLarge", err)
67 }
68 none := targz(t, map[string][]byte{"x.txt": []byte("x")}, []string{"x.txt"})
69 if _, err := TarGzMMDB(bytes.NewReader(none), 1<<20); err == nil {
70 t.Fatal("an archive with no .mmdb was accepted")
71 }
72}
73
74func TestFeedSpecsAndURLs(t *testing.T) {
75 s, ok := ParseFeed("dbip-city-lite")
76 if !ok || s.Type != "DBIP-City-Lite" || s.Provider != "dbip" {
77 t.Fatalf("spec = %+v %v", s, ok)
78 }
79 if got := DBIPURL("", s, time.Date(2026, 10, 6, 0, 0, 0, 0, time.UTC)); got != "https://download.db-ip.com/free/dbip-city-lite-2026-10.mmdb.gz" {
80 t.Fatalf("url = %s", got)
81 }
82 c, _ := ParseFeed("dbip-country-lite")
83 if got := DBIPURL("", c, time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)); got != "https://download.db-ip.com/free/dbip-country-lite-2026-01.mmdb.gz" {
84 t.Fatalf("country url = %s", got)
85 }
86 g, _ := ParseFeed("geolite2-city")
87 if got := MaxMindURL("", g, "tar.gz.sha256"); got != "https://download.maxmind.com/geoip/databases/GeoLite2-City/download?suffix=tar.gz.sha256" {
88 t.Fatalf("maxmind url = %s", got)
89 }
90 if _, ok := ParseFeed("ipinfo-lite"); ok {
91 t.Fatal("unknown feed accepted")
92 }
93}
94
95func TestFeedStatusFailing(t *testing.T) {
96 s := FeedStatus{V: 1, ConsecutiveFailures: 6}
97 if s.Failing() {
98 t.Fatal("6 is not failing")
99 }
100 s.ConsecutiveFailures = 7
101 if !s.Failing() {
102 t.Fatal("7 is failing")
103 }
104 if !(FeedStatus{ConsecutiveNotFound: 7}).Failing() {
105 t.Fatal("7 not-found is failing")
106 }
107 raw := []byte(`{"v":1,"feed":"dbip-city-lite","box":"b","consecutive_failures":2}`)
108 if got, err := ParseFeedStatus(raw); err != nil || got.Box != "b" {
109 t.Fatalf("parse = %+v %v", got, err)
110 }
111}
112
113// The paid MaxMind upgrade (Paul, 2026-10-07): same API, no D1 expiry.
114func TestPaidMaxMindFeeds(t *testing.T) {
115 for name, typ := range map[string]string{"geoip2-city": "GeoIP2-City", "geoip2-country": "GeoIP2-Country"} {
116 s, ok := ParseFeed(name)
117 if !ok || s.Type != typ || s.Provider != "maxmind" {
118 t.Fatalf("%s = %+v %v", name, s, ok)
119 }
120 if got := MaxMindURL("", s, "tar.gz"); got != "https://download.maxmind.com/geoip/databases/"+typ+"/download?suffix=tar.gz" {
121 t.Fatalf("%s url = %s", name, got)
122 }
123 if Expired(typ, time.Unix(0, 0), time.Now()) {
124 t.Fatalf("%s must never expire under D1", typ)
125 }
126 if _, ok := AttributionFor(typ); ok {
127 t.Fatalf("%s has no platform-known attribution", typ)
128 }
129 }
130}
131