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

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 134081b  ARROW-4126: [Go] offset not used when accessing boolean array
134081b is described below

commit 134081bea48d48307ed08b2e638fa40a3415ba77
Author: jlapacik <[email protected]>
AuthorDate: Mon Jan 7 15:47:33 2019 -0600

    ARROW-4126: [Go] offset not used when accessing boolean array
    
    Closes https://github.com/apache/arrow/issues/3273 .
    
    Author: jlapacik <[email protected]>
    
    Closes #3275 from jlapacik/fix/go-boolean-slice and squashes the following 
commits:
    
    67c5d739a <jlapacik> assign slice value in out of bounds tests
    9e3ac33dd <jlapacik> allocate new slice for each test case
    6901d09f1 <jlapacik> ARROW-4126:  offset not used when accessing boolean 
array
---
 go/arrow/array/boolean.go      |   7 +-
 go/arrow/array/boolean_test.go | 260 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 266 insertions(+), 1 deletion(-)

diff --git a/go/arrow/array/boolean.go b/go/arrow/array/boolean.go
index 19a6923..68de951 100644
--- a/go/arrow/array/boolean.go
+++ b/go/arrow/array/boolean.go
@@ -45,7 +45,12 @@ func NewBooleanData(data *Data) *Boolean {
        return a
 }
 
