Skip to content

Commit 6b879e9

Browse files
authored
Merge pull request #78 from maxmind/mm-david/empty-ok
Require geofeeds to have content
2 parents a2760c6 + a699957 commit 6b879e9

6 files changed

Lines changed: 65 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
## CHANGELOG
22

3+
## 3.1.0 (2024-11-05)
4+
5+
* Empty geofeeds will now be considered invalid, unless the (new) EmptyOK option
6+
is passed to ProcessGeofeed (e.g. via the new `empty-ok` flag).
7+
38
## 3.0.0 (2024-08-14)
49

510
* Update interface of ProcessGeofeed in the verifier package, adding a new

main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type config struct {
3030
db string
3131
isp string
3232
laxMode bool
33+
emptyOK bool
3334
}
3435

3536
func main() {
@@ -50,7 +51,7 @@ func run() error {
5051
conf.gf,
5152
conf.db,
5253
conf.isp,
53-
verify.Options{LaxMode: conf.laxMode},
54+
verify.Options{LaxMode: conf.laxMode, EmptyOK: conf.emptyOK},
5455
)
5556
if err != nil {
5657
if errors.Is(err, verify.ErrInvalidGeofeed) {
@@ -108,6 +109,11 @@ func parseFlags(program string, args []string) (c *config, output string, err er
108109
"lax",
109110
false,
110111
"Enable lax mode: geofeed's region code may be provided without country code prefix")
112+
flags.BoolVar(
113+
&conf.emptyOK,
114+
"empty-ok",
115+
false,
116+
"Allow empty geofeeds to be considered valid")
111117

112118
err = flags.Parse(args)
113119
if err != nil {

verify/errors.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ package verify
22

33
import "errors"
44

5-
// ErrInvalidGeofeed represents error that is returned in case of incomplete compliance
6-
// with RFC 8805 standards and the mode in which the program is run.
7-
var ErrInvalidGeofeed = errors.New("geofeed does not comply with the RFC 8805 standards")
5+
var (
6+
// ErrInvalidGeofeed represents error that is returned in case of incomplete
7+
// compliance with RFC 8805 standards and the mode in which the program is
8+
// run.
9+
ErrInvalidGeofeed = errors.New("geofeed does not comply with the RFC 8805 standards")
10+
// ErrEmptyGeofeed indicates a Geofeed with no records.
11+
ErrEmptyGeofeed = errors.New("geofeed is empty")
12+
)
813

914
// RowInvalidity represents type of row invalidity.
1015
type RowInvalidity int

verify/test_data/empty.csv

Whitespace-only changes.

verify/verify.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ type Options struct {
4747
// from appearing in error messages. This reduces information leakage in
4848
// contexts where the error messages might be shared.
4949
HideFilePathsInErrorMessages bool
50+
// EmptyOK, if set to true, will consider a geofeed with no records to be
51+
// valid. The default behavior (false) requires a geofeed to not be empty.
52+
EmptyOK bool
5053
}
5154

5255
// ProcessGeofeed attempts to validate a given geofeedFilename.
@@ -157,6 +160,10 @@ func ProcessGeofeed(
157160
return c, diffLines, asnCounts, fmt.Errorf("error while reading %s: %w", geofeedFilename, err)
158161
}
159162

163+
if c.Total == 0 && !opts.EmptyOK {
164+
return c, diffLines, asnCounts, ErrEmptyGeofeed
165+
}
166+
160167
if c.Invalid > 0 || len(c.SampleInvalidRows) > 0 {
161168
return c, diffLines, asnCounts, ErrInvalidGeofeed
162169
}

verify/verify_test.go

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type processGeofeedTest struct {
1414
c CheckResult
1515
em error
1616
laxMode bool
17+
emptyOK bool
1718
}
1819

1920
func TestProcessGeofeed_Valid(t *testing.T) {
@@ -74,14 +75,31 @@ func TestProcessGeofeed_Valid(t *testing.T) {
7475
},
7576
laxMode: false,
7677
},
78+
{
79+
gf: "test_data/empty.csv",
80+
db: "test_data/GeoIP2-City-Test.mmdb",
81+
c: CheckResult{
82+
Total: 0,
83+
SampleInvalidRows: map[RowInvalidity]string{},
84+
},
85+
emptyOK: true,
86+
},
7787
}
7888

7989
// Testing the full content of the difference explanation strings is likely to be
8090
// tedious and brittle, so we will just check for some substrings.
8191
for _, test := range goodTests {
8292
t.Run(
8393
test.gf+" "+test.db, func(t *testing.T) {
84-
c, dl, _, err := ProcessGeofeed(test.gf, test.db, "", Options{LaxMode: test.laxMode})
94+
c, dl, _, err := ProcessGeofeed(
95+
test.gf,
96+
test.db,
97+
"",
98+
Options{
99+
EmptyOK: test.emptyOK,
100+
LaxMode: test.laxMode,
101+
},
102+
)
85103
require.NoError(t, err, "processGeofeed ran without error")
86104
for i, s := range test.dl {
87105
assert.Contains(
@@ -102,7 +120,6 @@ func TestProcessGeofeed_Invalid(t *testing.T) {
102120
{
103121
gf: "test_data/geofeed-invalid-missing-fields.csv",
104122
db: "test_data/GeoIP2-City-Test.mmdb",
105-
dl: []string{},
106123
c: CheckResult{
107124
Total: 2,
108125
Differences: 0,
@@ -118,7 +135,6 @@ func TestProcessGeofeed_Invalid(t *testing.T) {
118135
{
119136
gf: "test_data/geofeed-invalid-empty-network.csv",
120137
db: "test_data/GeoIP2-City-Test.mmdb",
121-
dl: []string{},
122138
c: CheckResult{
123139
Total: 2,
124140
Differences: 1,
@@ -133,7 +149,6 @@ func TestProcessGeofeed_Invalid(t *testing.T) {
133149
{
134150
gf: "test_data/geofeed-invalid-network.csv",
135151
db: "test_data/GeoIP2-City-Test.mmdb",
136-
dl: []string{},
137152
c: CheckResult{
138153
Total: 2,
139154
Differences: 1,
@@ -149,7 +164,6 @@ func TestProcessGeofeed_Invalid(t *testing.T) {
149164
// Geofeed that is valid in lax mode should not be valid if laxMode == true.
150165
gf: "test_data/geofeed-valid-lax.csv",
151166
db: "test_data/GeoIP2-City-Test.mmdb",
152-
dl: []string{},
153167
c: CheckResult{
154168
Total: 3,
155169
Differences: 1,
@@ -162,12 +176,30 @@ func TestProcessGeofeed_Invalid(t *testing.T) {
162176
em: ErrInvalidGeofeed,
163177
laxMode: false,
164178
},
179+
{
180+
gf: "test_data/empty.csv",
181+
db: "test_data/GeoIP2-City-Test.mmdb",
182+
c: CheckResult{
183+
Total: 0,
184+
SampleInvalidRows: map[RowInvalidity]string{},
185+
},
186+
em: ErrEmptyGeofeed,
187+
emptyOK: false,
188+
},
165189
}
166190

167191
for _, test := range badTests {
168192
t.Run(
169193
test.gf+" "+test.db, func(t *testing.T) {
170-
c, _, _, err := ProcessGeofeed(test.gf, test.db, "", Options{LaxMode: test.laxMode})
194+
c, _, _, err := ProcessGeofeed(
195+
test.gf,
196+
test.db,
197+
"",
198+
Options{
199+
EmptyOK: test.emptyOK,
200+
LaxMode: test.laxMode,
201+
},
202+
)
171203
require.ErrorIs(
172204
t,
173205
err,

0 commit comments

Comments
 (0)