blob: 3081160ec71f98af90ccc1414c5d30a201c90905 [file] [log] [blame]
// 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.
using System;
using System.Runtime.InteropServices;
using Apache.Arrow.C;
using Apache.Arrow.Types;
using Xunit;
namespace Apache.Arrow.Tests
{
public class CDataInterfaceDataTests
{
private IArrowArray GetTestArray()
{
var builder = new StringArray.Builder();
builder.Append("hello");
builder.Append("world");
builder.AppendNull();
builder.Append("foo");
builder.Append("bar");
return builder.Build();
}
[Fact]
public unsafe void InitializeArrayZeroed()
{
CArrowArray* cArray = CArrowArray.Create();
Assert.Equal(0, cArray->length);
Assert.Equal(0, cArray->null_count);
Assert.Equal(0, cArray->offset);
Assert.Equal(0, cArray->n_buffers);
Assert.Equal(0, cArray->n_children);
Assert.True(cArray->buffers == null);
Assert.True(cArray->children == null);
Assert.True(cArray->dictionary == null);
Assert.True(cArray->release == default);
Assert.True(cArray->private_data == null);
CArrowArray.Free(cArray);
}
[Fact]
public unsafe void CallsReleaseForValid()
{
IArrowArray array = GetTestArray();
CArrowArray* cArray = CArrowArray.Create();
CArrowArrayExporter.ExportArray(array, cArray);
Assert.False(cArray->release == default);
CArrowArrayImporter.ImportArray(cArray, array.Data.DataType).Dispose();
Assert.True(cArray->release == default);
CArrowArray.Free(cArray);
}
#if NET5_0_OR_GREATER
[Fact]
public unsafe void CallsReleaseForInvalid()
{
// Make sure we call release callback, even if the imported array is invalid.
CArrowArray* cArray = CArrowArray.Create();
bool wasCalled = false;
var releaseCallback = (CArrowArray* cArray) =>
{
wasCalled = true;
cArray->release = default;
};
cArray->release = (delegate* unmanaged<CArrowArray*, void>)Marshal.GetFunctionPointerForDelegate(
releaseCallback);
Assert.Throws<InvalidOperationException>(() =>
{
CArrowArrayImporter.ImportArray(cArray, GetTestArray().Data.DataType);
});
Assert.True(wasCalled);
CArrowArray.Free(cArray);
GC.KeepAlive(releaseCallback);
}
#endif
[Fact]
public unsafe void RoundTripInt32ArrayWithOffset()
{
Int32Array array = new Int32Array.Builder()
.AppendRange(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })
.Build();
IArrowArray sliced = array.Slice(2, 6);
CArrowArray* cArray = CArrowArray.Create();
CArrowArrayExporter.ExportArray(sliced, cArray);
using (var importedSlice = (Int32Array)CArrowArrayImporter.ImportArray(cArray, array.Data.DataType))
{
Assert.Equal(6, importedSlice.Length);
Assert.Equal(2, importedSlice.Offset);
Assert.Equal(2, importedSlice.GetValue(0));
}
CArrowArray.Free(cArray);
}
[Fact]
public unsafe void ExportRecordBatch_LargerThan2GB_Succeeds()
{
RecordBatch GetTestRecordBatch()
{
const int rows = 50_000;
var doubles = new double[rows];
for (var i = 0; i < rows; ++i)
{
doubles[i] = i * 1.1;
}
var batchBuilder = new RecordBatch.Builder();
for (var i = 0; i < 10_000; i++)
{
batchBuilder.Append($"doubles{i}", true, ab => ab.Double(b => b.Append(doubles)));
}
return batchBuilder.Build();
}
RecordBatch batch = GetTestRecordBatch();
CArrowArray* cArray = CArrowArray.Create();
CArrowArrayExporter.ExportRecordBatch(batch, cArray);
CArrowArray.Free(cArray);
}
}
}