github.com/apache/arrow/go/v16@v16.1.0/arrow/array/list_test.go (about)

     1  // Licensed to the Apache Software Foundation (ASF) under one
     2  // or more contributor license agreements.  See the NOTICE file
     3  // distributed with this work for additional information
     4  // regarding copyright ownership.  The ASF licenses this file
     5  // to you under the Apache License, Version 2.0 (the
     6  // "License"); you may not use this file except in compliance
     7  // with the License.  You may obtain a copy of the License at
     8  //
     9  // http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package array_test
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/apache/arrow/go/v16/arrow"
    24  	"github.com/apache/arrow/go/v16/arrow/array"
    25  	"github.com/apache/arrow/go/v16/arrow/memory"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  func TestListArray(t *testing.T) {
    30  	tests := []struct {
    31  		typeID  arrow.Type
    32  		offsets interface{}
    33  		sizes   interface{}
    34  		dt      arrow.DataType
    35  	}{
    36  		{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)},
    37  		{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)},
    38  		{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOfField(arrow.Field{Name: "item", Type: arrow.PrimitiveTypes.Int32, Nullable: true})},
    39  		{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOfField(arrow.Field{Name: "item", Type: arrow.PrimitiveTypes.Int32, Nullable: true})},
    40  		{arrow.LIST_VIEW, []int32{0, 3, 3, 3}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
    41  		{arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
    42  	}
    43  
    44  	for _, tt := range tests {
    45  		t.Run(tt.typeID.String(), func(t *testing.T) {
    46  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
    47  			defer pool.AssertSize(t, 0)
    48  
    49  			var (
    50  				vs      = []int32{0, 1, 2, 3, 4, 5, 6}
    51  				lengths = []int{3, 0, 0, 4}
    52  				isValid = []bool{true, false, true, true}
    53  			)
    54  
    55  			lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
    56  			defer lb.Release()
    57  
    58  			for i := 0; i < 10; i++ {
    59  				vb := lb.ValueBuilder().(*array.Int32Builder)
    60  				vb.Reserve(len(vs))
    61  
    62  				pos := 0
    63  				for i, length := range lengths {
    64  					lb.AppendWithSize(isValid[i], length)
    65  					for j := 0; j < length; j++ {
    66  						vb.Append(vs[pos])
    67  						pos++
    68  					}
    69  				}
    70  
    71  				arr := lb.NewArray().(array.ListLike)
    72  				defer arr.Release()
    73  
    74  				arr.Retain()
    75  				arr.Release()
    76  
    77  				if got, want := arr.DataType().ID(), tt.typeID; got != want {
    78  					t.Fatalf("got=%v, want=%v", got, want)
    79  				}
    80  
    81  				if got, want := arr.Len(), len(isValid); got != want {
    82  					t.Fatalf("got=%d, want=%d", got, want)
    83  				}
    84  
    85  				for i := range lengths {
    86  					if got, want := arr.IsValid(i), isValid[i]; got != want {
    87  						t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
    88  					}
    89  					if got, want := arr.IsNull(i), !isValid[i]; got != want {
    90  						t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
    91  					}
    92  				}
    93  
    94  				var gotOffsets, gotSizes interface{}
    95  				switch tt.typeID {
    96  				case arrow.LIST:
    97  					arr := arr.(*array.List)
    98  					gotOffsets = arr.Offsets()
    99  				case arrow.LARGE_LIST:
   100  					arr := arr.(*array.LargeList)
   101  					gotOffsets = arr.Offsets()
   102  				case arrow.LIST_VIEW:
   103  					arr := arr.(*array.ListView)
   104  					gotOffsets = arr.Offsets()
   105  					gotSizes = arr.Sizes()
   106  				case arrow.LARGE_LIST_VIEW:
   107  					arr := arr.(*array.LargeListView)
   108  					gotOffsets = arr.Offsets()
   109  					gotSizes = arr.Sizes()
   110  				}
   111  
   112  				if !reflect.DeepEqual(gotOffsets, tt.offsets) {
   113  					t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
   114  				}
   115  
   116  				if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW {
   117  					if !reflect.DeepEqual(gotSizes, tt.sizes) {
   118  						t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
   119  					}
   120  				}
   121  
   122  				varr := arr.ListValues().(*array.Int32)
   123  				if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
   124  					t.Fatalf("got=%v, want=%v", got, want)
   125  				}
   126  			}
   127  		})
   128  	}
   129  }
   130  
   131  // Like the list-view tests in TestListArray, but with out-of-order offsets.
   132  func TestListViewArray(t *testing.T) {
   133  	tests := []struct {
   134  		typeID  arrow.Type
   135  		offsets interface{}
   136  		sizes   interface{}
   137  		dt      arrow.DataType
   138  	}{
   139  		{arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
   140  		{arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
   141  	}
   142  
   143  	for _, tt := range tests {
   144  		t.Run(tt.typeID.String(), func(t *testing.T) {
   145  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   146  			defer pool.AssertSize(t, 0)
   147  
   148  			var (
   149  				vs      = []int32{-1, 3, 4, 5, 6, 0, 1, 2}
   150  				lengths = []int{3, 0, 0, 4}
   151  				isValid = []bool{true, false, true, true}
   152  			)
   153  
   154  			lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
   155  			defer lb.Release()
   156  
   157  			for i := 0; i < 10; i++ {
   158  				switch lvb := lb.(type) {
   159  				case *array.ListViewBuilder:
   160  					lvb.AppendDimensions(5, 3)
   161  					lb.AppendNull()
   162  					lvb.AppendDimensions(0, 0)
   163  					lvb.AppendDimensions(1, 4)
   164  				case *array.LargeListViewBuilder:
   165  					lvb.AppendDimensions(5, 3)
   166  					lb.AppendNull()
   167  					lvb.AppendDimensions(0, 0)
   168  					lvb.AppendDimensions(1, 4)
   169  				}
   170  
   171  				vb := lb.ValueBuilder().(*array.Int32Builder)
   172  				vb.Reserve(len(vs))
   173  				vb.AppendValues(vs, []bool{false, true, true, true, true, true, true, true})
   174  
   175  				arr := lb.NewArray().(array.ListLike)
   176  				defer arr.Release()
   177  
   178  				arr.Retain()
   179  				arr.Release()
   180  
   181  				if got, want := arr.DataType().ID(), tt.typeID; got != want {
   182  					t.Fatalf("got=%v, want=%v", got, want)
   183  				}
   184  
   185  				if got, want := arr.Len(), len(isValid); got != want {
   186  					t.Fatalf("got=%d, want=%d", got, want)
   187  				}
   188  
   189  				for i := range lengths {
   190  					if got, want := arr.IsValid(i), isValid[i]; got != want {
   191  						t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   192  					}
   193  					if got, want := arr.IsNull(i), !isValid[i]; got != want {
   194  						t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   195  					}
   196  				}
   197  
   198  				var gotOffsets, gotSizes interface{}
   199  				switch tt.typeID {
   200  				case arrow.LIST_VIEW:
   201  					arr := arr.(*array.ListView)
   202  					gotOffsets = arr.Offsets()
   203  					gotSizes = arr.Sizes()
   204  				case arrow.LARGE_LIST_VIEW:
   205  					arr := arr.(*array.LargeListView)
   206  					gotOffsets = arr.Offsets()
   207  					gotSizes = arr.Sizes()
   208  				}
   209  
   210  				if !reflect.DeepEqual(gotOffsets, tt.offsets) {
   211  					t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
   212  				}
   213  
   214  				if !reflect.DeepEqual(gotSizes, tt.sizes) {
   215  					t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
   216  				}
   217  
   218  				varr := arr.ListValues().(*array.Int32)
   219  				if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
   220  					t.Fatalf("got=%v, want=%v", got, want)
   221  				}
   222  			}
   223  		})
   224  	}
   225  }
   226  
   227  func TestListArrayEmpty(t *testing.T) {
   228  	typ := []arrow.DataType{
   229  		arrow.ListOf(arrow.PrimitiveTypes.Int32),
   230  		arrow.LargeListOf(arrow.PrimitiveTypes.Int32),
   231  		arrow.ListViewOf(arrow.PrimitiveTypes.Int32),
   232  		arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32),
   233  	}
   234  
   235  	for _, dt := range typ {
   236  		t.Run(dt.String(), func(t *testing.T) {
   237  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   238  			defer pool.AssertSize(t, 0)
   239  
   240  			lb := array.NewBuilder(pool, dt)
   241  			defer lb.Release()
   242  			arr := lb.NewArray()
   243  			defer arr.Release()
   244  			if got, want := arr.Len(), 0; got != want {
   245  				t.Fatalf("got=%d, want=%d", got, want)
   246  			}
   247  		})
   248  	}
   249  }
   250  
   251  func TestListArrayBulkAppend(t *testing.T) {
   252  	tests := []struct {
   253  		typeID  arrow.Type
   254  		offsets interface{}
   255  		sizes   interface{}
   256  		dt      arrow.DataType
   257  	}{
   258  		{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)},
   259  		{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)},
   260  		{arrow.LIST_VIEW, []int32{0, 3, 3, 3}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
   261  		{arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
   262  	}
   263  
   264  	for _, tt := range tests {
   265  		t.Run(tt.typeID.String(), func(t *testing.T) {
   266  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   267  			defer pool.AssertSize(t, 0)
   268  
   269  			var (
   270  				vs      = []int32{0, 1, 2, 3, 4, 5, 6}
   271  				lengths = []int{3, 0, 0, 4}
   272  				isValid = []bool{true, false, true, true}
   273  			)
   274  
   275  			lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
   276  			defer lb.Release()
   277  			vb := lb.ValueBuilder().(*array.Int32Builder)
   278  			vb.Reserve(len(vs))
   279  
   280  			switch tt.typeID {
   281  			case arrow.LIST:
   282  				lb.(*array.ListBuilder).AppendValues(tt.offsets.([]int32), isValid)
   283  			case arrow.LARGE_LIST:
   284  				lb.(*array.LargeListBuilder).AppendValues(tt.offsets.([]int64), isValid)
   285  			case arrow.LIST_VIEW:
   286  				lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
   287  			case arrow.LARGE_LIST_VIEW:
   288  				lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
   289  			}
   290  			for _, v := range vs {
   291  				vb.Append(v)
   292  			}
   293  
   294  			arr := lb.NewArray().(array.VarLenListLike)
   295  			defer arr.Release()
   296  
   297  			if got, want := arr.DataType().ID(), tt.typeID; got != want {
   298  				t.Fatalf("got=%v, want=%v", got, want)
   299  			}
   300  
   301  			if got, want := arr.Len(), len(isValid); got != want {
   302  				t.Fatalf("got=%d, want=%d", got, want)
   303  			}
   304  
   305  			for i := range lengths {
   306  				if got, want := arr.IsValid(i), isValid[i]; got != want {
   307  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   308  				}
   309  				if got, want := arr.IsNull(i), !isValid[i]; got != want {
   310  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   311  				}
   312  			}
   313  
   314  			var gotOffsets, gotSizes interface{}
   315  			switch tt.typeID {
   316  			case arrow.LIST:
   317  				arr := arr.(*array.List)
   318  				gotOffsets = arr.Offsets()
   319  			case arrow.LARGE_LIST:
   320  				arr := arr.(*array.LargeList)
   321  				gotOffsets = arr.Offsets()
   322  			case arrow.LIST_VIEW:
   323  				arr := arr.(*array.ListView)
   324  				gotOffsets = arr.Offsets()
   325  				gotSizes = arr.Sizes()
   326  			case arrow.LARGE_LIST_VIEW:
   327  				arr := arr.(*array.LargeListView)
   328  				gotOffsets = arr.Offsets()
   329  				gotSizes = arr.Sizes()
   330  			}
   331  
   332  			if !reflect.DeepEqual(gotOffsets, tt.offsets) {
   333  				t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
   334  			}
   335  			if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW {
   336  				if !reflect.DeepEqual(gotSizes, tt.sizes) {
   337  					t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
   338  				}
   339  			}
   340  
   341  			varr := arr.ListValues().(*array.Int32)
   342  			if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
   343  				t.Fatalf("got=%v, want=%v", got, want)
   344  			}
   345  		})
   346  	}
   347  }
   348  
   349  func TestListViewArrayBulkAppend(t *testing.T) {
   350  	tests := []struct {
   351  		typeID  arrow.Type
   352  		offsets interface{}
   353  		sizes   interface{}
   354  		dt      arrow.DataType
   355  	}{
   356  		{arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
   357  		{arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
   358  	}
   359  
   360  	for _, tt := range tests {
   361  		t.Run(tt.typeID.String(), func(t *testing.T) {
   362  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   363  			defer pool.AssertSize(t, 0)
   364  
   365  			var (
   366  				vs      = []int32{-1, 3, 4, 5, 6, 0, 1, 2}
   367  				lengths = []int{3, 0, 0, 4}
   368  				isValid = []bool{true, false, true, true}
   369  			)
   370  
   371  			lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
   372  			defer lb.Release()
   373  			vb := lb.ValueBuilder().(*array.Int32Builder)
   374  			vb.Reserve(len(vs))
   375  
   376  			switch tt.typeID {
   377  			case arrow.LIST_VIEW:
   378  				lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
   379  			case arrow.LARGE_LIST_VIEW:
   380  				lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
   381  			}
   382  			for _, v := range vs {
   383  				vb.Append(v)
   384  			}
   385  
   386  			arr := lb.NewArray().(array.VarLenListLike)
   387  			defer arr.Release()
   388  
   389  			if got, want := arr.DataType().ID(), tt.typeID; got != want {
   390  				t.Fatalf("got=%v, want=%v", got, want)
   391  			}
   392  
   393  			if got, want := arr.Len(), len(isValid); got != want {
   394  				t.Fatalf("got=%d, want=%d", got, want)
   395  			}
   396  
   397  			for i := range lengths {
   398  				if got, want := arr.IsValid(i), isValid[i]; got != want {
   399  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   400  				}
   401  				if got, want := arr.IsNull(i), !isValid[i]; got != want {
   402  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   403  				}
   404  			}
   405  
   406  			var gotOffsets, gotSizes interface{}
   407  			switch tt.typeID {
   408  			case arrow.LIST_VIEW:
   409  				arr := arr.(*array.ListView)
   410  				gotOffsets = arr.Offsets()
   411  				gotSizes = arr.Sizes()
   412  			case arrow.LARGE_LIST_VIEW:
   413  				arr := arr.(*array.LargeListView)
   414  				gotOffsets = arr.Offsets()
   415  				gotSizes = arr.Sizes()
   416  			}
   417  
   418  			if !reflect.DeepEqual(gotOffsets, tt.offsets) {
   419  				t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
   420  			}
   421  			if !reflect.DeepEqual(gotSizes, tt.sizes) {
   422  				t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
   423  			}
   424  
   425  			varr := arr.ListValues().(*array.Int32)
   426  			if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
   427  				t.Fatalf("got=%v, want=%v", got, want)
   428  			}
   429  		})
   430  	}
   431  }
   432  
   433  func TestListArraySlice(t *testing.T) {
   434  	tests := []struct {
   435  		typeID  arrow.Type
   436  		offsets interface{}
   437  		sizes   interface{}
   438  		dt      arrow.DataType
   439  	}{
   440  		{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)},
   441  		{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)},
   442  		{arrow.LIST_VIEW, []int32{0, 3, 3, 3, 7}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
   443  		{arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3, 7}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
   444  	}
   445  
   446  	for _, tt := range tests {
   447  		t.Run(tt.typeID.String(), func(t *testing.T) {
   448  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   449  			defer pool.AssertSize(t, 0)
   450  
   451  			var (
   452  				vs      = []int32{0, 1, 2, 3, 4, 5, 6}
   453  				lengths = []int{3, 0, 0, 4}
   454  				isValid = []bool{true, false, true, true}
   455  			)
   456  
   457  			lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
   458  			defer lb.Release()
   459  			vb := lb.ValueBuilder().(*array.Int32Builder)
   460  			vb.Reserve(len(vs))
   461  
   462  			switch tt.typeID {
   463  			case arrow.LIST:
   464  				lb.(*array.ListBuilder).AppendValues(tt.offsets.([]int32), isValid)
   465  			case arrow.LARGE_LIST:
   466  				lb.(*array.LargeListBuilder).AppendValues(tt.offsets.([]int64), isValid)
   467  			case arrow.LIST_VIEW:
   468  				lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
   469  			case arrow.LARGE_LIST_VIEW:
   470  				lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
   471  			}
   472  			for _, v := range vs {
   473  				vb.Append(v)
   474  			}
   475  
   476  			arr := lb.NewArray().(array.VarLenListLike)
   477  			defer arr.Release()
   478  
   479  			if got, want := arr.DataType().ID(), tt.typeID; got != want {
   480  				t.Fatalf("got=%v, want=%v", got, want)
   481  			}
   482  
   483  			if got, want := arr.Len(), len(isValid); got != want {
   484  				t.Fatalf("got=%d, want=%d", got, want)
   485  			}
   486  
   487  			for i := range lengths {
   488  				if got, want := arr.IsValid(i), isValid[i]; got != want {
   489  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   490  				}
   491  				if got, want := arr.IsNull(i), !isValid[i]; got != want {
   492  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   493  				}
   494  			}
   495  
   496  			var gotOffsets, gotSizes interface{}
   497  			switch tt.typeID {
   498  			case arrow.LIST:
   499  				arr := arr.(*array.List)
   500  				gotOffsets = arr.Offsets()
   501  			case arrow.LARGE_LIST:
   502  				arr := arr.(*array.LargeList)
   503  				gotOffsets = arr.Offsets()
   504  			case arrow.LIST_VIEW:
   505  				arr := arr.(*array.ListView)
   506  				gotOffsets = arr.Offsets()
   507  				gotSizes = arr.Sizes()
   508  			case arrow.LARGE_LIST_VIEW:
   509  				arr := arr.(*array.LargeListView)
   510  				gotOffsets = arr.Offsets()
   511  				gotSizes = arr.Sizes()
   512  			}
   513  
   514  			if !reflect.DeepEqual(gotOffsets, tt.offsets) {
   515  				t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
   516  			}
   517  
   518  			if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW {
   519  				if !reflect.DeepEqual(gotSizes, tt.sizes) {
   520  					t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
   521  				}
   522  			}
   523  
   524  			varr := arr.ListValues().(*array.Int32)
   525  			if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
   526  				t.Fatalf("got=%v, want=%v", got, want)
   527  			}
   528  
   529  			if got, want := arr.String(), `[[0 1 2] (null) [] [3 4 5 6]]`; got != want {
   530  				t.Fatalf("got=%q, want=%q", got, want)
   531  			}
   532  			assert.Equal(t, "[0,1,2]", arr.ValueStr(0))
   533  
   534  			sub := array.NewSlice(arr, 1, 4).(array.ListLike)
   535  			defer sub.Release()
   536  
   537  			if got, want := sub.String(), `[(null) [] [3 4 5 6]]`; got != want {
   538  				t.Fatalf("got=%q, want=%q", got, want)
   539  			}
   540  		})
   541  	}
   542  }
   543  
   544  func TestListViewArraySlice(t *testing.T) {
   545  	tests := []struct {
   546  		typeID  arrow.Type
   547  		offsets interface{}
   548  		sizes   interface{}
   549  		dt      arrow.DataType
   550  	}{
   551  		{arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
   552  		{arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
   553  	}
   554  
   555  	for _, tt := range tests {
   556  		t.Run(tt.typeID.String(), func(t *testing.T) {
   557  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   558  			defer pool.AssertSize(t, 0)
   559  
   560  			var (
   561  				vs      = []int32{-1, 3, 4, 5, 6, 0, 1, 2}
   562  				lengths = []int{3, 0, 0, 4}
   563  				isValid = []bool{true, false, true, true}
   564  			)
   565  
   566  			lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
   567  			defer lb.Release()
   568  			vb := lb.ValueBuilder().(*array.Int32Builder)
   569  			vb.Reserve(len(vs))
   570  
   571  			switch tt.typeID {
   572  			case arrow.LIST_VIEW:
   573  				lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
   574  			case arrow.LARGE_LIST_VIEW:
   575  				lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
   576  			}
   577  			for _, v := range vs {
   578  				vb.Append(v)
   579  			}
   580  
   581  			arr := lb.NewArray().(array.VarLenListLike)
   582  			defer arr.Release()
   583  
   584  			if got, want := arr.DataType().ID(), tt.typeID; got != want {
   585  				t.Fatalf("got=%v, want=%v", got, want)
   586  			}
   587  
   588  			if got, want := arr.Len(), len(isValid); got != want {
   589  				t.Fatalf("got=%d, want=%d", got, want)
   590  			}
   591  
   592  			for i := range lengths {
   593  				if got, want := arr.IsValid(i), isValid[i]; got != want {
   594  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   595  				}
   596  				if got, want := arr.IsNull(i), !isValid[i]; got != want {
   597  					t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
   598  				}
   599  			}
   600  
   601  			var gotOffsets, gotSizes interface{}
   602  			switch tt.typeID {
   603  			case arrow.LIST_VIEW:
   604  				arr := arr.(*array.ListView)
   605  				gotOffsets = arr.Offsets()
   606  				gotSizes = arr.Sizes()
   607  			case arrow.LARGE_LIST_VIEW:
   608  				arr := arr.(*array.LargeListView)
   609  				gotOffsets = arr.Offsets()
   610  				gotSizes = arr.Sizes()
   611  			}
   612  
   613  			if !reflect.DeepEqual(gotOffsets, tt.offsets) {
   614  				t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
   615  			}
   616  
   617  			if !reflect.DeepEqual(gotSizes, tt.sizes) {
   618  				t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
   619  			}
   620  
   621  			varr := arr.ListValues().(*array.Int32)
   622  			if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
   623  				t.Fatalf("got=%v, want=%v", got, want)
   624  			}
   625  
   626  			if got, want := arr.String(), `[[0 1 2] (null) [] [3 4 5 6]]`; got != want {
   627  				t.Fatalf("got=%q, want=%q", got, want)
   628  			}
   629  			assert.Equal(t, "[0,1,2]", arr.ValueStr(0))
   630  
   631  			sub := array.NewSlice(arr, 1, 4).(array.ListLike)
   632  			defer sub.Release()
   633  
   634  			if got, want := sub.String(), `[(null) [] [3 4 5 6]]`; got != want {
   635  				t.Fatalf("got=%q, want=%q", got, want)
   636  			}
   637  		})
   638  	}
   639  }
   640  
   641  func TestVarLenListLikeStringRoundTrip(t *testing.T) {
   642  	// 1. create array
   643  	mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
   644  	defer mem.AssertSize(t, 0)
   645  
   646  	builders := []array.VarLenListLikeBuilder{
   647  		array.NewListBuilder(mem, arrow.PrimitiveTypes.Int32),
   648  		array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   649  		array.NewLargeListBuilder(mem, arrow.PrimitiveTypes.Int32),
   650  		array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   651  	}
   652  
   653  	builders1 := []array.VarLenListLikeBuilder{
   654  		array.NewListBuilder(mem, arrow.PrimitiveTypes.Int32),
   655  		array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   656  		array.NewLargeListBuilder(mem, arrow.PrimitiveTypes.Int32),
   657  		array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   658  	}
   659  
   660  	for i, b := range builders {
   661  		defer b.Release()
   662  
   663  		vb := b.ValueBuilder().(*array.Int32Builder)
   664  
   665  		var values = [][]int32{
   666  			{0, 1, 2, 3, 4, 5, 6},
   667  			{1, 2, 3, 4, 5, 6, 7},
   668  			{2, 3, 4, 5, 6, 7, 8},
   669  			{3, 4, 5, 6, 7, 8, 9},
   670  		}
   671  		for _, value := range values {
   672  			b.AppendNull()
   673  			b.AppendWithSize(true, 2*len(value))
   674  			for _, el := range value {
   675  				vb.Append(el)
   676  				vb.AppendNull()
   677  			}
   678  			b.AppendWithSize(false, 0)
   679  		}
   680  
   681  		arr := b.NewArray()
   682  		defer arr.Release()
   683  
   684  		// 2. create array via AppendValueFromString
   685  		b1 := builders1[i]
   686  		defer b1.Release()
   687  
   688  		for i := 0; i < arr.Len(); i++ {
   689  			assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i)))
   690  		}
   691  
   692  		arr1 := b1.NewArray()
   693  		defer arr1.Release()
   694  
   695  		assert.True(t, array.Equal(arr, arr1))
   696  	}
   697  }
   698  
   699  // Test the string roun-trip for a list-view containing out-of-order offsets.
   700  func TestListViewStringRoundTrip(t *testing.T) {
   701  	// 1. create array
   702  	mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
   703  	defer mem.AssertSize(t, 0)
   704  
   705  	builders := []array.VarLenListLikeBuilder{
   706  		array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   707  		array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   708  	}
   709  
   710  	builders1 := []array.VarLenListLikeBuilder{
   711  		array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   712  		array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
   713  	}
   714  
   715  	for i, b := range builders {
   716  		defer b.Release()
   717  
   718  		switch lvb := b.(type) {
   719  		case *array.ListViewBuilder:
   720  			lvb.AppendDimensions(5, 3)
   721  			b.AppendNull()
   722  			lvb.AppendDimensions(0, 0)
   723  			lvb.AppendDimensions(1, 4)
   724  		case *array.LargeListViewBuilder:
   725  			lvb.AppendDimensions(5, 3)
   726  			b.AppendNull()
   727  			lvb.AppendDimensions(0, 0)
   728  			lvb.AppendDimensions(1, 4)
   729  		}
   730  
   731  		vb := b.ValueBuilder().(*array.Int32Builder)
   732  
   733  		vs := []int32{-1, 3, 4, 5, 6, 0, 1, 2}
   734  		isValid := []bool{false, true, true, true, true, true, true, true}
   735  		vb.Reserve(len(vs))
   736  		vb.AppendValues(vs, isValid)
   737  
   738  		arr := b.NewArray()
   739  		defer arr.Release()
   740  
   741  		// 2. create array via AppendValueFromString
   742  		b1 := builders1[i]
   743  		defer b1.Release()
   744  
   745  		for i := 0; i < arr.Len(); i++ {
   746  			assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i)))
   747  		}
   748  
   749  		arr1 := b1.NewArray()
   750  		defer arr1.Release()
   751  
   752  		assert.True(t, array.Equal(arr, arr1))
   753  	}
   754  }
   755  
   756  func TestRangeOfValuesUsed(t *testing.T) {
   757  	tests := []struct {
   758  		typeID arrow.Type
   759  		dt     arrow.DataType
   760  	}{
   761  		{arrow.LIST, arrow.ListOf(arrow.PrimitiveTypes.Int16)},
   762  		{arrow.LARGE_LIST, arrow.LargeListOf(arrow.PrimitiveTypes.Int16)},
   763  		{arrow.LIST_VIEW, arrow.ListViewOf(arrow.PrimitiveTypes.Int16)},
   764  		{arrow.LARGE_LIST_VIEW, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int16)},
   765  	}
   766  	for _, tt := range tests {
   767  		t.Run(tt.typeID.String(), func(t *testing.T) {
   768  			pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
   769  			defer pool.AssertSize(t, 0)
   770  
   771  			isListView := tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW
   772  
   773  			bldr := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
   774  			defer bldr.Release()
   775  
   776  			var arr array.VarLenListLike
   777  
   778  			// Empty array
   779  			arr = bldr.NewArray().(array.VarLenListLike)
   780  			defer arr.Release()
   781  			offset, len := array.RangeOfValuesUsed(arr)
   782  			assert.Equal(t, 0, offset)
   783  			assert.Equal(t, 0, len)
   784  
   785  			// List-like array with only nulls
   786  			bldr.AppendNulls(3)
   787  			arr = bldr.NewArray().(array.VarLenListLike)
   788  			defer arr.Release()
   789  			offset, len = array.RangeOfValuesUsed(arr)
   790  			assert.Equal(t, 0, offset)
   791  			assert.Equal(t, 0, len)
   792  
   793  			// Array with nulls and non-nulls (starting at a non-zero offset)
   794  			vb := bldr.ValueBuilder().(*array.Int16Builder)
   795  			vb.Append(-2)
   796  			vb.Append(-1)
   797  			bldr.AppendWithSize(false, 0)
   798  			bldr.AppendWithSize(true, 2)
   799  			vb.Append(0)
   800  			vb.Append(1)
   801  			bldr.AppendWithSize(true, 3)
   802  			vb.Append(2)
   803  			vb.Append(3)
   804  			vb.Append(4)
   805  			if isListView {
   806  				vb.Append(10)
   807  				vb.Append(11)
   808  			}
   809  			arr = bldr.NewArray().(array.VarLenListLike)
   810  			defer arr.Release()
   811  			offset, len = array.RangeOfValuesUsed(arr)
   812  			assert.Equal(t, 2, offset)
   813  			assert.Equal(t, 5, len)
   814  
   815  			// Overlapping list-views
   816  			// [null, [0, 1, 2, 3, 4, 5], [1, 2], null, [4], null, null]
   817  			vb = bldr.ValueBuilder().(*array.Int16Builder)
   818  			vb.Append(-2)
   819  			vb.Append(-1)
   820  			bldr.AppendWithSize(false, 0)
   821  			if isListView {
   822  				bldr.AppendWithSize(true, 6)
   823  				vb.Append(0)
   824  				bldr.AppendWithSize(true, 2)
   825  				vb.Append(1)
   826  				vb.Append(2)
   827  				vb.Append(3)
   828  				bldr.AppendWithSize(false, 0)
   829  				bldr.AppendWithSize(true, 1)
   830  				vb.Append(4)
   831  				vb.Append(5)
   832  				// -- used range ends here --
   833  				vb.Append(10)
   834  				vb.Append(11)
   835  			} else {
   836  				bldr.AppendWithSize(true, 6)
   837  				vb.Append(0)
   838  				vb.Append(1)
   839  				vb.Append(2)
   840  				vb.Append(3)
   841  				vb.Append(4)
   842  				vb.Append(5)
   843  				bldr.AppendWithSize(true, 2)
   844  				vb.Append(1)
   845  				vb.Append(2)
   846  				bldr.AppendWithSize(false, 0)
   847  				bldr.AppendWithSize(true, 1)
   848  				vb.Append(4)
   849  			}
   850  			bldr.AppendNulls(2)
   851  			arr = bldr.NewArray().(array.VarLenListLike)
   852  			defer arr.Release()
   853  
   854  			// Check the range
   855  			offset, len = array.RangeOfValuesUsed(arr)
   856  			assert.Equal(t, 2, offset)
   857  			if isListView {
   858  				assert.Equal(t, 6, len)
   859  			} else {
   860  				assert.Equal(t, 9, len)
   861  			}
   862  		})
   863  	}
   864  }