From 473a00b66a2b9b8dae82e79ae8133d6259effec5 Mon Sep 17 00:00:00 2001 From: Dominic Mitchell Date: Sun, 9 Nov 2025 16:58:23 +0000 Subject: [PATCH 1/6] Use the stdlib iter package now Go 1.24 is the minimum. --- iter.go | 8 +++++--- roaring64/iter.go | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/iter.go b/iter.go index 5b304b7a..1c43379e 100644 --- a/iter.go +++ b/iter.go @@ -1,9 +1,11 @@ package roaring +import "iter" + // Values returns an iterator that yields the elements of the bitmap in // increasing order. Starting with Go 1.23, users can use a for loop to iterate // over it. -func Values(b *Bitmap) func(func(uint32) bool) { +func Values(b *Bitmap) iter.Seq[uint32] { return func(yield func(uint32) bool) { it := b.Iterator() for it.HasNext() { @@ -17,7 +19,7 @@ func Values(b *Bitmap) func(func(uint32) bool) { // Backward returns an iterator that yields the elements of the bitmap in // decreasing order. Starting with Go 1.23, users can use a for loop to iterate // over it. -func Backward(b *Bitmap) func(func(uint32) bool) { +func Backward(b *Bitmap) iter.Seq[uint32] { return func(yield func(uint32) bool) { it := b.ReverseIterator() for it.HasNext() { @@ -30,7 +32,7 @@ func Backward(b *Bitmap) func(func(uint32) bool) { // Unset creates an iterator that yields values in the range [min, max] that are NOT contained in the bitmap. // The iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove). -func Unset(b *Bitmap, min, max uint32) func(func(uint32) bool) { +func Unset(b *Bitmap, min, max uint32) iter.Seq[uint32] { return func(yield func(uint32) bool) { it := b.UnsetIterator(uint64(min), uint64(max)+1) for it.HasNext() { diff --git a/roaring64/iter.go b/roaring64/iter.go index 7bf297a6..ce6c24db 100644 --- a/roaring64/iter.go +++ b/roaring64/iter.go @@ -1,9 +1,11 @@ package roaring64 +import "iter" + // Values returns an iterator that yields the elements of the bitmap in // increasing order. Starting with Go 1.23, users can use a for loop to iterate // over it. -func Values(b *Bitmap) func(func(uint64) bool) { +func Values(b *Bitmap) iter.Seq[uint64] { return func(yield func(uint64) bool) { it := b.Iterator() for it.HasNext() { @@ -17,7 +19,7 @@ func Values(b *Bitmap) func(func(uint64) bool) { // Backward returns an iterator that yields the elements of the bitmap in // decreasing order. Starting with Go 1.23, users can use a for loop to iterate // over it. -func Backward(b *Bitmap) func(func(uint64) bool) { +func Backward(b *Bitmap) iter.Seq[uint64] { return func(yield func(uint64) bool) { it := b.ReverseIterator() for it.HasNext() { From 22f439b30f62a07276c45e1dc94fa09a38d73602 Mon Sep 17 00:00:00 2001 From: Dominic Mitchell Date: Sun, 9 Nov 2025 16:58:21 +0000 Subject: [PATCH 2/6] Avoid the deprecated ioutil package. --- roaring64/bsi64_test.go | 3 +-- roaring64/serialization_test.go | 5 ++--- serialization_frozen_test.go | 13 ++++++------- serialization_test.go | 15 +++++++-------- smat_generate_test.go | 3 +-- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/roaring64/bsi64_test.go b/roaring64/bsi64_test.go index 3a08ac0b..5da0808e 100644 --- a/roaring64/bsi64_test.go +++ b/roaring64/bsi64_test.go @@ -5,7 +5,6 @@ import ( "encoding/binary" "fmt" "io" - "io/ioutil" "math/big" "math/rand" "os" @@ -645,7 +644,7 @@ func TestMinMaxWithNilFoundSet(t *testing.T) { } func TestBSIWriteToReadFrom(t *testing.T) { - file, err := ioutil.TempFile("./testdata", "bsi-test") + file, err := os.CreateTemp("./testdata", "bsi-test") if err != nil { t.Fatal(err) } diff --git a/roaring64/serialization_test.go b/roaring64/serialization_test.go index 7655d8b8..23509406 100644 --- a/roaring64/serialization_test.go +++ b/roaring64/serialization_test.go @@ -6,7 +6,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "math" "os" "path/filepath" @@ -276,7 +275,7 @@ func Test_tryReadFromRoaring32WithRoaring64(t *testing.T) { } func Test_tryReadFromRoaring32WithRoaring64_File(t *testing.T) { - tempDir, err := ioutil.TempDir("./", "testdata") + tempDir, err := os.MkdirTemp("./", "testdata") if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return @@ -290,7 +289,7 @@ func Test_tryReadFromRoaring32WithRoaring64_File(t *testing.T) { } name := filepath.Join(tempDir, "r32") - if err := ioutil.WriteFile(name, bs, 0o600); err != nil { + if err := os.WriteFile(name, bs, 0o600); err != nil { t.Fatal(err) } file, err := os.Open(name) diff --git a/serialization_frozen_test.go b/serialization_frozen_test.go index cb67392b..ee179ea1 100644 --- a/serialization_frozen_test.go +++ b/serialization_frozen_test.go @@ -6,7 +6,6 @@ package roaring import ( "bytes" "fmt" - "io/ioutil" "os" "reflect" "testing" @@ -49,12 +48,12 @@ func TestFrozenFormat(t *testing.T) { t.Run("view "+name, func(t *testing.T) { t.Parallel() - frozenBuf, err := ioutil.ReadFile(fpath) + frozenBuf, err := os.ReadFile(fpath) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return } - portableBuf, err := ioutil.ReadFile(ppath) + portableBuf, err := os.ReadFile(ppath) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return @@ -75,12 +74,12 @@ func TestFrozenFormat(t *testing.T) { t.Run("freeze "+name, func(t *testing.T) { t.Parallel() - frozenBuf, err := ioutil.ReadFile(fpath) + frozenBuf, err := os.ReadFile(fpath) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return } - portableBuf, err := ioutil.ReadFile(ppath) + portableBuf, err := os.ReadFile(ppath) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return @@ -106,12 +105,12 @@ func TestFrozenFormat(t *testing.T) { t.Run("freeze with writer"+name, func(t *testing.T) { t.Parallel() - frozenBuf, err := ioutil.ReadFile(fpath) + frozenBuf, err := os.ReadFile(fpath) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return } - portableBuf, err := ioutil.ReadFile(ppath) + portableBuf, err := os.ReadFile(ppath) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return diff --git a/serialization_test.go b/serialization_test.go index 035d3753..921f6540 100644 --- a/serialization_test.go +++ b/serialization_test.go @@ -7,7 +7,6 @@ import ( "encoding/binary" "encoding/gob" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" @@ -102,7 +101,7 @@ func TestSerializationToFile038(t *testing.T) { func TestSerializationReadRunsFromFile039(t *testing.T) { fn := "testdata/bitmapwithruns.bin" - by, err := ioutil.ReadFile(fn) + by, err := os.ReadFile(fn) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return @@ -464,7 +463,7 @@ func TestBitmap_FromBuffer(t *testing.T) { t.Run("bitmap with runs", func(t *testing.T) { file := "testdata/bitmapwithruns.bin" - buf, err := ioutil.ReadFile(file) + buf, err := os.ReadFile(file) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return @@ -480,7 +479,7 @@ func TestBitmap_FromBuffer(t *testing.T) { t.Run("bitmap without runs", func(t *testing.T) { fn := "testdata/bitmapwithruns.bin" - buf, err := ioutil.ReadFile(fn) + buf, err := os.ReadFile(fn) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") @@ -496,7 +495,7 @@ func TestBitmap_FromBuffer(t *testing.T) { // all3.classic somehow created by other tests. t.Run("all3.classic bitmap", func(t *testing.T) { file := "testdata/all3.classic" - buf, err := ioutil.ReadFile(file) + buf, err := os.ReadFile(file) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") @@ -511,7 +510,7 @@ func TestBitmap_FromBuffer(t *testing.T) { t.Run("testdata/bitmapwithruns.bin bitmap Ops", func(t *testing.T) { file := "testdata/bitmapwithruns.bin" - buf, err := ioutil.ReadFile(file) + buf, err := os.ReadFile(file) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") @@ -545,7 +544,7 @@ func TestBitmap_FromBuffer(t *testing.T) { t.Run("marking all containers as requiring COW", func(t *testing.T) { file := "testdata/bitmapwithruns.bin" - buf, err := ioutil.ReadFile(file) + buf, err := os.ReadFile(file) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") @@ -572,7 +571,7 @@ func TestSerializationCrashers(t *testing.T) { } for _, crasher := range crashers { - data, err := ioutil.ReadFile(crasher) + data, err := os.ReadFile(crasher) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") return diff --git a/smat_generate_test.go b/smat_generate_test.go index ed328d31..d2631440 100644 --- a/smat_generate_test.go +++ b/smat_generate_test.go @@ -5,7 +5,6 @@ package roaring import ( "fmt" - "io/ioutil" "os" "testing" @@ -21,7 +20,7 @@ func TestGenerateSmatCorpus(t *testing.T) { err, i, actionSeq) } os.MkdirAll("workdir/corpus", 0700) - ioutil.WriteFile(fmt.Sprintf("workdir/corpus/%d", i), byteSequence, 0600) + os.WriteFile(fmt.Sprintf("workdir/corpus/%d", i), byteSequence, 0600) } } From c79435ab5a1f8d3ec963de122c5869ddd69a508c Mon Sep 17 00:00:00 2001 From: Dominic Mitchell Date: Sun, 9 Nov 2025 16:58:18 +0000 Subject: [PATCH 3/6] Use `t.TempDir()` to access a guaranteed writable directory. This is available since [Go 1.15](https://tip.golang.org/doc/go1.15#testingpkgtesting). --- roaring64/bsi64_test.go | 3 +-- roaring64/serialization_test.go | 7 ++----- serialization_test.go | 7 ++----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/roaring64/bsi64_test.go b/roaring64/bsi64_test.go index 5da0808e..fce3f0d0 100644 --- a/roaring64/bsi64_test.go +++ b/roaring64/bsi64_test.go @@ -644,11 +644,10 @@ func TestMinMaxWithNilFoundSet(t *testing.T) { } func TestBSIWriteToReadFrom(t *testing.T) { - file, err := os.CreateTemp("./testdata", "bsi-test") + file, err := os.CreateTemp(t.TempDir(), "bsi-test") if err != nil { t.Fatal(err) } - defer t.Cleanup(func() { os.Remove(file.Name()) }) defer file.Close() bsi, min, max := setupRandom() _, err = bsi.WriteTo(file) diff --git a/roaring64/serialization_test.go b/roaring64/serialization_test.go index 23509406..c1c4a11c 100644 --- a/roaring64/serialization_test.go +++ b/roaring64/serialization_test.go @@ -86,7 +86,7 @@ func TestSerializationBasic037(t *testing.T) { func TestSerializationToFile038(t *testing.T) { rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000) - fname := "myfile.bin" + fname := filepath.Join(t.TempDir(), "myfile.bin") fout, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o660) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") @@ -113,10 +113,7 @@ func TestSerializationToFile038(t *testing.T) { buf := bytes.NewBuffer(nil) teer := io.TeeReader(fin, buf) - defer func() { - fin.Close() - _ = os.Remove(fname) - }() + defer fin.Close() _, _ = newrb.ReadFrom(teer) assert.True(t, rb.Equals(newrb)) diff --git a/serialization_test.go b/serialization_test.go index 921f6540..979a5765 100644 --- a/serialization_test.go +++ b/serialization_test.go @@ -64,7 +64,7 @@ func TestSerializationBasic037(t *testing.T) { func TestSerializationToFile038(t *testing.T) { rb := BitmapOf(1, 2, 3, 4, 5, 100, 1000) - fname := "myfile.bin" + fname := filepath.Join(t.TempDir(), "myfile.bin") fout, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0660) if err != nil { fmt.Fprintf(os.Stderr, "\n\nIMPORTANT: For testing file IO, the roaring library requires disk access.\nWe omit some tests for now.\n\n") @@ -89,10 +89,7 @@ func TestSerializationToFile038(t *testing.T) { return } - defer func() { - fin.Close() - _ = os.Remove(fname) - }() + defer fin.Close() _, _ = newrb.ReadFrom(fin) assert.True(t, rb.Equals(newrb)) From f8a2ba21c35d526337eb756ff02af40b76401fda Mon Sep 17 00:00:00 2001 From: Dominic Mitchell Date: Sun, 9 Nov 2025 16:55:55 +0000 Subject: [PATCH 4/6] Correct whitespace. --- .vscode/settings.json | 3 +++ roaring64/serialization_test.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..07eabfd6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.enabled": false +} diff --git a/roaring64/serialization_test.go b/roaring64/serialization_test.go index c1c4a11c..999d8d55 100644 --- a/roaring64/serialization_test.go +++ b/roaring64/serialization_test.go @@ -113,7 +113,7 @@ func TestSerializationToFile038(t *testing.T) { buf := bytes.NewBuffer(nil) teer := io.TeeReader(fin, buf) - defer fin.Close() + defer fin.Close() _, _ = newrb.ReadFrom(teer) assert.True(t, rb.Equals(newrb)) From f2007153f4a42085fa795b52e79eb161c85fb0f7 Mon Sep 17 00:00:00 2001 From: Dominic Mitchell Date: Sun, 9 Nov 2025 22:52:15 +0100 Subject: [PATCH 5/6] Remove unused local file. --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 07eabfd6..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "git.enabled": false -} From af00e64c33fa5ccf75f369cdfff84386e3b109a7 Mon Sep 17 00:00:00 2001 From: Dominic Mitchell Date: Sun, 9 Nov 2025 23:12:35 +0100 Subject: [PATCH 6/6] Update workflows to use Go 1.24. The main go.mod uses this as well now, so the CI should follow along. --- .github/workflows/armtests.yml | 2 +- .github/workflows/basictests.yml | 2 +- .github/workflows/bigendiantests.yml | 2 +- .github/workflows/legacytests.yml | 2 +- .github/workflows/macostests.yml | 2 +- .github/workflows/windowstests.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/armtests.yml b/.github/workflows/armtests.yml index 2be5ce61..d16b7f8c 100644 --- a/.github/workflows/armtests.yml +++ b/.github/workflows/armtests.yml @@ -7,7 +7,7 @@ jobs: test: strategy: matrix: - go-version: [1.22.x] + go-version: [1.24.x] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/basictests.yml b/.github/workflows/basictests.yml index 90e058d7..c8c9ac57 100644 --- a/.github/workflows/basictests.yml +++ b/.github/workflows/basictests.yml @@ -7,7 +7,7 @@ jobs: test: strategy: matrix: - go-version: [1.22.x] + go-version: [1.24.x] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/bigendiantests.yml b/.github/workflows/bigendiantests.yml index 326372e5..5ce88625 100644 --- a/.github/workflows/bigendiantests.yml +++ b/.github/workflows/bigendiantests.yml @@ -7,7 +7,7 @@ jobs: test: strategy: matrix: - go-version: [1.22.x] + go-version: [1.24.x] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/legacytests.yml b/.github/workflows/legacytests.yml index ffaa7bef..41981a4b 100644 --- a/.github/workflows/legacytests.yml +++ b/.github/workflows/legacytests.yml @@ -7,7 +7,7 @@ jobs: test: strategy: matrix: - go-version: [1.22.x] + go-version: [1.24.x] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/macostests.yml b/.github/workflows/macostests.yml index e83fed1b..8b095d50 100644 --- a/.github/workflows/macostests.yml +++ b/.github/workflows/macostests.yml @@ -7,7 +7,7 @@ jobs: test: strategy: matrix: - go-version: [1.22.x] + go-version: [1.24.x] platform: [macos-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/windowstests.yml b/.github/workflows/windowstests.yml index 9660de6c..92937f62 100644 --- a/.github/workflows/windowstests.yml +++ b/.github/workflows/windowstests.yml @@ -7,7 +7,7 @@ jobs: test: strategy: matrix: - go-version: [1.22.x] + go-version: [1.24.x] platform: [windows-latest] runs-on: ${{ matrix.platform }} steps: