Skip to content

Commit 358583c

Browse files
committed
fixing various Validate() bugs.
1 parent 461d7ec commit 358583c

File tree

6 files changed

+65
-24
lines changed

6 files changed

+65
-24
lines changed

roaring.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,9 @@ func (rb *Bitmap) Stats() Statistics {
21332133
return stats
21342134
}
21352135

2136+
// Validate checks if the bitmap is internally consistent.
2137+
// You may call it after deserialization to check that the bitmap is valid.
2138+
// This function returns an error if the bitmap is invalid, nil otherwise.
21362139
func (rb *Bitmap) Validate() error {
21372140
return rb.highlowcontainer.validate()
21382141
}

roaring64/roaringarray64.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ type roaringArray64 struct {
1414
}
1515

1616
var (
17-
ErrEmptyKeys = errors.New("keys were empty")
1817
ErrKeySortOrder = errors.New("keys were out of order")
1918
ErrCardinalityConstraint = errors.New("size of arrays was not coherent")
2019
)
@@ -437,10 +436,6 @@ func (ra *roaringArray64) checkKeysSorted() bool {
437436
// validate checks the referential integrity
438437
// ensures len(keys) == len(containers), recurses and checks each container type
439438
func (ra *roaringArray64) validate() error {
440-
if len(ra.keys) == 0 {
441-
return ErrEmptyKeys
442-
}
443-
444439
if !ra.checkKeysSorted() {
445440
return ErrKeySortOrder
446441
}

roaring_test.go

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2732,8 +2732,6 @@ func TestFromBitSet(t *testing.T) {
27322732
func TestRoaringArrayValidation(t *testing.T) {
27332733
a := newRoaringArray()
27342734

2735-
assert.ErrorIs(t, a.validate(), ErrEmptyKeys)
2736-
27372735
a.keys = append(a.keys, uint16(3), uint16(1))
27382736
assert.ErrorIs(t, a.validate(), ErrKeySortOrder)
27392737
a.clear()
@@ -2805,11 +2803,9 @@ func TestBitMapValidationFromDeserialization(t *testing.T) {
28052803
bm.AddRange(100, 110)
28062804
},
28072805
corruptor: func(s []byte) {
2808-
// 13 is the length of the run
2809-
// Setting to zero causes an invalid run
28102806
s[13] = 0
28112807
},
2812-
err: ErrRunIntervalLength,
2808+
err: ErrRunIntervalSize,
28132809
},
28142810
{
28152811
name: "Creates Interval Overlap",
@@ -3310,3 +3306,59 @@ func TestIssue467CaseLarge(t *testing.T) {
33103306
b.RunOptimize()
33113307
require.NoError(t, b.Validate())
33123308
}
3309+
3310+
func TestValidateEmpty(t *testing.T) {
3311+
require.NoError(t, New().Validate())
3312+
}
3313+
3314+
func TestValidate469(t *testing.T) {
3315+
b := New()
3316+
b.RemoveRange(0, 180)
3317+
b.AddRange(0, 180)
3318+
require.NoError(t, b.Validate())
3319+
b.RemoveRange(180, 217)
3320+
b.AddRange(180, 217)
3321+
require.NoError(t, b.Validate())
3322+
b.RemoveRange(217, 2394)
3323+
b.RemoveRange(2394, 2427)
3324+
b.AddRange(2394, 2427)
3325+
require.NoError(t, b.Validate())
3326+
b.RemoveRange(2427, 2428)
3327+
b.AddRange(2427, 2428)
3328+
require.NoError(t, b.Validate())
3329+
b.RemoveRange(2428, 3345)
3330+
require.NoError(t, b.Validate())
3331+
b.RemoveRange(3345, 3346)
3332+
require.NoError(t, b.Validate())
3333+
b.RemoveRange(3346, 3597)
3334+
require.NoError(t, b.Validate())
3335+
b.RemoveRange(3597, 3815)
3336+
require.NoError(t, b.Validate())
3337+
b.RemoveRange(3815, 3816)
3338+
require.NoError(t, b.Validate())
3339+
b.AddRange(3815, 3816)
3340+
require.NoError(t, b.Validate())
3341+
b.RemoveRange(3816, 3856)
3342+
b.RemoveRange(3856, 4067)
3343+
b.RemoveRange(4067, 4069)
3344+
b.RemoveRange(4069, 4071)
3345+
b.RemoveRange(4071, 4095)
3346+
b.RemoveRange(4095, 4096)
3347+
require.NoError(t, b.Validate())
3348+
b.RunOptimize()
3349+
require.False(t, b.IsEmpty())
3350+
require.NoError(t, b.Validate())
3351+
}
3352+
3353+
func TestValidateFromV1(t *testing.T) {
3354+
v1 := New()
3355+
for i := 0; i <= 2; i++ {
3356+
v1.Add(uint32(i))
3357+
}
3358+
v1.RunOptimize()
3359+
b, err := v1.MarshalBinary()
3360+
require.NoError(t, err)
3361+
v2 := New()
3362+
require.NoError(t, v2.UnmarshalBinary(b))
3363+
require.NoError(t, v2.Validate())
3364+
}

roaringarray.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ const (
9090
)
9191

9292
var (
93-
ErrEmptyKeys = errors.New("keys were empty")
9493
ErrKeySortOrder = errors.New("keys were out of order")
9594
ErrCardinalityConstraint = errors.New("size of arrays was not coherent")
9695
)
@@ -798,10 +797,6 @@ func (ra *roaringArray) checkKeysSorted() bool {
798797
// validate checks the referential integrity
799798
// ensures len(keys) == len(containers), recurses and checks each container type
800799
func (ra *roaringArray) validate() error {
801-
if len(ra.keys) == 0 {
802-
return ErrEmptyKeys
803-
}
804-
805800
if !ra.checkKeysSorted() {
806801
return ErrKeySortOrder
807802
}

runcontainer.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ type interval16 struct {
6262
var (
6363
ErrRunIntervalsEmpty = errors.New("run contained no interval")
6464
ErrRunNonSorted = errors.New("runs were not sorted")
65-
ErrRunIntervalLength = errors.New("interval had zero length")
6665
ErrRunIntervalEqual = errors.New("intervals were equal")
6766
ErrRunIntervalOverlap = errors.New("intervals overlapped or were continguous")
6867
ErrRunIntervalSize = errors.New("too many intervals relative to data")
@@ -2757,10 +2756,9 @@ func (rc *runContainer16) validate() error {
27572756

27582757
intervalsSum := 0
27592758
for outeridx := range rc.iv {
2760-
2761-
if rc.iv[outeridx].length == 0 {
2762-
return ErrRunIntervalLength
2763-
}
2759+
// The length being stored is the actual length - 1.
2760+
// So we need to add 1 to get the actual length.
2761+
// It is not possible to have a run with length 0.
27642762

27652763
outerInterval := rc.iv[outeridx]
27662764

@@ -2799,7 +2797,7 @@ func (rc *runContainer16) validate() error {
27992797
return ErrRunIntervalSize
28002798
}
28012799
} else {
2802-
if !(len(rc.iv) < (intervalsSum / 2)) {
2800+
if !(2*len(rc.iv) < intervalsSum) {
28032801
return ErrRunIntervalSize
28042802
}
28052803
}

serialization_frozen_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,9 @@ func TestBitMapValidationFromFrozen(t *testing.T) {
171171
bm.AddRange(100, 110)
172172
},
173173
corruptor: func(s []byte) {
174-
// 13 is the length of the run
175-
// Setting to zero causes an invalid run
176174
s[2] = 0
177175
},
178-
err: ErrRunIntervalLength,
176+
err: ErrRunIntervalSize,
179177
},
180178
{
181179
name: "Creates Interval Overlap",

0 commit comments

Comments
 (0)