Skip to content

Commit 1724785

Browse files
bkietzpaleolimbot
andauthored
feat: Add ArrowArray and ArrowArrayStream C++ iterators (#404)
All of this *should* be c++11 ```diff - auto arrow_array = ImportArray(&array, large_utf8()); - ARROW_EXPECT_OK(arrow_array); - - auto builder = LargeStringBuilder(); - ARROW_EXPECT_OK(builder.Append("1234")); - ARROW_EXPECT_OK(builder.AppendNulls(2)); - ARROW_EXPECT_OK(builder.Append("56789")); - ARROW_EXPECT_OK(builder.AppendEmptyValue()); - auto expected_array = builder.Finish(); - - EXPECT_TRUE(arrow_array.ValueUnsafe()->Equals(expected_array.ValueUnsafe())); + EXPECT_THAT(nanoarrow::ViewAsBytes<64>(&array), + ElementsAre("1234"_v, kNull, kNull, "56789"_v, ""_v)); ``` fixes #403 --------- Co-authored-by: Dewey Dunnington <[email protected]>
1 parent e7c47fa commit 1724785

File tree

8 files changed

+664
-104
lines changed

8 files changed

+664
-104
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ __pycache__
3030

3131
# meson subprojects
3232
subprojects
33+
34+
compile_commands.json

CMakeLists.txt

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ if(NANOARROW_BUNDLE)
9191
file(READ src/nanoarrow/nanoarrow_testing.hpp SRC_FILE_CONTENTS)
9292
file(WRITE ${NANOARROW_TESTING_HPP_TEMP} "${SRC_FILE_CONTENTS}")
9393

94+
# Copy nanoarrow_gtest_util.hpp
95+
set(NANOARROW_GTEST_UTIL_HPP_TEMP
96+
${CMAKE_BINARY_DIR}/amalgamation/nanoarrow/nanoarrow_gtest_util.hpp)
97+
file(READ src/nanoarrow/nanoarrow_gtest_util.hpp SRC_FILE_CONTENTS)
98+
file(WRITE ${NANOARROW_GTEST_UTIL_HPP_TEMP} "${SRC_FILE_CONTENTS}")
99+
94100
# Combine all source files into amalgamation/nanoarrow.c in the build directory
95101
if(NANOARROW_BUNDLE_AS_CPP)
96102
set(NANOARROW_C_TEMP ${CMAKE_BINARY_DIR}/amalgamation/nanoarrow/nanoarrow.cc)
@@ -116,8 +122,12 @@ if(NANOARROW_BUNDLE)
116122
endif()
117123

118124
# Install the amalgamated header and source
119-
install(FILES ${NANOARROW_H_TEMP} ${NANOARROW_C_TEMP} ${NANOARROW_HPP_TEMP}
120-
${NANOARROW_TESTING_HPP_TEMP} DESTINATION ".")
125+
install(FILES ${NANOARROW_H_TEMP}
126+
${NANOARROW_C_TEMP}
127+
${NANOARROW_HPP_TEMP}
128+
${NANOARROW_GTEST_UTIL_HPP_TEMP}
129+
${NANOARROW_TESTING_HPP_TEMP}
130+
DESTINATION ".")
121131
else()
122132
add_library(nanoarrow src/nanoarrow/array.c src/nanoarrow/schema.c
123133
src/nanoarrow/array_stream.c src/nanoarrow/utils.c)
@@ -259,12 +269,25 @@ if(NANOARROW_BUILD_TESTS)
259269
target_link_options(nanoarrow PUBLIC --coverage)
260270
endif()
261271

262-
target_link_libraries(utils_test nanoarrow gtest_main ${NANOARROW_ARROW_TARGET})
272+
target_link_libraries(utils_test
273+
nanoarrow
274+
gtest_main
275+
gmock_main
276+
${NANOARROW_ARROW_TARGET}
277+
nlohmann_json::nlohmann_json)
263278
target_link_libraries(buffer_test nanoarrow gtest_main)
264-
target_link_libraries(array_test nanoarrow gtest_main ${NANOARROW_ARROW_TARGET})
279+
target_link_libraries(array_test
280+
nanoarrow
281+
gtest_main
282+
gmock_main
283+
${NANOARROW_ARROW_TARGET})
265284
target_link_libraries(schema_test nanoarrow gtest_main ${NANOARROW_ARROW_TARGET})
266-
target_link_libraries(array_stream_test nanoarrow gtest_main)
267-
target_link_libraries(nanoarrow_hpp_test nanoarrow gtest_main)
285+
target_link_libraries(array_stream_test nanoarrow gtest_main gmock_main)
286+
target_link_libraries(nanoarrow_hpp_test
287+
nanoarrow
288+
gtest_main
289+
gmock_main
290+
nlohmann_json::nlohmann_json)
268291
target_link_libraries(nanoarrow_testing_test nanoarrow gtest_main
269292
nlohmann_json::nlohmann_json)
270293
target_link_libraries(c_data_integration_test nanoarrow nanoarrow_c_data_integration

src/nanoarrow/array_stream_test.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
#include <gmock/gmock-matchers.h>
1819
#include <gtest/gtest.h>
1920

20-
#include "nanoarrow/nanoarrow.h"
21+
#include "nanoarrow/nanoarrow.hpp"
22+
23+
using testing::ElementsAre;
2124

2225
TEST(ArrayStreamTest, ArrayStreamTestBasic) {
2326
struct ArrowArrayStream array_stream;
@@ -44,16 +47,14 @@ TEST(ArrayStreamTest, ArrayStreamTestBasic) {
4447
EXPECT_STREQ(schema_copy.format, "i");
4548
ArrowSchemaRelease(&schema_copy);
4649

47-
struct ArrowArray array_copy;
48-
EXPECT_EQ(ArrowArrayStreamGetNext(&array_stream, &array_copy, nullptr), NANOARROW_OK);
49-
EXPECT_EQ(array_copy.length, 1);
50-
EXPECT_EQ(array_copy.n_buffers, 2);
51-
ArrowArrayRelease(&array_copy);
52-
53-
EXPECT_EQ(ArrowArrayStreamGetNext(&array_stream, &array_copy, nullptr), NANOARROW_OK);
54-
EXPECT_EQ(array_copy.release, nullptr);
55-
56-
EXPECT_EQ(array_stream.get_last_error(&array_stream), nullptr);
50+
nanoarrow::ViewArrayStream array_stream_view(&array_stream);
51+
for (ArrowArray& array : array_stream_view) {
52+
EXPECT_THAT(nanoarrow::ViewArrayAs<int32_t>(&array), ElementsAre(123));
53+
EXPECT_EQ(array.n_buffers, 2);
54+
}
55+
EXPECT_EQ(array_stream_view.count(), 1);
56+
EXPECT_EQ(array_stream_view.code(), NANOARROW_OK);
57+
EXPECT_STREQ(array_stream_view.error()->message, "");
5758

5859
ArrowArrayStreamRelease(&array_stream);
5960
EXPECT_EQ(array_stream.release, nullptr);

src/nanoarrow/array_test.cc

Lines changed: 19 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
#include <gmock/gmock-matchers.h>
1819
#include <gtest/gtest.h>
1920
#include <cmath>
21+
#include <cstdint>
2022

2123
#include <arrow/array.h>
2224
#include <arrow/array/builder_binary.h>
@@ -29,9 +31,11 @@
2931
#include <arrow/compare.h>
3032
#include <arrow/util/decimal.h>
3133

32-
#include "nanoarrow/nanoarrow.h"
34+
#include "nanoarrow/nanoarrow.hpp"
3335

3436
using namespace arrow;
37+
using nanoarrow::NA;
38+
using testing::ElementsAre;
3539

3640
// Lightweight versions of ArrowTesting's ARROW_EXPECT_OK. This
3741
// version accomplishes the task of making sure the status message
@@ -603,20 +607,9 @@ TEST(ArrayTest, ArrayTestAppendToUInt32Array) {
603607

604608
EXPECT_EQ(array.length, 2);
605609
EXPECT_EQ(array.null_count, 0);
606-
auto data_buffer = reinterpret_cast<const uint32_t*>(array.buffers[1]);
607610
EXPECT_EQ(array.buffers[0], nullptr);
608-
EXPECT_EQ(data_buffer[0], 1);
609-
EXPECT_EQ(data_buffer[1], 3);
610-
611-
auto arrow_array = ImportArray(&array, uint32());
612-
ARROW_EXPECT_OK(arrow_array);
613-
614-
auto builder = UInt32Builder();
615-
ARROW_EXPECT_OK(builder.Append(1));
616-
ARROW_EXPECT_OK(builder.Append(3));
617-
auto expected_array = builder.Finish();
618-
619-
EXPECT_TRUE(arrow_array.ValueUnsafe()->Equals(expected_array.ValueUnsafe()));
611+
EXPECT_THAT(nanoarrow::ViewArrayAs<uint32_t>(&array), ElementsAre(1, 3));
612+
ArrowArrayRelease(&array);
620613
}
621614

622615
TEST(ArrayTest, ArrayTestAppendToUInt16Array) {
@@ -806,24 +799,8 @@ TEST(ArrayTest, ArrayTestAppendToBoolArray) {
806799

807800
EXPECT_EQ(array.length, 4);
808801
EXPECT_EQ(array.null_count, 2);
809-
auto validity_buffer = reinterpret_cast<const uint8_t*>(array.buffers[0]);
810-
auto data_buffer = reinterpret_cast<const uint8_t*>(array.buffers[1]);
811-
EXPECT_EQ(validity_buffer[0], 0x01 | 0x08);
812-
EXPECT_EQ(ArrowBitGet(data_buffer, 0), 0x01);
813-
EXPECT_EQ(ArrowBitGet(data_buffer, 1), 0x00);
814-
EXPECT_EQ(ArrowBitGet(data_buffer, 2), 0x00);
815-
EXPECT_EQ(ArrowBitGet(data_buffer, 3), 0x00);
816-
817-
auto arrow_array = ImportArray(&array, boolean());
818-
ARROW_EXPECT_OK(arrow_array);
819-
820-
auto builder = BooleanBuilder();
821-
ARROW_EXPECT_OK(builder.Append(true));
822-
ARROW_EXPECT_OK(builder.AppendNulls(2));
823-
ARROW_EXPECT_OK(builder.Append(false));
824-
auto expected_array = builder.Finish();
825-
826-
EXPECT_TRUE(arrow_array.ValueUnsafe()->Equals(expected_array.ValueUnsafe()));
802+
EXPECT_THAT(nanoarrow::ViewArrayAs<bool>(&array), ElementsAre(true, NA, NA, false));
803+
ArrowArrayRelease(&array);
827804
}
828805

829806
TEST(ArrayTest, ArrayTestAppendToLargeStringArray) {
@@ -855,17 +832,9 @@ TEST(ArrayTest, ArrayTestAppendToLargeStringArray) {
855832
EXPECT_EQ(offset_buffer[4], 9);
856833
EXPECT_EQ(memcmp(data_buffer, "123456789", 9), 0);
857834

858-
auto arrow_array = ImportArray(&array, large_utf8());
859-
ARROW_EXPECT_OK(arrow_array);
860-
861-
auto builder = LargeStringBuilder();
862-
ARROW_EXPECT_OK(builder.Append("1234"));
863-
ARROW_EXPECT_OK(builder.AppendNulls(2));
864-
ARROW_EXPECT_OK(builder.Append("56789"));
865-
ARROW_EXPECT_OK(builder.AppendEmptyValue());
866-
auto expected_array = builder.Finish();
867-
868-
EXPECT_TRUE(arrow_array.ValueUnsafe()->Equals(expected_array.ValueUnsafe()));
835+
EXPECT_THAT(nanoarrow::ViewArrayAsBytes<64>(&array),
836+
ElementsAre("1234"_v, NA, NA, "56789"_v, ""_v));
837+
ArrowArrayRelease(&array);
869838
}
870839

871840
TEST(ArrayTest, ArrayTestAppendToFixedSizeBinaryArray) {
@@ -899,18 +868,10 @@ TEST(ArrayTest, ArrayTestAppendToFixedSizeBinaryArray) {
899868
'9', '0', 0x00, 0x00, 0x00, 0x00, 0x00};
900869
EXPECT_EQ(memcmp(data_buffer, expected_data, 25), 0);
901870

902-
auto arrow_array = ImportArray(&array, &schema);
903-
ARROW_EXPECT_OK(arrow_array);
904-
905-
auto builder = FixedSizeBinaryBuilder(fixed_size_binary(5));
906-
ARROW_EXPECT_OK(builder.Append("12345"));
907-
ARROW_EXPECT_OK(builder.AppendNulls(2));
908-
ARROW_EXPECT_OK(builder.Append("67890"));
909-
ARROW_EXPECT_OK(builder.AppendEmptyValue());
910-
auto expected_array = builder.Finish();
911-
ARROW_EXPECT_OK(expected_array);
912-
913-
EXPECT_TRUE(arrow_array.ValueUnsafe()->Equals(expected_array.ValueUnsafe()));
871+
EXPECT_THAT(nanoarrow::ViewArrayAsFixedSizeBytes(&array, 5),
872+
ElementsAre("12345"_v, NA, NA, "67890"_v, "\0\0\0\0\0"_v));
873+
ArrowArrayRelease(&array);
874+
ArrowSchemaRelease(&schema);
914875
}
915876

916877
TEST(ArrayTest, ArrayTestAppendToBinaryArrayErrors) {
@@ -932,7 +893,7 @@ TEST(ArrayTest, ArrayTestAppendToIntervalArrayYearMonth) {
932893
const int32_t months = 42;
933894
struct ArrowInterval interval;
934895
ArrowIntervalInit(&interval, ArrowType::NANOARROW_TYPE_INTERVAL_MONTHS);
935-
interval.months = 42;
896+
interval.months = months;
936897

937898
ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_INTERVAL_MONTHS), NANOARROW_OK);
938899
EXPECT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
@@ -943,14 +904,8 @@ TEST(ArrayTest, ArrayTestAppendToIntervalArrayYearMonth) {
943904
EXPECT_EQ(array.length, 2);
944905
EXPECT_EQ(array.null_count, 1);
945906

946-
auto data_buffer = reinterpret_cast<const int32_t*>(array.buffers[1]);
947-
EXPECT_EQ(data_buffer[0], months);
948-
949-
auto arrow_array = ImportArray(&array, month_interval());
950-
ARROW_EXPECT_OK(arrow_array);
951-
952-
// TODO: arrow does not have a builder for MonthIntervals
953-
// so no comparison is done after creating the array
907+
EXPECT_THAT(nanoarrow::ViewArrayAs<int32_t>(&array), ElementsAre(months, NA));
908+
ArrowArrayRelease(&array);
954909
}
955910

956911
TEST(ArrayTest, ArrayTestAppendToIntervalArrayDayTime) {

0 commit comments

Comments
 (0)