-
Notifications
You must be signed in to change notification settings - Fork 240
Description
While using roaring/v2 in my project, I encountered unexpected error interval had zero length
from .Validate()
at the end of operations similar to those in TestValidate
. Please note that bmap is not empty while calling .Validate()
.
Version: v2.4.3
import (
"testing"
"github.com/RoaringBitmap/roaring/v2"
"github.com/stretchr/testify/require"
)
func TestValidate(t *testing.T) {
b := roaring.New()
b.RemoveRange(0, 180)
b.AddRange(0, 180)
b.RemoveRange(180, 217)
b.AddRange(180, 217)
b.RemoveRange(217, 2394)
b.RemoveRange(2394, 2427)
b.AddRange(2394, 2427)
b.RemoveRange(2427, 2428)
b.AddRange(2427, 2428)
b.RemoveRange(2428, 3345)
b.RemoveRange(3345, 3346)
b.RemoveRange(3346, 3597)
b.RemoveRange(3597, 3815)
b.RemoveRange(3815, 3816)
b.AddRange(3815, 3816)
b.RemoveRange(3816, 3856)
b.RemoveRange(3856, 4067)
b.RemoveRange(4067, 4069)
b.RemoveRange(4069, 4071)
b.RemoveRange(4071, 4095)
b.RemoveRange(4095, 4096)
b.RunOptimize()
require.False(t, b.IsEmpty())
require.NoError(t, b.Validate())
}
Question: by the way, I’ve discovered that an empty bitmap doesn’t pass validation. Is that intentional? For example, in my project, bitmaps can be empty, and that’s a valid state. However, if I want to perform validation, I have to handle these two cases separately
func TestValidateEmpty(t *testing.T) {
require.NoError(t, roaring.New().Validate())
}
Question: in my project, I store bitmaps in storage in binary format using .MarshalBinary
. I started storing data when the bitmap version was v1 (from the package github.com/RoaringBitmap/roaring
). Before saving a v1 bitmap to storage, I also called v1.RunOptimize()
.
Now, since the v2 binary format is backward-compatible with v1, when reading data from storage, I simply use v2.UnmarshalBinary(..v1 bytes...)
. Additionally, from time to time, I call v2.Validate()
afterward to ensure everything is correct.
However, I’ve discovered that even though v1.RunOptimize()
was applied before serialization, v2.Validate()
can still fail (see the example below). To prevent this, I have to explicitly call v2.RunOptimize()
after deserialization before running v2.Validate()
.
Is this behavior intentional?
v1 version: v1.9.4
.
v2 version: v2.4.3
.
import (
"testing"
v1 "github.com/RoaringBitmap/roaring"
v2 "github.com/RoaringBitmap/roaring/v2"
"github.com/stretchr/testify/require"
)
func TestValidateFromV1(t *testing.T) {
v1 := v1.NewBitmap()
for i := 0; i <= 2; i++ {
v1.Add(uint32(i))
}
v1.RunOptimize()
b, err := v1.MarshalBinary()
require.NoError(t, err)
v2 := v2.New()
require.NoError(t, v2.UnmarshalBinary(b))
// v2.RunOptimize() <- if uncomment this line, .Validate will pass
require.NoError(t, v2.Validate())
}
Question: which are gurantees for .Validate
if i from origin use v2 bitmap, but don't do any .RunOptimize()
. Could it fail ?