-func (a *Boolean) Value(i int) bool { return bitutil.BitIsSet(a.values, i) }
+func (a *Boolean) Value(i int) bool {
+       if i < 0 || i >= a.array.data.length {
+               panic("arrow/array: index out of range")
+       }
+       return bitutil.BitIsSet(a.values, a.array.data.offset+i)
+}
 
 func (a *Boolean) String() string {
        o := new(strings.Builder)
diff --git a/go/arrow/array/boolean_test.go b/go/arrow/array/boolean_test.go
new file mode 100644
index 0000000..e6f4b9b
--- /dev/null
+++ b/go/arrow/array/boolean_test.go
@@ -0,0 +1,260 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package array_test
+
+import (
+       "reflect"
+       "testing"
+
+       "github.com/apache/arrow/go/arrow/array"
+       "github.com/apache/arrow/go/arrow/memory"
+)
+
+func TestBooleanSliceData(t *testing.T) {
+       pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+       defer pool.AssertSize(t, 0)
+
+       values := []bool{true, false, true, true, true, true, true, false, 
true, false}
+
+       b := array.NewBooleanBuilder(pool)
+       defer b.Release()
+
+       for _, v := range values {
+               b.Append(v)
+       }
+
+       arr := b.NewArray().(*array.Boolean)
+       defer arr.Release()
+
+       if got, want := arr.Len(), len(values); got != want {
+               t.Fatalf("got=%d, want=%d", got, want)
+       }
+
+       vs := make([]bool, arr.Len())
+
+       for i := range vs {
+               vs[i] = arr.Value(i)
+       }
+
+       if got, want := vs, values; !reflect.DeepEqual(got, want) {
+               t.Fatalf("got=%v, want=%v", got, want)
+       }
+
+       tests := []struct {
+               interval [2]int64
+               want     []bool
+       }{
+               {
+                       interval: [2]int64{0, 0},
+                       want:     []bool{},
+               },
+               {
+                       interval: [2]int64{10, 10},
+                       want:     []bool{},
+               },
+               {
+                       interval: [2]int64{0, 5},
+                       want:     []bool{true, false, true, true, true},
+               },
+               {
+                       interval: [2]int64{5, 10},
+                       want:     []bool{true, true, false, true, false},
+               },
+               {
+                       interval: [2]int64{2, 7},
+                       want:     []bool{true, true, true, true, true},
+               },
+       }
+
+       for _, tc := range tests {
+               t.Run("", func(t *testing.T) {
+
+                       slice := array.NewSlice(arr, tc.interval[0], 
tc.interval[1]).(*array.Boolean)
+                       defer slice.Release()
+
+                       if got, want := slice.Len(), len(tc.want); got != want {
+                               t.Fatalf("got=%d, want=%d", got, want)
+                       }
+
+                       vs := make([]bool, slice.Len())
+
+                       for i := range vs {
+                               vs[i] = slice.Value(i)
+                       }
+
+                       if got, want := vs, tc.want; !reflect.DeepEqual(got, 
want) {
+                               t.Fatalf("got=%v, want=%v", got, want)
+                       }
+               })
+       }
+}
+
+func TestBooleanSliceDataWithNull(t *testing.T) {
+       pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+       defer pool.AssertSize(t, 0)
+
+       values := []bool{true, false, true, false, false, false, true, false, 
true, false}
+       valids := []bool{true, false, true, true, true, true, true, false, 
true, true}
+
+       b := array.NewBooleanBuilder(pool)
+       defer b.Release()
+
+       b.AppendValues(values, valids)
+
+       arr := b.NewArray().(*array.Boolean)
+       defer arr.Release()
+
+       if got, want := arr.Len(), len(valids); got != want {
+               t.Fatalf("got=%d, want=%d", got, want)
+       }
+
+       if got, want := arr.NullN(), 2; got != want {
+               t.Fatalf("got=%d, want=%d", got, want)
+       }
+
+       vs := make([]bool, arr.Len())
+
+       for i := range vs {
+               vs[i] = arr.Value(i)
+       }
+
+       if got, want := vs, values; !reflect.DeepEqual(got, want) {
+               t.Fatalf("got=%v, want=%v", got, want)
+       }
+
+       tests := []struct {
+               interval [2]int64
+               nulls    int
+               want     []bool
+       }{
+               {
+                       interval: [2]int64{2, 9},
+                       nulls:    1,
+                       want:     []bool{true, false, false, false, true, 
false, true},
+               },
+               {
+                       interval: [2]int64{0, 7},
+                       nulls:    1,
+                       want:     []bool{true, false, true, false, false, 
false, true},
+               },
+               {
+                       interval: [2]int64{1, 8},
+                       nulls:    2,
+                       want:     []bool{false, true, false, false, false, 
true, false},
+               },
+               {
+                       interval: [2]int64{2, 7},
+                       nulls:    0,
+                       want:     []bool{true, false, false, false, true},
+               },
+       }
+
+       for _, tc := range tests {
+               t.Run("", func(t *testing.T) {
+
+                       slice := array.NewSlice(arr, tc.interval[0], 
tc.interval[1]).(*array.Boolean)
+                       defer slice.Release()
+
+                       if got, want := slice.NullN(), tc.nulls; got != want {
+                               t.Errorf("got=%d, want=%d", got, want)
+                       }
+
+                       if got, want := slice.Len(), len(tc.want); got != want {
+                               t.Fatalf("got=%d, want=%d", got, want)
+                       }
+
+                       vs := make([]bool, slice.Len())
+
+                       for i := range vs {
+                               vs[i] = slice.Value(i)
+                       }
+
+                       if got, want := vs, tc.want; !reflect.DeepEqual(got, 
want) {
+                               t.Fatalf("got=%v, want=%v", got, want)
+                       }
+               })
+       }
+}
+
+func TestBooleanSliceOutOfBounds(t *testing.T) {
+       pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+       defer pool.AssertSize(t, 0)
+
+       values := []bool{true, false, true, false, true, false, true, false, 
true, false}
+
+       b := array.NewBooleanBuilder(pool)
+       defer b.Release()
+
+       for _, v := range values {
+               b.Append(v)
+       }
+
+       arr := b.NewArray().(*array.Boolean)
+       defer arr.Release()
+
+       slice := array.NewSlice(arr, 3, 8).(*array.Boolean)
+       defer slice.Release()
+
+       tests := []struct {
+               index int
+               panic bool
+       }{
+               {
+                       index: -1,
+                       panic: true,
+               },
+               {
+                       index: 5,
+                       panic: true,
+               },
+               {
+                       index: 0,
+                       panic: false,
+               },
+               {
+                       index: 4,
+                       panic: false,
+               },
+       }
+
+       for _, tc := range tests {
+               t.Run("", func(t *testing.T) {
+
+                       var val bool
+
+                       if tc.panic {
+                               defer func() {
+                                       e := recover()
+                                       if e == nil {
+                                               t.Fatalf("this should have 
panicked, but did not; slice value %v", val)
+                                       }
+                                       if got, want := e.(string), 
"arrow/array: index out of range"; got != want {
+                                               t.Fatalf("invalid error. 
got=%q, want=%q", got, want)
+                                       }
+                               }()
+                       } else {
+                               defer func() {
+                                       if e := recover(); e != nil {
+                                               t.Fatalf("unexpected panic: 
%v", e)
+                                       }
+                               }()
+                       }
+
+                       val = slice.Value(tc.index)
+               })
+       }
+}

Reply via email to