This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 28128ef0 test(arrow/array): make run-end-encoded concat tests valid on 
32-bit platforms (#1408)
28128ef0 is described below

commit 28128ef0cc71db9c8865de06df38971efc8b396e
Author: Matt Topol <[email protected]>
AuthorDate: Mon Oct 26 15:21:24 2026 +0000

    test(arrow/array): make run-end-encoded concat tests valid on 32-bit 
platforms (#1408)
    
    ### Rationale for this change
    
    `TestConcatRunEndEncodedInt64FinalRunEndClamp` panics on 386
    (`GOARCH=386 go test ./arrow/array -run
    TestConcatRunEndEncodedInt64FinalRunEndClamp`):
    
    ```
    panic: arrow/array: index out of range
        arrow/array/data.go:245  (NewSliceData)
        arrow/array/concat_test.go:1231
    ```
    
    The test builds its input with
    `RunEndEncodedBuilder.Append(math.MaxInt64)`, which makes an array whose
    length is `math.MaxInt64`. Array lengths are `int`, so on 32-bit targets
    the length wraps negative and `array.NewSlice(big, 0, 1)` panics while
    *building the input*: the test never reaches `Concatenate`. That is
    exactly the platform it was written for, since #1219's original bug (an
    `int(e)` conversion of the run end) only overflowed when `int` is 32
    bits.
    
    Two related tests, `TestConcatAlmostOverflowRunEndEncoding/int64` and
    `TestConcatOverflowRunEndEncoding/int64`, have the same problem: they
    build inputs whose logical lengths are near 2^62, which cannot exist
    with 32-bit `int`.
    
    These panics are not visible in CI, which only cross-builds for 386.
    
    ### What changes are included in this PR?
    
    Test-only changes in `arrow/array/concat_test.go`:
    
    - `TestConcatRunEndEncodedInt64FinalRunEndClamp` builds the one-element
    input directly with `NewRunEndEncodedArray`: run ends `[math.MaxInt64]`,
    logical length 1. That is the same shape as a one-element slice of a
    `MaxInt64`-length run, and it is valid on 32-bit. The test now also
    checks the concatenated run ends (`[5, 6]`) and values (`[1, 2]`), not
    just the length.
    - The two `*OverflowRunEndEncoding` tests skip their `int64` case when
    `tt.max > math.MaxInt`, i.e. only where the inputs cannot be
    constructed. The int16 and int32 cases still run everywhere.
    
    ### Are these changes tested?
    
    - `GOARCH=386 go test ./arrow/array -run Concat`: ok (two `int64`
    subtests skipped).
    - `go test ./arrow/array`: ok on amd64, no skips.
    - The rewritten clamp test still guards #1219: with #1219's `concat.go`
    change reverted it fails on amd64 (`overflow in run-length-encoded run
    ends concat`) and on 386 (wrong run ends).
    - `go vet ./arrow/array` and `gofmt -l`: clean.
    
    Not addressed here: `arrow/array` still has other, unrelated 386
    failures in the decimal tests (e.g. `TestDecimal128Slice`,
    `TestDecimal256Slice`), which fail the same way on main.
    
    ### Are there any user-facing changes?
    
    No.
---
 arrow/array/concat_test.go | 34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/arrow/array/concat_test.go b/arrow/array/concat_test.go
index ccd661ff..1beb650c 100644
--- a/arrow/array/concat_test.go
+++ b/arrow/array/concat_test.go
@@ -1222,19 +1222,29 @@ func TestConcatRunEndEncodedInt64FinalRunEndClamp(t 
*testing.T) {
        prefix := prefixBldr.NewArray()
        defer prefix.Release()
 
-       bigBldr := array.NewRunEndEncodedBuilder(mem, 
arrow.PrimitiveTypes.Int64, arrow.PrimitiveTypes.Int64)
-       defer bigBldr.Release()
-       bigBldr.Append(math.MaxInt64)
-       bigBldr.ValueBuilder().(*array.Int64Builder).Append(2)
-       big := bigBldr.NewArray()
-       defer big.Release()
-       oneElem := array.NewSlice(big, 0, 1) // first element of the 
MaxInt64-length run
+       // One logical element from a run ending at math.MaxInt64, as a slice 
of the
+       // run's first element would be. Build it directly: an array whose 
length is
+       // math.MaxInt64 cannot exist when int is 32 bits, but this one is 
valid there.
+       runEndsBldr := array.NewInt64Builder(mem)
+       defer runEndsBldr.Release()
+       runEndsBldr.Append(math.MaxInt64)
+       runEnds := runEndsBldr.NewArray()
+       defer runEnds.Release()
+       valuesBldr := array.NewInt64Builder(mem)
+       defer valuesBldr.Release()
+       valuesBldr.Append(2)
+       values := valuesBldr.NewArray()
+       defer values.Release()
+       oneElem := array.NewRunEndEncodedArray(runEnds, values, 1, 0)
        defer oneElem.Release()
 
        result, err := array.Concatenate([]arrow.Array{prefix, oneElem}, mem)
        require.NoError(t, err)
        defer result.Release()
        assert.EqualValues(t, 6, result.Len())
+       ree := result.(*array.RunEndEncoded)
+       assert.Equal(t, []int64{5, 6}, 
ree.RunEndsArr().(*array.Int64).Int64Values())
+       assert.Equal(t, []int64{1, 2}, 
ree.Values().(*array.Int64).Int64Values())
 }
 
 func TestConcatAlmostOverflowRunEndEncoding(t *testing.T) {
@@ -1249,6 +1259,11 @@ func TestConcatAlmostOverflowRunEndEncoding(t 
*testing.T) {
 
        for _, tt := range tests {
                t.Run(tt.offsetType.String(), func(t *testing.T) {
+                       if tt.max > math.MaxInt {
+                               // The inputs' logical lengths are near tt.max, 
and array lengths
+                               // are ints, so this case cannot be built when 
int is 32 bits.
+                               t.Skipf("array lengths near %d do not fit in 
int", tt.max)
+                       }
                        mem := 
memory.NewCheckedAllocator(memory.DefaultAllocator)
                        defer mem.AssertSize(t, 0)
 
@@ -1296,6 +1311,11 @@ func TestConcatOverflowRunEndEncoding(t *testing.T) {
 
        for _, tt := range tests {
                t.Run(tt.offsetType.String(), func(t *testing.T) {
+                       if tt.max > math.MaxInt {
+                               // The inputs' logical lengths are near tt.max, 
and array lengths
+                               // are ints, so this case cannot be built when 
int is 32 bits.
+                               t.Skipf("array lengths near %d do not fit in 
int", tt.max)
+                       }
                        mem := 
memory.NewCheckedAllocator(memory.DefaultAllocator)
                        defer mem.AssertSize(t, 0)
 

Reply via email to