From b33186b788992b2f3e2741dbd45ebb69c8926c18 Mon Sep 17 00:00:00 2001 From: niranda perera Date: Tue, 18 Aug 2026 11:07:22 -0700 Subject: [PATCH 1/5] Add lists_column_initializer and opt-in harness failing-current helper Expose scoped fail_on_current_device_resource_use() on BaseFixtureWithHarness, add recursive list initializers for explicit stream/mr nesting, and port list gather test construction sites without changing gather production APIs. --- cpp/include/cudf_test/base_fixture.hpp | 15 + cpp/include/cudf_test/column_wrapper.hpp | 383 +++++++--- cpp/tests/copying/gather_list_tests.cpp | 441 +++++++---- .../copying/segmented_gather_list_tests.cpp | 696 +++++++++++------- .../utilities/memory_resource_utilities.cpp | 20 + .../lists_column_wrapper_tests.cpp | 68 ++ 6 files changed, 1116 insertions(+), 507 deletions(-) diff --git a/cpp/include/cudf_test/base_fixture.hpp b/cpp/include/cudf_test/base_fixture.hpp index 003955369001..793260e47923 100644 --- a/cpp/include/cudf_test/base_fixture.hpp +++ b/cpp/include/cudf_test/base_fixture.hpp @@ -47,6 +47,8 @@ class BaseFixture : public ::testing::Test { * * Each test instantiates a fresh harness. Tests should construct results with `resources()`. * `TearDown` asserts that no output or temporary allocations remain live. + * Call `fail_on_current_device_resource_use()` in test scopes that must reject accidental + * current-device-resource allocations. */ struct BaseFixtureWithHarness : public BaseFixture { /** @@ -66,6 +68,19 @@ struct BaseFixtureWithHarness : public BaseFixture { */ cudf::memory_resources resources() { return _harness.resources(); } + /** + * @brief Install a scoped failing current-device resource. + * + * While the returned object is alive, allocations from the current device resource fail. + * Destroy it (or let it leave scope) to restore the previous current resource. + * + * @return Scoped guard around the failing current-device resource + */ + [[nodiscard]] scoped_current_device_resource fail_on_current_device_resource_use() + { + return _harness.fail_on_current_device_resource_use(); + } + protected: memory_resource_test_harness _harness{mr()}; }; diff --git a/cpp/include/cudf_test/column_wrapper.hpp b/cpp/include/cudf_test/column_wrapper.hpp index e749a086cd6b..8ac30e57b0f0 100644 --- a/cpp/include/cudf_test/column_wrapper.hpp +++ b/cpp/include/cudf_test/column_wrapper.hpp @@ -35,9 +35,12 @@ #include #include +#include +#include #include #include #include +#include #include namespace CUDF_EXPORT cudf { @@ -337,8 +340,175 @@ auto make_chars_and_offsets(StringsIterator begin, StringsIterator end, Validity } return std::pair(std::move(chars), std::move(offsets)); }; + } // namespace detail +// Forward declaration for lists_column_initializer::build +template +class lists_column_wrapper; + +/** + * @brief Host-side recursive initializer tree for constructing list columns with an + * explicit stream and memory resources at every nesting level. + * + * Prefer this over brace-nested `lists_column_wrapper` constructions that pass + * `stream`/`mr` only at the outer level, which leave brace-constructed children on + * the default test resources. + * + * Example: + * @code{.cpp} + * using Init = cudf::test::lists_column_initializer; + * // List: [{1, 2}, {3}] + * lists_column_wrapper col{Init{{{1, 2}, {3}}}, stream, mr}; + * @endcode + * + * Leaf and nested constructors accept the existing validity iterators + * (`valids`, `null_at(...)`, etc.) and materialize them into owned storage. + * + * @tparam T Host leaf element type (e.g. `int32_t` or `std::string`) + */ +template +class lists_column_initializer { + public: + /** + * @brief Construct an empty leaf. Avoids ambiguity between the leaf and nested + * empty `initializer_list` constructors. + */ + lists_column_initializer() = default; + + /** + * @brief Construct a leaf from scalar values. + * + * @param values Leaf element values + */ + lists_column_initializer(std::initializer_list values) : values_{values} {} + + /** + * @brief Construct a leaf from scalar values and a validity iterator. + * + * @tparam ValidityIterator Iterator convertible to `bool` + * @param values Leaf element values + * @param v Validity iterator over `values.size()` elements + */ + template + lists_column_initializer(std::initializer_list values, ValidityIterator v) : values_{values} + { + value_validity_.reserve(values_.size()); + for (std::size_t i = 0; i < values_.size(); ++i) { + value_validity_.push_back(static_cast(*v++)); + } + } + + /** + * @brief Construct a nested node from child initializers. + * + * This constructor is a template so the non-template leaf + * `initializer_list` constructor is preferred for scalar lists such as + * `{1, 2, 3}`. Otherwise both overloads are non-templates and constructing + * `Init` from an `int` via the nested overload recurses until the stack + * overflows. + * + * @param children Child list initializers + */ + template + lists_column_initializer(std::initializer_list children) + requires(std::is_same_v) + : children_{children.begin(), children.end()}, nested_{true} + { + } + + /** + * @brief Construct a nested node from child initializers and a row-validity iterator. + * + * @tparam ValidityIterator Iterator convertible to `bool` + * @param children Child list initializers + * @param v Validity iterator over `children.size()` rows + */ + template + lists_column_initializer(std::initializer_list children, ValidityIterator v) + requires(std::is_same_v) + : nested_{true} + { + children_.reserve(children.size()); + for (auto const& child : children) { + if (static_cast(*v++)) { + children_.push_back(child); + } else { + children_.emplace_back(); + children_.back().valid_ = false; + } + } + } + + /** + * @brief True if this node holds nested child initializers rather than leaf values. + * @return Whether this node is nested + */ + [[nodiscard]] bool nested() const { return nested_; } + /** + * @brief True if this row is valid (non-null) in its parent list. + * @return Whether this row is valid + */ + [[nodiscard]] bool valid() const { return valid_; } + /** + * @brief Leaf element values when `nested()` is false. + * @return Reference to the leaf values + */ + [[nodiscard]] auto const& values() const { return values_; } + /** + * @brief Per-element validity for leaf values; empty when all leaf values are valid. + * @return Reference to the leaf validity mask + */ + [[nodiscard]] auto const& value_validity() const { return value_validity_; } + /** + * @brief Child initializers when `nested()` is true. + * @return Reference to the child initializers + */ + [[nodiscard]] auto const& children() const { return children_; } + + /** + * @brief Recursively build child list wrappers and row validity for a nested node. + * + * Each valid child is allocated with the provided `stream` and `mr`. Null children are + * represented as default-constructed wrappers (skipped during concatenate). + * + * @tparam ElementT List wrapper element type + * @tparam SourceElementT Source type used by the list wrapper + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate child columns + * @return Child wrappers and an empty validity vector when all rows are valid, + * otherwise a validity mask matching `children().size()` + */ + template + [[nodiscard]] std::pair>, + std::vector> + build(rmm::cuda_stream_view stream, cudf::memory_resources mr) const + { + std::vector> children; + std::vector validity; + children.reserve(children_.size()); + validity.reserve(children_.size()); + bool any_null = false; + for (auto const& child : children_) { + any_null = any_null || !child.valid(); + validity.push_back(child.valid()); + if (child.valid()) { + children.emplace_back(child, stream, mr); + } else { + children.emplace_back(); // null rows are skipped during concatenate + } + } + return {std::move(children), any_null ? std::move(validity) : std::vector{}}; + } + + private: + std::vector values_; + std::vector value_validity_; + std::vector children_; + bool nested_{false}; + bool valid_{true}; +}; + /** * @brief `column_wrapper` derived class for wrapping columns of fixed-width * elements. @@ -1482,191 +1652,181 @@ class lists_column_wrapper : public detail::column_wrapper { operator lists_column_view() const { return cudf::lists_column_view{wrapped->view()}; } /** - * @brief Construct a lists column containing a single list of fixed-width - * type from an initializer list of values. + * @brief Host-side leaf element type (`std::string` for string lists, else `SourceElementT`). + */ + using host_element_t = + std::conditional_t, std::string, SourceElementT>; + /** + * @brief Column wrapper type used to materialize leaf list contents. + */ + using leaf_wrapper_t = std::conditional_t, + strings_column_wrapper, + fixed_width_column_wrapper>; + + /** + * @brief Construct a lists column containing a single list from an initializer + * list of values. * * Example: * @code{.cpp} - * Creates a LIST column with 1 list composed of 2 total integers - * [{0, 1}] + * // Creates a LIST column with 1 list composed of 2 total integers + * // [{0, 1}] * lists_column_wrapper l{0, 1}; * @endcode * + * These leaf constructors are templates (via `requires`) so that the non-template + * nested `initializer_list` constructor is preferred for + * ambiguous cases such as `lists_column_wrapper{{}, {}}`. + * * @param elements The list of elements * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template ()>* = nullptr> + template lists_column_wrapper(std::initializer_list elements, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + requires(cudf::is_fixed_width()) : column_wrapper{} { build_from_non_nested( - cudf::test::fixed_width_column_wrapper(elements, stream, mr).release(), - stream, - mr); + fixed_width_column_wrapper(elements, stream, mr).release(), stream, mr); } /** - * @brief Construct a lists column containing a single list of fixed-width - * type from an iterator range. + * @brief Construct a lists column containing a single list of strings. * * Example: * @code{.cpp} - * // Creates a LIST column with 1 list composed of 5 total integers - * auto elements = make_counting_transform_iterator(0, [](auto i){return i*2;}); - * // [{0, 1, 2, 3, 4}] - * lists_column_wrapper l(elements, elements+5); + * // Creates a LIST column with 1 list composed of 2 total strings + * // [{"abc", "def"}] + * lists_column_wrapper s{"abc", "def"}; * @endcode * - * @param begin Beginning of the sequence - * @param end End of the sequence + * @param elements The list of strings * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template ()>* = nullptr> - lists_column_wrapper(InputIterator begin, - InputIterator end, + template + lists_column_wrapper(std::initializer_list elements, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + requires(std::is_same_v) : column_wrapper{} { - build_from_non_nested( - cudf::test::fixed_width_column_wrapper(begin, end, stream, mr).release(), - stream, - mr); + build_from_non_nested(strings_column_wrapper(elements, stream, mr).release(), stream, mr); } /** - * @brief Construct a lists column containing a single list of fixed-width - * type from an initializer list of values and a validity iterator. + * @brief Construct a lists column containing a single list from an iterator range. * * Example: * @code{.cpp} - * // Creates a LIST column with 1 lists composed of 2 total integers - * auto validity = make_counting_transform_iterator(0, [](auto i){return i%2;}); - * // [{0, NULL}] - * lists_column_wrapper l{{0, 1}, validity}; + * // Creates a LIST column with 1 list composed of 5 total integers + * auto elements = make_counting_transform_iterator(0, [](auto i){return i*2;}); + * // [{0, 1, 2, 3, 4}] + * lists_column_wrapper l(elements, elements+5); * @endcode * - * @param elements The list of elements - * @param v The validity iterator + * @param begin Beginning of the sequence + * @param end End of the sequence * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template ()>* = nullptr> - lists_column_wrapper(std::initializer_list elements, - ValidityIterator v, + template + lists_column_wrapper(InputIterator begin, + InputIterator end, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { - build_from_non_nested( - cudf::test::fixed_width_column_wrapper(elements, v, stream, mr).release(), - stream, - mr); + build_from_non_nested(leaf_wrapper_t(begin, end, stream, mr).release(), stream, mr); } /** - * @brief Construct a lists column containing a single list of fixed-width - * type from an iterator range and a validity iterator. + * @brief Construct a lists column containing a single list from an initializer + * list of values and a validity iterator. * * Example: * @code{.cpp} - * // Creates a LIST column with 1 lists composed of 5 total integers - * auto elements = make_counting_transform_iterator(0, [](auto i){return i*2;}); + * // Creates a LIST column with 1 list composed of 2 total integers * auto validity = make_counting_transform_iterator(0, [](auto i){return i%2;}); - * // [{0, NULL, 2, NULL, 4}] - * lists_column_wrapper l(elements, elements+5, validity); + * // [{0, NULL}] + * lists_column_wrapper l{{0, 1}, validity}; * @endcode * - * @param begin Beginning of the sequence - * @param end End of the sequence + * @param elements The list of elements * @param v The validity iterator * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template ()>* = nullptr> - lists_column_wrapper(InputIterator begin, - InputIterator end, + template + lists_column_wrapper(std::initializer_list elements, ValidityIterator v, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + requires(cudf::is_fixed_width()) : column_wrapper{} { build_from_non_nested( - cudf::test::fixed_width_column_wrapper(begin, end, v, stream, mr) - .release(), - stream, - mr); + fixed_width_column_wrapper(elements, v, stream, mr).release(), stream, mr); } /** - * @brief Construct a lists column containing a single list of strings - * from an initializer list of values. + * @brief Construct a lists column containing a single list of strings and a + * validity iterator. * * Example: * @code{.cpp} - * // Creates a LIST column with 1 list composed of 2 total strings - * // [{"abc", "def"}] - * lists_column_wrapper l{"abc", "def"}; + * auto validity = make_counting_transform_iterator(0, [](auto i){return i%2;}); + * // [{"abc", NULL}] + * lists_column_wrapper l{{"abc", "def"}, validity}; * @endcode * - * @param elements The list of elements + * @param elements The list of strings + * @param v The validity iterator * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template >* = nullptr> + template lists_column_wrapper(std::initializer_list elements, + ValidityIterator v, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + requires(std::is_same_v) : column_wrapper{} { - build_from_non_nested( - cudf::test::strings_column_wrapper(elements.begin(), elements.end(), stream, mr).release(), - stream, - mr); + build_from_non_nested(strings_column_wrapper(elements, v, stream, mr).release(), stream, mr); } /** - * @brief Construct a lists column containing a single list of strings - * from an initializer list of values and a validity iterator. + * @brief Construct a lists column containing a single list from an iterator + * range and a validity iterator. * * Example: * @code{.cpp} - * // Creates a LIST column with 1 list composed of 2 total strings + * // Creates a LIST column with 1 list composed of 5 total integers + * auto elements = make_counting_transform_iterator(0, [](auto i){return i*2;}); * auto validity = make_counting_transform_iterator(0, [](auto i){return i%2;}); - * // [{"abc", NULL}] - * lists_column_wrapper l{{"abc", "def"}, validity}; + * // [{0, NULL, 2, NULL, 4}] + * lists_column_wrapper l(elements, elements+5, validity); * @endcode * - * @param elements The list of elements + * @param begin Beginning of the sequence + * @param end End of the sequence * @param v The validity iterator * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template >* = nullptr> - lists_column_wrapper(std::initializer_list elements, + template + lists_column_wrapper(InputIterator begin, + InputIterator end, ValidityIterator v, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { - build_from_non_nested( - cudf::test::strings_column_wrapper(elements.begin(), elements.end(), v, stream, mr).release(), - stream, - mr); + build_from_non_nested(leaf_wrapper_t(begin, end, v, stream, mr).release(), stream, mr); } /** @@ -1688,6 +1848,11 @@ class lists_column_wrapper : public detail::column_wrapper { * lists_column_wrapper l{ {{0, 1}, {2, 3}}, {{4, 5}, {6, 7}} }; * @endcode * + * For multi-row (and deeper) columns that should allocate with an explicit stream/mr, use + * `lists_column_initializer` so every nesting level receives those arguments: + * `using Init = cudf::test::lists_column_initializer;` + * `lists_column_wrapper l{Init{{{0, 1}, {2, 3}, {4, 5}}}, stream, mr};` + * * @param elements The list of elements * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column @@ -1763,6 +1928,46 @@ class lists_column_wrapper : public detail::column_wrapper { build_from_nested(elements, validity, stream, mr); } + /** + * @brief Construct a lists column from a recursive `lists_column_initializer` tree. + * + * Every nesting level is allocated with the provided `stream` and `mr`. Prefer this over + * brace-nested `lists_column_wrapper` constructions that pass resources only at the outer + * level. + * + * Example: + * @code{.cpp} + * using Init = cudf::test::lists_column_initializer; + * // List: [{0, 1}, {2, 3}, {4, 5}] + * lists_column_wrapper l{Init{{{0, 1}, {2, 3}, {4, 5}}}, stream, mr}; + * + * // List>: [{{0, 1}, {2}}, {{3}}] + * lists_column_wrapper nested{Init{{{{0, 1}, {2}}, {{3}}}}, stream, mr}; + * @endcode + * + * @param init Host-side nested values (and optional validity) + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column + */ + lists_column_wrapper(lists_column_initializer init, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) + : column_wrapper{} + { + if (!init.nested()) { + if (init.value_validity().empty()) { + *this = lists_column_wrapper(init.values().begin(), init.values().end(), stream, mr); + } else { + *this = lists_column_wrapper( + init.values().begin(), init.values().end(), init.value_validity().begin(), stream, mr); + } + return; + } + + auto [children, validity] = init.template build(stream, mr); + build_from_nested(children, validity, stream, mr); + } + /** * @brief Construct a list column containing a single empty, optionally null row. * @@ -1826,7 +2031,8 @@ class lists_column_wrapper : public detail::column_wrapper { * @param mr Memory resources used to allocate the returned column * */ - void build_from_nested(std::initializer_list> elements, + template + void build_from_nested(ListsRange const& elements, std::vector const& v, rmm::cuda_stream_view stream, cudf::memory_resources mr) @@ -1986,8 +2192,9 @@ class lists_column_wrapper : public detail::column_wrapper { cudf::copy_bitmask(col, stream, temp_mr)); } + template std::pair, std::vector>> preprocess_columns( - std::initializer_list> const& elements, + ListsRange const& elements, column_view& expected_hierarchy, int expected_depth, rmm::cuda_stream_view stream, diff --git a/cpp/tests/copying/gather_list_tests.cpp b/cpp/tests/copying/gather_list_tests.cpp index a07747a9403c..2e9ff3fdfed6 100644 --- a/cpp/tests/copying/gather_list_tests.cpp +++ b/cpp/tests/copying/gather_list_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -17,7 +17,7 @@ #include template -class GatherTestListTyped : public cudf::test::BaseFixture {}; +class GatherTestListTyped : public cudf::test::BaseFixtureWithHarness {}; using FixedWidthTypesNotBool = cudf::test::Concat; TYPED_TEST_SUITE(GatherTestListTyped, FixedWidthTypesNotBool); -class GatherTestList : public cudf::test::BaseFixture {}; +class GatherTestList : public cudf::test::BaseFixtureWithHarness {}; // to disambiguate between {} == 0 and {} == List{0} // Also, see note about compiler issues when declaring nested @@ -33,46 +33,62 @@ class GatherTestList : public cudf::test::BaseFixture {}; template using LCW = cudf::test::lists_column_wrapper; +// Nested list values. Passing these to lists_column_wrapper builds every nesting level with the +// explicit stream and memory resources instead of the current device resource. +using Init = cudf::test::lists_column_initializer; + TYPED_TEST(GatherTestListTyped, Gather) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List - LCW list{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}; - cudf::test::fixed_width_column_wrapper gather_map{0, 2}; + LCW list{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}, st, mr}; + cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{1, 2, 3, 4}, {6, 7}}; + LCW expected{Init{{1, 2, 3, 4}, {6, 7}}, st, mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } TYPED_TEST(GatherTestListTyped, GatherNothing) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List { - LCW list{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}; + LCW list{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}, st, mr}; cudf::test::fixed_width_column_wrapper gather_map{}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List { - cudf::test::lists_column_wrapper list{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}; + cudf::test::lists_column_wrapper list{ + Init{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}, st, mr}; cudf::test::fixed_width_column_wrapper gather_map{}; cudf::table_view source_table({list}); - auto result = cudf::gather(source_table, gather_map); + auto result = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -94,58 +110,77 @@ TYPED_TEST(GatherTestListTyped, GatherNulls) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + auto valids = cudf::test::iterators::valids_at_multiples_of(2); // List - LCW list{{{1, 2, 3, 4}, valids}, {5}, {{6, 7}, valids}, {{8, 9, 10}, valids}}; - cudf::test::fixed_width_column_wrapper gather_map{0, 2}; + LCW list{Init{{{1, 2, 3, 4}, valids}, {5}, {{6, 7}, valids}, {{8, 9, 10}, valids}}, st, mr}; + cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{{1, 2, 3, 4}, valids}, {{6, 7}, valids}}; + LCW expected{Init{{{1, 2, 3, 4}, valids}, {{6, 7}, valids}}, st, mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } TYPED_TEST(GatherTestListTyped, GatherNested) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List> { - LCW list{{{2, 3}, {4, 5}}, - {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - cudf::test::fixed_width_column_wrapper gather_map{0, 2}; + LCW list{Init{{{2, 3}, {4, 5}}, + {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + st, + mr}; + cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{{2, 3}, {4, 5}}, {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; + LCW expected{ + Init{{{2, 3}, {4, 5}}, {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, st, mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List>> { - LCW list{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - {{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, - {{LCW{0}}}, - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{10, 20}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}}; - cudf::test::fixed_width_column_wrapper gather_map{1, 2, 4}; + LCW list{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + {{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + {{Init{0}}}, + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + {{{10, 20}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}}, + st, + mr}; + cudf::test::fixed_width_column_wrapper gather_map{{1, 2, 4}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, - {{LCW{0}}}, - {{{10, 20}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}}; + LCW expected{Init{{{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + {{Init{0}}}, + {{{10, 20}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}}, + st, + mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -153,21 +188,30 @@ TYPED_TEST(GatherTestListTyped, GatherOutOfOrder) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List> { - LCW list{{{2, 3}, {4, 5}}, - {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - cudf::test::fixed_width_column_wrapper gather_map{1, 2, 0}; + LCW list{Init{{{2, 3}, {4, 5}}, + {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + st, + mr}; + cudf::test::fixed_width_column_wrapper gather_map{{1, 2, 0}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}, - {{2, 3}, {4, 5}}}; + LCW expected{Init{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}, + {{2, 3}, {4, 5}}}, + st, + mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -175,48 +219,64 @@ TYPED_TEST(GatherTestListTyped, GatherNestedNulls) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + auto valids = cudf::test::iterators::valids_at_multiples_of(2); // List> { - LCW list{{{{2, 3}, valids}, {4, 5}}, - {{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, valids}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}, - {{{{25, 26}, valids}, {27, 28}, {{29, 30}, valids}, {31, 32}, {33, 34}}, valids}}; + LCW list{ + Init{{{{2, 3}, valids}, {4, 5}}, + {{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, valids}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}, + {{{{25, 26}, valids}, {27, 28}, {{29, 30}, valids}, {31, 32}, {33, 34}}, valids}}, + st, + mr}; - cudf::test::fixed_width_column_wrapper gather_map{0, 1, 3}; + cudf::test::fixed_width_column_wrapper gather_map{{0, 1, 3}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ - {{{2, 3}, valids}, {4, 5}}, - {{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, valids}, - {{{{25, 26}, valids}, {27, 28}, {{29, 30}, valids}, {31, 32}, {33, 34}}, valids}}; - - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + Init{{{{2, 3}, valids}, {4, 5}}, + {{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, valids}, + {{{{25, 26}, valids}, {27, 28}, {{29, 30}, valids}, {31, 32}, {33, 34}}, valids}}, + st, + mr}; + + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List>> { - LCW list{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, - {{LCW{0}}}, - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}}; - - cudf::test::fixed_width_column_wrapper gather_map{1, 2, 4}; + LCW list{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, + {{Init{0}}}, + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}}, + st, + mr}; + + cudf::test::fixed_width_column_wrapper gather_map{{1, 2, 4}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, - {{LCW{0}}}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}}; + LCW expected{Init{{{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, + {{Init{0}}}, + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}}, + st, + mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -224,55 +284,70 @@ TYPED_TEST(GatherTestListTyped, GatherNestedWithEmpties) { using T = TypeParam; - LCW list{{{2, 3}, LCW{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {LCW{}}}; - cudf::test::fixed_width_column_wrapper gather_map{0, 2}; + auto const st = this->stream(); + auto const mr = this->resources(); + + LCW list{Init{{{2, 3}, Init{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {Init{}}}, st, mr}; + cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - LCW expected{{{2, 3}, LCW{}}, {LCW{}}}; + LCW expected{Init{{{2, 3}, Init{}}, {Init{}}}, st, mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } TYPED_TEST(GatherTestListTyped, GatherDetailInvalidIndex) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List> { - LCW list{{{2, 3}, {4, 5}}, - {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - cudf::test::fixed_width_column_wrapper gather_map{0, 15, 16, 2}; + LCW list{Init{{{2, 3}, {4, 5}}, + {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + st, + mr}; + cudf::test::fixed_width_column_wrapper gather_map{{0, 15, 16, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::NULLIFY); + auto results = + cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::NULLIFY, st, mr.get_output_mr()); std::vector expected_validity{1, 0, 0, 1}; - LCW expected{{{{2, 3}, {4, 5}}, - {LCW{}}, - {LCW{}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, - expected_validity.begin()}; - - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view().column(0), expected); + LCW expected{ + Init{ + {{{2, 3}, {4, 5}}, {Init{}}, {Init{}}, {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + expected_validity.begin()}, + st, + mr}; + + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view().column(0), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } TEST_F(GatherTestList, GatherIncompleteHierarchies) { - using LCW = cudf::test::lists_column_wrapper; + auto const st = this->stream(); + auto const mr = this->resources(); { // List, but rows 1 and 2 are empty at the very top. // We expect to get back a "full" hierarchy of type List> anyway. - cudf::test::lists_column_wrapper list{{{{1, 2}}}, LCW{}, LCW{}}; + cudf::test::lists_column_wrapper list{Init{{{{1, 2}}}, Init{}, Init{}}, st, mr}; cudf::table_view source_table({list}); - cudf::test::fixed_width_column_wrapper row1_map{1}; - auto result = cudf::gather(source_table, row1_map); + cudf::test::fixed_width_column_wrapper row1_map{{1}, st, mr}; + auto result = + cudf::gather(source_table, row1_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -292,12 +367,13 @@ TEST_F(GatherTestList, GatherIncompleteHierarchies) { // List, gathering nothing. // We expect to get back a "full" hierarchy of type List> anyway. - cudf::test::lists_column_wrapper list{{{{1, 2}}}, LCW{}}; + cudf::test::lists_column_wrapper list{Init{{{{1, 2}}}, Init{}}, st, mr}; cudf::table_view source_table({list}); cudf::test::fixed_width_column_wrapper empty_map{}; - auto result = cudf::gather(source_table, empty_map); + auto result = + cudf::gather(source_table, empty_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -318,34 +394,54 @@ TEST_F(GatherTestList, GatherIncompleteHierarchies) TYPED_TEST(GatherTestListTyped, GatherSliced) { using T = TypeParam; + + auto const st = this->stream(); + auto const mr = this->resources(); + { - LCW a{ - {{1, 1, 1}, {2, 2}, {3, 3}}, - {{4, 4, 4}, {5, 5}, {6, 6}}, - {{7, 7, 7}, {8, 8}, {9, 9}}, - {{10, 10, 10}, {11, 11}, {12, 12}}, - {{20, 20, 20, 20}, {25}}, - {{30, 30, 30, 30}, {40}}, - {{50, 50, 50, 50}, {6, 13}}, - {{70, 70, 70, 70}, {80}}, - }; - auto split_a = cudf::split(a, {3}); + LCW a{Init{ + {{1, 1, 1}, {2, 2}, {3, 3}}, + {{4, 4, 4}, {5, 5}, {6, 6}}, + {{7, 7, 7}, {8, 8}, {9, 9}}, + {{10, 10, 10}, {11, 11}, {12, 12}}, + {{20, 20, 20, 20}, {25}}, + {{30, 30, 30, 30}, {40}}, + {{50, 50, 50, 50}, {6, 13}}, + {{70, 70, 70, 70}, {80}}, + }, + st, + mr}; + auto split_a = cudf::split(a, {3}, st); cudf::table_view tbl0({split_a[0]}); cudf::table_view tbl1({split_a[1]}); - auto result0 = cudf::gather(tbl0, cudf::test::fixed_width_column_wrapper{1, 2}); - LCW expected0{ - {{4, 4, 4}, {5, 5}, {6, 6}}, - {{7, 7, 7}, {8, 8}, {9, 9}}, - }; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected0, result0->get_column(0).view()); - - auto result1 = cudf::gather(tbl1, cudf::test::fixed_width_column_wrapper{0, 3}); - LCW expected1{ - {{10, 10, 10}, {11, 11}, {12, 12}}, - {{50, 50, 50, 50}, {6, 13}}, - }; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected1, result1->get_column(0).view()); + cudf::test::fixed_width_column_wrapper map0{{1, 2}, st, mr}; + auto result0 = cudf::gather(tbl0, map0, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + LCW expected0{Init{ + {{4, 4, 4}, {5, 5}, {6, 6}}, + {{7, 7, 7}, {8, 8}, {9, 9}}, + }, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected0, + result0->get_column(0).view(), + cudf::test::debug_output_level::FIRST_ERROR, + st, + mr); + + cudf::test::fixed_width_column_wrapper map1{{0, 3}, st, mr}; + auto result1 = cudf::gather(tbl1, map1, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + LCW expected1{Init{ + {{10, 10, 10}, {11, 11}, {12, 12}}, + {{50, 50, 50, 50}, {6, 13}}, + }, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected1, + result1->get_column(0).view(), + cudf::test::debug_output_level::FIRST_ERROR, + st, + mr); } auto valids = cudf::test::iterators::valids_at_multiples_of(2); @@ -353,70 +449,93 @@ TYPED_TEST(GatherTestListTyped, GatherSliced) // List>> { LCW list{ - // slice 0 - {{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + Init{// slice 0 + {{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}, - {{11, 12}, {{42, 43, 44}, valids}, {{77, 78}, valids}}}, + {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}, + {{11, 12}, {{42, 43, 44}, valids}, {{77, 78}, valids}}}, - // slice 1 - {{LCW{0}}}, - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, + // slice 1 + {{Init{0}}}, + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, - // slice 2 - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}, - {{{{10, 20, 30}}, {LCW{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}}; + // slice 2 + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}, + {{{{10, 20, 30}}, {Init{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}}, + st, + mr}; - auto sliced = cudf::slice(list, {0, 1, 2, 5, 5, 7}); + auto sliced = cudf::slice(list, {0, 1, 2, 5, 5, 7}, st); // gather from slice 0 { cudf::table_view tbl({sliced[0]}); - cudf::test::fixed_width_column_wrapper map{0}; - auto result = cudf::gather(tbl, map); - LCW expected{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->get_column(0).view()); + cudf::test::fixed_width_column_wrapper map{{0}, st, mr}; + auto result = cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + LCW expected{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, + result->get_column(0).view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } // gather from slice 1 { cudf::table_view tbl({sliced[1]}); - cudf::test::fixed_width_column_wrapper map{1, 2, 0, 1}; - auto result = cudf::gather(tbl, map); + cudf::test::fixed_width_column_wrapper map{{1, 2, 0, 1}, st, mr}; + auto result = cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - - {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, - - {{LCW{0}}}, - - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - }; - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->get_column(0).view()); + Init{ + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + + {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, + + {{Init{0}}}, + + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + }, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, + result->get_column(0).view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } // gather from slice 2 { cudf::table_view tbl({sliced[2]}); - cudf::test::fixed_width_column_wrapper map{1, 0, 0, 1, 1, 0}; - auto result = cudf::gather(tbl, map); - LCW expected{{{{{10, 20, 30}}, {LCW{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}, - {{{{10, 20, 30}}, {LCW{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, - {{{{10, 20, 30}}, {LCW{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}}; - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->get_column(0).view()); + cudf::test::fixed_width_column_wrapper map{{1, 0, 0, 1, 1, 0}, st, mr}; + auto result = cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + LCW expected{ + Init{{{{{10, 20, 30}}, {Init{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}, + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}, + {{{{10, 20, 30}}, {Init{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, + {{{{10, 20, 30}}, {Init{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}}, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, + result->get_column(0).view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } } } diff --git a/cpp/tests/copying/segmented_gather_list_tests.cpp b/cpp/tests/copying/segmented_gather_list_tests.cpp index 1827275b328e..a3e2bcac2825 100644 --- a/cpp/tests/copying/segmented_gather_list_tests.cpp +++ b/cpp/tests/copying/segmented_gather_list_tests.cpp @@ -1,7 +1,15 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ + +// Nested `LCW{LCW...` constructions (including empty-list columns with explicit stream/mr) +// trip gcc14's -Wmaybe-uninitialized on column_view_base's copy constructor. Same diagnostic +// as lists/extract_tests.cpp; ignore for the whole file because the warning fires in headers. +#if defined(__GNUC__) && (__GNUC__ >= 14) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif #include #include #include @@ -17,7 +25,7 @@ #include template -class SegmentedGatherTest : public cudf::test::BaseFixture {}; +class SegmentedGatherTest : public cudf::test::BaseFixtureWithHarness {}; using FixedWidthTypesNotBool = cudf::test::Concat; using namespace cudf::test::iterators; auto constexpr NULLIFY = cudf::out_of_bounds_policy::NULLIFY; +// Nested list values. Passing these to lists_column_wrapper builds every nesting level with the +// explicit stream and memory resources instead of the current device resource. +using Init = cudf::test::lists_column_initializer; +using I8Init = cudf::test::lists_column_initializer; +using StrInit = cudf::test::lists_column_initializer; + TYPED_TEST(SegmentedGatherTest, Gather) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List - LCW list{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}; + LCW list{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}, st, mr}; { // Straight-line case. - auto const gather_map = LCW{{3, 2, 1, 0}, {0}, {0, 1}, {0, 2, 1}}; - auto const expected = LCW{{4, 3, 2, 1}, {5}, {6, 7}, {8, 10, 9}}; + auto const gather_map = LCW{Init{{3, 2, 1, 0}, {0}, {0, 1}, {0, 2, 1}}, st, mr}; + auto const expected = LCW{Init{{4, 3, 2, 1}, {5}, {6, 7}, {8, 10, 9}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } { // Nullify out-of-bounds values. - auto const gather_map = LCW{{3, 2, 4, 0}, {0}, {0, -3}, {0, 2, 1}}; - auto const expected = LCW{{{4, 3, 2, 1}, null_at(2)}, {5}, {{6, 7}, null_at(1)}, {8, 10, 9}}; - auto const results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + auto const gather_map = LCW{Init{{3, 2, 4, 0}, {0}, {0, -3}, {0, 2, 1}}, st, mr}; + auto const expected = + LCW{Init{{{{4, 3, 2, 1}, null_at(2)}, {5}, {{6, 7}, null_at(1)}, {8, 10, 9}}}, st, mr}; + auto const results = cudf::lists::segmented_gather( + cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -62,37 +83,48 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List { - auto const list = LCW{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}; - auto const gather_map = LCW{LCW{}, LCW{}, LCW{}, LCW{}}; + auto const list = LCW{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}, st, mr}; + auto const gather_map = LCW{{LCW{}, LCW{}, LCW{}, LCW{}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); - auto const expected = LCW{LCW{}, LCW{}, LCW{}, LCW{}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*results, expected); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{{LCW{}, LCW{}, LCW{}, LCW{}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List> { - auto const list = LCW{{{1, 2, 3, 4}, {5}}, {{6, 7}}, {{}, {8, 9, 10}}}; - auto const gather_map = LCW{LCW{}, LCW{}, LCW{}}; + auto const list = LCW{Init{{{1, 2, 3, 4}, {5}}, {{6, 7}}, {Init{}, {8, 9, 10}}}, st, mr}; + auto const gather_map = LCW{{LCW{}, LCW{}, LCW{}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // hack to get column of empty list of list - auto const expected_dummy = LCW{{{1, 2, 3, 4}, {5}}, LCW{}, LCW{}, LCW{}}; - auto const expected = cudf::split(expected_dummy, {1})[1]; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*results, expected); + auto const expected_dummy = + LCW{{LCW{Init{{{1, 2, 3, 4}, {5}}}, st, mr}, LCW{}, LCW{}, LCW{}}, st, mr}; + auto const expected = cudf::split(expected_dummy, {1}, st)[1]; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List>> { - auto const list = LCW{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}; - auto const gather_map = LCW{LCW{}, LCW{}}; + auto const list = LCW{Init{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}, st, mr}; + auto const gather_map = LCW{{LCW{}, LCW{}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // hack to get column of empty list of list of list - auto const expected_dummy = LCW{{{{1, 2, 3, 4}}}, LCW{}, LCW{}}; - auto const expected = cudf::split(expected_dummy, {1})[1]; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*results, expected); + auto const expected_dummy = + LCW{{LCW{Init{{{{1, 2, 3, 4}}}}, st, mr}, LCW{}, LCW{}}, st, mr}; + auto const expected = cudf::split(expected_dummy, {1}, st)[1]; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -113,40 +145,54 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) using SegmentedGatherTestSingle = SegmentedGatherTest; TEST_F(SegmentedGatherTestSingle, GatherEmpty) { + auto const st = this->stream(); + auto const mr = this->resources(); + auto const list = LCW{}; auto const gather_map = LCW{}; auto const expected = LCW{}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*results, expected); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } TYPED_TEST(SegmentedGatherTest, GatherNulls) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + auto valids = cudf::test::iterators::valids_at_multiples_of(2); // List - auto const list = LCW{{{1, 2, 3, 4}, valids}, {5}, {{6, 7}, valids}, {{8, 9, 10}, valids}}; + auto const list = + LCW{Init{{{1, 2, 3, 4}, valids}, {5}, {{6, 7}, valids}, {{8, 9, 10}, valids}}, st, mr}; { // Test gathering on lists that contain nulls. - auto const gather_map = LCW{{0, 1}, LCW{}, {1}, {2, 1, 0}}; + auto const gather_map = LCW{Init{{0, 1}, Init{}, {1}, {2, 1, 0}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); auto const expected = - LCW{{{1, 2}, valids}, LCW{}, {{7}, valids + 1}, {{10, 9, 8}, valids}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + LCW{Init{{{{1, 2}, valids}, Init{}, {{7}, valids + 1}, {{10, 9, 8}, valids}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } { // Test gathering on lists that contain nulls, with out-of-bounds indices. - auto const gather_map = LCW{{10, -10}, LCW{}, {1}, {2, -10, 0}}; + auto const gather_map = LCW{Init{{10, -10}, Init{}, {1}, {2, -10, 0}}, st, mr}; auto const results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - auto const expected = - LCW{{{0, 0}, nulls_at({0, 1})}, LCW{}, {{7}, valids + 1}, {{10, 0, 8}, null_at(1)}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const expected = LCW{ + Init{{{{0, 0}, nulls_at({0, 1})}, Init{}, {{7}, valids + 1}, {{10, 0, 8}, null_at(1)}}}, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -154,78 +200,85 @@ TYPED_TEST(SegmentedGatherTest, GatherNested) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List> { // clang-format off - auto const list = LCW{{{2, 3}, {4, 5}}, + auto const list = LCW{Init{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {-17, -18}}}; - auto const gather_map = LCW{{0, -2, -2}, {1}, {1, 0, -1, -5}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}); - auto const expected = LCW{{{2, 3}, {2, 3}, {2, 3}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {-17, -18}}}, st, mr}; + auto const gather_map = LCW{Init{{0, -2, -2}, {1}, {1, 0, -1, -5}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{2, 3}, {2, 3}, {2, 3}}, {{9, 10, 11}}, - {{17, 18}, {15, 16}, {-17, -18}, {15, 16}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{17, 18}, {15, 16}, {-17, -18}, {15, 16}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } // List>, with out-of-bounds gather indices. { // clang-format off - auto const list = LCW{{{2, 3}, {4, 5}}, + auto const list = LCW{Init{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {-17, -18}}}; - auto const gather_map = LCW{{0, 2, -2}, {1}, {1, 0, -1, -6}}; + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {-17, -18}}}, st, mr}; + auto const gather_map = LCW{Init{{0, 2, -2}, {1}, {1, 0, -1, -6}}, st, mr}; auto const results = - cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - auto const expected = LCW{{{{2, 3}, LCW{}, {2, 3}}, null_at(1)}, + cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{{{2, 3}, Init{}, {2, 3}}, null_at(1)}, {{9, 10, 11}}, - {{{17, 18}, {15, 16}, {-17, -18}, LCW{}}, null_at(3)}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{{17, 18}, {15, 16}, {-17, -18}, Init{}}, null_at(3)}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } // List>> { // clang-format off - auto const list = LCW{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + auto const list = LCW{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, {{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, - {{LCW{0}}}, + {{Init{0}}}, {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, {{0, 1, 3}, {5}}, {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{10, 20}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}}; - auto const gather_map = LCW{{1}, LCW{}, {0}, {1}, {0, -1, 1}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}); - auto const expected = LCW{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - LCW{}, - {{LCW{0}}}, + {{{10, 20}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}}, st, mr}; + auto const gather_map = LCW{Init{{1}, Init{}, {0}, {1}, {0, -1, 1}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + Init{}, + {{Init{0}}}, {{{0, 1, 3}, {5}}}, - {{{10, 20}}, {{40, 50}, {60, 70, 80}}, {LCW{30}}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{{10, 20}}, {{40, 50}, {60, 70, 80}}, {Init{30}}}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } // List>>, with out-of-bounds gather indices. { - auto const list = LCW{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - {{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, - {{LCW{0}}}, - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{10, 20}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}}; - auto const gather_map = LCW{{1}, LCW{}, {0}, {1}, {0, -1, 3, -4}}; + auto const list = LCW{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + {{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, + {{Init{0}}}, + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + {{{10, 20}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}}, + st, + mr}; + auto const gather_map = LCW{Init{{1}, Init{}, {0}, {1}, {0, -1, 3, -4}}, st, mr}; auto const results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); + cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); auto const expected = - LCW{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - LCW{}, - {{LCW{0}}}, - {{{0, 1, 3}, {5}}}, - {{{{10, 20}}, {{40, 50}, {60, 70, 80}}, LCW{}, LCW{}}, nulls_at({2, 3})}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); - // clang-format on + LCW{Init{{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + Init{}, + {{Init{0}}}, + {{{0, 1, 3}, {5}}}, + {{{{10, 20}}, {{40, 50}, {60, 70, 80}}, Init{}, Init{}}, nulls_at({2, 3})}}}, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -233,33 +286,36 @@ TYPED_TEST(SegmentedGatherTest, GatherOutOfOrder) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List> { // clang-format off - auto const list = LCW{{{2, 3}, {4, 5}}, + auto const list = LCW{Init{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - auto const gather_map = LCW{{1, 0}, {1, 2, 0}, {4, 3, 2, 1, 0}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}); - auto const expected = LCW{{{4, 5}, {2, 3}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, st, mr}; + auto const gather_map = LCW{Init{{1, 0}, {1, 2, 0}, {4, 3, 2, 1, 0}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{4, 5}, {2, 3}}, {{9, 10, 11}, {12, 13, 14}, {6, 7, 8}}, - {{17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } // List>, with out-of-bounds gather indices. { // clang-format off - auto const list = LCW{{{2, 3}, {4, 5}}, + auto const list = LCW{Init{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - auto const gather_map = LCW{{1, 0}, {3, -1, -4}, {5, 4, 3, 2, 1, 0}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - auto const expected = LCW{{{4, 5}, {2, 3}}, - {{LCW{}, {12, 13, 14}, LCW{}}, nulls_at({0, 2})}, - {{LCW{}, {17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}, null_at(0)}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, st, mr}; + auto const gather_map = LCW{Init{{1, 0}, {3, -1, -4}, {5, 4, 3, 2, 1, 0}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{4, 5}, {2, 3}}, + {{Init{}, {12, 13, 14}, Init{}}, nulls_at({0, 2})}, + {{Init{}, {17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}, null_at(0)}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } } @@ -268,33 +324,36 @@ TYPED_TEST(SegmentedGatherTest, GatherNegatives) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + // List> { // clang-format off - auto const list = LCW{{{2, 3}, {4, 5}}, + auto const list = LCW{Init{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - auto const gather_map = LCW{{-1, 0}, {-2, -1, 0}, {-5, -4, -3, -2, -1, 0}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}); - auto const expected = LCW{{{4, 5}, {2, 3}}, + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, st, mr}; + auto const gather_map = LCW{Init{{-1, 0}, {-2, -1, 0}, {-5, -4, -3, -2, -1, 0}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{4, 5}, {2, 3}}, {{9, 10, 11}, {12, 13, 14}, {6, 7, 8}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } // List>, with out-of-bounds gather indices. { // clang-format off - auto const list = LCW{{{2, 3}, {4, 5}}, + auto const list = LCW{Init{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, - {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}; - auto const gather_map = LCW{{-1, 0}, {-2, -1, -4}, {-6, -4, -3, -2, -1, 0}}; + {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, st, mr}; + auto const gather_map = LCW{Init{{-1, 0}, {-2, -1, -4}, {-6, -4, -3, -2, -1, 0}}, st, mr}; auto const results = - cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - auto const expected = LCW{{{4, 5}, {2, 3}}, - {{{9, 10, 11}, {12, 13, 14}, LCW{}}, null_at(2)}, - {{LCW{}, {17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}, null_at(0)}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{4, 5}, {2, 3}}, + {{{9, 10, 11}, {12, 13, 14}, Init{}}, null_at(2)}, + {{Init{}, {17, 18}, {17, 18}, {17, 18}, {17, 18}, {15, 16}}, null_at(0)}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } } @@ -303,41 +362,44 @@ TYPED_TEST(SegmentedGatherTest, GatherNestedNulls) { using T = TypeParam; + auto const st = this->stream(); + auto const mr = this->resources(); + auto valids = cudf::test::iterators::valids_at_multiples_of(2); // List> { // clang-format off - auto const list = LCW{{{{2, 3}, valids}, {4, 5}}, + auto const list = LCW{Init{{{{2, 3}, valids}, {4, 5}}, {{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, valids}, {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}, - {{{{25, 26}, valids}, {27, 28}, {{29, 30}, valids}, {31, 32}, {33, 34}}, valids}}; - auto const gather_map = LCW{{0, 1}, {0, 2}, LCW{}, {0, 1, 4}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}); - auto const expected = LCW{{{{2, 3}, valids}, {4, 5}}, + {{{{25, 26}, valids}, {27, 28}, {{29, 30}, valids}, {31, 32}, {33, 34}}, valids}}, st, mr}; + auto const gather_map = LCW{Init{{0, 1}, {0, 2}, Init{}, {0, 1, 4}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{{2, 3}, valids}, {4, 5}}, {{{6, 7, 8}, {12, 13, 14}}, no_nulls()}, - LCW{}, - {{{{25, 26}, valids}, {27, 28}, {33, 34}}, valids}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + Init{}, + {{{{25, 26}, valids}, {27, 28}, {33, 34}}, valids}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } // List>>> { // clang-format off - auto const list = LCW{{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + auto const list = LCW{Init{{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, - {{LCW{0}}}, + {{Init{0}}}, {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, {{0, 1, 3}, {5}}, {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}}}; - auto const gather_map = LCW{{1, 2, 4}}; - auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}); - auto const expected = LCW{{{{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, - {{LCW{0}}}, - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}}}, st, mr}; + auto const gather_map = LCW{Init{{1, 2, 4}}, st, mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{{{{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, + {{Init{0}}}, + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } } @@ -346,52 +408,72 @@ TYPED_TEST(SegmentedGatherTest, GatherNestedWithEmpties) { using T = TypeParam; - auto const list = LCW{{{2, 3}, LCW{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {LCW{}}}; - auto const gather_map = LCW{LCW{0}, LCW{0}, LCW{0}}; + auto const st = this->stream(); + auto const mr = this->resources(); + + auto const list = + LCW{Init{{{2, 3}, Init{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {Init{}}}, st, mr}; + auto const gather_map = LCW{Init{{0}, {0}, {0}}, st, mr}; auto results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); auto const expected = - LCW{{{2, 3}}, {{6, 7, 8}}, {LCW{}}}; // skip one null, gather one null. - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + LCW{Init{{{2, 3}}, {{6, 7, 8}}, {Init{}}}, st, mr}; // skip one null, gather one null. + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } TYPED_TEST(SegmentedGatherTest, GatherSliced) { using T = TypeParam; + + auto const st = this->stream(); + auto const mr = this->resources(); + { - auto const a = LCW{ - {{1, 1, 1}, {2, 2}, {3, 3}}, - {{4, 4, 4}, {5, 5}, {6, 6}}, - {{7, 7, 7}, {8, 8}, {9, 9}}, - {{10, 10, 10}, {11, 11}, {12, 12}}, - {{20, 20, 20, 20}, {25}}, - {{30, 30, 30, 30}, {40}}, - {{50, 50, 50, 50}, {6, 13}}, - {{70, 70, 70, 70}, {80}}, - }; - auto const split_a = cudf::split(a, {3}); + auto const a = LCW{Init{ + {{1, 1, 1}, {2, 2}, {3, 3}}, + {{4, 4, 4}, {5, 5}, {6, 6}}, + {{7, 7, 7}, {8, 8}, {9, 9}}, + {{10, 10, 10}, {11, 11}, {12, 12}}, + {{20, 20, 20, 20}, {25}}, + {{30, 30, 30, 30}, {40}}, + {{50, 50, 50, 50}, {6, 13}}, + {{70, 70, 70, 70}, {80}}, + }, + st, + mr}; + auto const split_a = cudf::split(a, {3}, st); { - auto const list = LCW{{1, 2}, {0, 2}, {0, 1}}; + auto const list = LCW{Init{{1, 2}, {0, 2}, {0, 1}}, st, mr}; auto const gather_map = cudf::lists_column_view{list}; - auto const result = - cudf::lists::segmented_gather(cudf::lists_column_view{split_a[0]}, gather_map); - auto const expected = LCW{ - {{2, 2}, {3, 3}}, - {{4, 4, 4}, {6, 6}}, - {{7, 7, 7}, {8, 8}}, - }; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); + auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{split_a[0]}, + gather_map, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto const expected = LCW{Init{ + {{2, 2}, {3, 3}}, + {{4, 4, 4}, {6, 6}}, + {{7, 7, 7}, {8, 8}}, + }, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, result->view(), cudf::test::debug_output_level::FIRST_ERROR, st, mr); } { - auto const list = LCW{{0, 1}, LCW{}, LCW{}, {0, 1}, LCW{}}; + auto const list = LCW{Init{{0, 1}, Init{}, Init{}, {0, 1}, Init{}}, st, mr}; auto const gather_map = cudf::lists_column_view{list}; - auto const result = - cudf::lists::segmented_gather(cudf::lists_column_view{split_a[1]}, gather_map); + auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{split_a[1]}, + gather_map, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); auto const expected = - LCW{{{10, 10, 10}, {11, 11}}, LCW{}, LCW{}, {{50, 50, 50, 50}, {6, 13}}, LCW{}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); + LCW{Init{{{10, 10, 10}, {11, 11}}, Init{}, Init{}, {{50, 50, 50, 50}, {6, 13}}, Init{}}, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, result->view(), cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -400,74 +482,99 @@ TYPED_TEST(SegmentedGatherTest, GatherSliced) // List>> { LCW list{ - // slice 0 - {{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + Init{// slice 0 + {{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}, - {{11, 12}, {{42, 43, 44}, valids}, {{77, 78}, valids}}}, + {{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}, + {{11, 12}, {{42, 43, 44}, valids}, {{77, 78}, valids}}}, - // slice 1 - {{LCW{0}}}, - {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, - {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, + // slice 1 + {{Init{0}}}, + {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}}, + {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, - // slice 2 - {{{{{10, 20}, valids}}, {LCW{30}}, {{40, 50}, {60, 70, 80}}}, valids}, - {{{{10, 20, 30}}, {LCW{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}}; + // slice 2 + {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}, + {{{{10, 20, 30}}, {Init{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}}, + st, + mr}; - auto sliced = cudf::slice(list, {0, 1, 2, 5, 5, 7}); + auto sliced = cudf::slice(list, {0, 1, 2, 5, 5, 7}, st); // gather from slice 0 { - LCW map{{0, 1}}; + LCW map{Init{{0, 1}}, st, mr}; auto result = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[0]}, - cudf::lists_column_view{map}); - LCW expected{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}}; - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->view()); + cudf::lists_column_view{map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + LCW expected{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, + result->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } // gather from slice 1 { - LCW map{{0}, {1, 2, 0, 1}, {0, 1, 2}}; + LCW map{Init{{0}, {1, 2, 0, 1}, {0, 1, 2}}, st, mr}; auto result = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[1]}, - cudf::lists_column_view{map}); + cudf::lists_column_view{map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ - {{LCW{0}}}, - - {{{0, 1, 3}, {5}}, - {{11, 12, 13, 14, 15}, {16, 17}, {0}}, - {{10}, {20, 30, 40, 50}, {60, 70, 80}}, - {{0, 1, 3}, {5}}}, - - {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, - }; - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->view()); + Init{ + {{Init{0}}}, + + {{{0, 1, 3}, {5}}, + {{11, 12, 13, 14, 15}, {16, 17}, {0}}, + {{10}, {20, 30, 40, 50}, {60, 70, 80}}, + {{0, 1, 3}, {5}}}, + + {{{{1, 6}, {60, 70, 80, 100}}, {{10, 11, 13}, {15}}, {{11, 12, 13, 14, 15}}}, valids}, + }, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, + result->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } // gather from slice 2 { - LCW map{{1, 0, 0, 1, 1, 0}, {1, 0, 0, 1, 1, 2}}; + LCW map{Init{{1, 0, 0, 1, 1, 0}, {1, 0, 0, 1, 1, 2}}, st, mr}; auto result = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[2]}, - cudf::lists_column_view{map}); + cudf::lists_column_view{map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); std::vector expected_valids = {false, true, true, false, false, true}; - LCW expected{{{{LCW{30}}, - {{{10, 20}, valids}}, - {{{10, 20}, valids}}, - {LCW{30}}, - {LCW{30}}, - {{{10, 20}, valids}}}, - expected_valids.begin()}, - {{{LCW{30}}, - {{10, 20, 30}}, - {{10, 20, 30}}, - {LCW{30}}, - {LCW{30}}, - {{{20, 30}, valids}, {62, 72, 82}}}, - expected_valids.begin()}}; - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->view()); + LCW expected{Init{{{{Init{30}}, + {{{10, 20}, valids}}, + {{{10, 20}, valids}}, + {Init{30}}, + {Init{30}}, + {{{10, 20}, valids}}}, + expected_valids.begin()}, + {{{Init{30}}, + {{10, 20, 30}}, + {{10, 20, 30}}, + {Init{30}}, + {Init{30}}, + {{{20, 30}, valids}, {62, 72, 82}}}, + expected_valids.begin()}}, + st, + mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, + result->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } } } @@ -476,26 +583,41 @@ using SegmentedGatherTestString = SegmentedGatherTest; TEST_F(SegmentedGatherTestString, StringGather) { using T = cudf::string_view; + + auto const st = this->stream(); + auto const mr = this->resources(); + // List { - auto const list = LCW{{"a", "b", "c", "d"}, {"1", "22", "333", "4"}, {"x", "y", "z"}}; - auto const gather_map = LCW{{0, 1, 3, 2}, {1, 0, 3, 2}, LCW{}}; - auto const expected = LCW{{"a", "b", "d", "c"}, {"22", "1", "4", "333"}, LCW{}}; - auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); + auto const list = + LCW{StrInit{{"a", "b", "c", "d"}, {"1", "22", "333", "4"}, {"x", "y", "z"}}, st, mr}; + auto const gather_map = cudf::test::lists_column_wrapper{ + I8Init{{0, 1, 3, 2}, {1, 0, 3, 2}, I8Init{}}, st, mr}; + auto const expected = + LCW{StrInit{{"a", "b", "d", "c"}, {"22", "1", "4", "333"}, StrInit{}}, st, mr}; + auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{list}, + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, result->view(), cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List, with out-of-order gather indices. { - auto const list = LCW{{"a", "b", "c", "d"}, {"1", "22", "333", "4"}, {"x", "y", "z"}}; - auto const gather_map = LCW{{0, 1, 3, 4}, {1, -5, 3, 2}, LCW{}}; - auto const expected = LCW{{{"a", "b", "d", "c"}, cudf::test::iterators::null_at(3)}, - {{"22", "1", "4", "333"}, cudf::test::iterators::null_at(1)}, - LCW{}}; - auto result = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); + auto const list = + LCW{StrInit{{"a", "b", "c", "d"}, {"1", "22", "333", "4"}, {"x", "y", "z"}}, st, mr}; + auto const gather_map = cudf::test::lists_column_wrapper{ + I8Init{{0, 1, 3, 4}, {1, -5, 3, 2}, I8Init{}}, st, mr}; + auto const expected = + LCW{StrInit{{{{"a", "b", "d", "c"}, cudf::test::iterators::null_at(3)}, + {{"22", "1", "4", "333"}, cudf::test::iterators::null_at(1)}, + StrInit{}}}, + st, + mr}; + auto result = cudf::lists::segmented_gather( + cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, result->view(), cudf::test::debug_output_level::FIRST_ERROR, st, mr); } } @@ -504,92 +626,150 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) { using T = float; + auto const st = this->stream(); + auto const mr = this->resources(); + // List { - auto const list = LCW{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}, {11, 12}, {13, 14, 15, 16}}; - auto const gather_map = LCW{{3, 2, 1, 0}, {0}, {0, 1}, {0, 2, 1}, {0}, {1}}; + auto const list = + LCW{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}, {11, 12}, {13, 14, 15, 16}}, st, mr}; + auto const gather_map = LCW{Init{{3, 2, 1, 0}, {0}, {0, 1}, {0, 2, 1}, {0}, {1}}, st, mr}; // gather_map.offset: 0, 4, 5, 7, 10, 11, 12 - auto const expected = LCW{{4, 3, 2, 1}, {5}, {6, 7}, {8, 10, 9}, {11}, {14}}; + auto const expected = LCW{Init{{4, 3, 2, 1}, {5}, {6, 7}, {8, 10, 9}, {11}, {14}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{gather_map}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + cudf::lists_column_view{gather_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); - auto const sliced = cudf::split(list, {1, 4}); - auto const split_m = cudf::split(gather_map, {1, 4}); - auto const split_e = cudf::split(expected, {1, 4}); + auto const sliced = cudf::split(list, {1, 4}, st); + auto const split_m = cudf::split(gather_map, {1, 4}, st); + auto const split_e = cudf::split(expected, {1, 4}, st); auto result0 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[0]}, - cudf::lists_column_view{split_m[0]}); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[0], result0->view()); + cudf::lists_column_view{split_m[0]}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[0], + result0->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); auto result1 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[1]}, - cudf::lists_column_view{split_m[1]}); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[1], result1->view()); + cudf::lists_column_view{split_m[1]}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[1], + result1->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); auto result2 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[2]}, - cudf::lists_column_view{split_m[2]}); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[2], result2->view()); + cudf::lists_column_view{split_m[2]}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[2], + result2->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } // List, with out-of-bounds gather indices. { - auto const list = LCW{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}, {11, 12}, {13, 14, 15, 16}}; - auto const gather_map = LCW{{3, -5, 1, 0}, {0}, {0, 1}, {0, 2, 3}, {0}, {1}}; + auto const list = + LCW{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}, {11, 12}, {13, 14, 15, 16}}, st, mr}; + auto const gather_map = LCW{Init{{3, -5, 1, 0}, {0}, {0, 1}, {0, 2, 3}, {0}, {1}}, st, mr}; // gather_map.offset: 0, 4, 5, 7, 10, 11, 12 auto const expected = - LCW{{{4, 0, 2, 1}, null_at(1)}, {5}, {6, 7}, {{8, 10, 9}, null_at(2)}, {11}, {14}}; + LCW{Init{{{{4, 0, 2, 1}, null_at(1)}, {5}, {6, 7}, {{8, 10, 9}, null_at(2)}, {11}, {14}}}, + st, + mr}; auto results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected); + cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); - auto const sliced = cudf::split(list, {1, 4}); - auto const split_m = cudf::split(gather_map, {1, 4}); - auto const split_e = cudf::split(expected, {1, 4}); + auto const sliced = cudf::split(list, {1, 4}, st); + auto const split_m = cudf::split(gather_map, {1, 4}, st); + auto const split_e = cudf::split(expected, {1, 4}, st); auto const result0 = cudf::lists::segmented_gather( - cudf::lists_column_view{sliced[0]}, cudf::lists_column_view{split_m[0]}, NULLIFY); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[0], result0->view()); + cudf::lists_column_view{sliced[0]}, cudf::lists_column_view{split_m[0]}, NULLIFY, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[0], + result0->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); auto const result1 = cudf::lists::segmented_gather( - cudf::lists_column_view{sliced[1]}, cudf::lists_column_view{split_m[1]}, NULLIFY); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[1], result1->view()); + cudf::lists_column_view{sliced[1]}, cudf::lists_column_view{split_m[1]}, NULLIFY, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[1], + result1->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); auto const result2 = cudf::lists::segmented_gather( - cudf::lists_column_view{sliced[2]}, cudf::lists_column_view{split_m[2]}, NULLIFY); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[2], result2->view()); + cudf::lists_column_view{sliced[2]}, cudf::lists_column_view{split_m[2]}, NULLIFY, st, mr.get_output_mr()); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[2], + result2->view(), + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + st, + mr); } } TEST_F(SegmentedGatherTestFloat, Fails) { using T = float; + + auto const st = this->stream(); + auto const mr = this->resources(); + // List - LCW list{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}; - LCW size_mismatch_map{{3, 2, 1, 0}, {0}, {0, 1}}; - cudf::test::fixed_width_column_wrapper nonlist_map0{1, 2, 0, 1}; - cudf::test::strings_column_wrapper nonlist_map1{"1", "2", "0", "1"}; - LCW nonlist_map2{{"1", "2", "0", "1"}}; + LCW list{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}, st, mr}; + cudf::test::lists_column_wrapper size_mismatch_map{ + I8Init{{3, 2, 1, 0}, {0}, {0, 1}}, st, mr}; + cudf::test::fixed_width_column_wrapper nonlist_map0{{1, 2, 0, 1}, st, mr}; + cudf::test::strings_column_wrapper nonlist_map1{{"1", "2", "0", "1"}, st, mr}; + LCW nonlist_map2{StrInit{{"1", "2", "0", "1"}}, st, mr}; // Input must be a list of integer indices. It should fail for integers, // strings, or lists containing anything other than integers. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{nonlist_map0}), + cudf::lists_column_view{nonlist_map0}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), cudf::logic_error); EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{nonlist_map1}), + cudf::lists_column_view{nonlist_map1}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), cudf::logic_error); EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{nonlist_map2}), + cudf::lists_column_view{nonlist_map2}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), cudf::logic_error); auto valids = cudf::test::iterators::valids_at_multiples_of(2); - LCW nulls_map{{{3, 2, 1, 0}, {0}, {0}, {0, 1}}, valids}; + cudf::test::lists_column_wrapper nulls_map{ + I8Init{{{{3, 2, 1, 0}, {0}, {0}, {0, 1}}, valids}}, st, mr}; // Nulls are not supported in the gather map. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{nulls_map}), + cudf::lists_column_view{nulls_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), std::invalid_argument); // Gather map and list column sizes must be the same. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, - cudf::lists_column_view{size_mismatch_map}), + cudf::lists_column_view{size_mismatch_map}, + cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), cudf::logic_error); } + +#if defined(__GNUC__) && (__GNUC__ >= 14) +#pragma GCC diagnostic pop +#endif diff --git a/cpp/tests/utilities/memory_resource_utilities.cpp b/cpp/tests/utilities/memory_resource_utilities.cpp index 06e57bb027a4..0baafeb9a5be 100644 --- a/cpp/tests/utilities/memory_resource_utilities.cpp +++ b/cpp/tests/utilities/memory_resource_utilities.cpp @@ -11,7 +11,11 @@ #include +#include +#include + #include +#include #include namespace cudf::test { @@ -27,11 +31,27 @@ scoped_current_device_resource::~scoped_current_device_resource() std::ignore = cudf::set_current_device_resource(std::move(_previous)); } +namespace { + +void print_allocation_stacktrace() +{ + constexpr int max_frames = 64; + void* frames[max_frames]; + int const nframes = ::backtrace(frames, max_frames); + std::cerr << "Unexpected allocation from the current device resource. Callstack (" << nframes + << " frames):\n"; + if (nframes > 0) { ::backtrace_symbols_fd(frames, nframes, STDERR_FILENO); } + std::cerr.flush(); +} + +} // namespace + memory_resource_test_harness::memory_resource_test_harness(rmm::device_async_resource_ref upstream) : _setup_mr{upstream}, _output_mr{upstream}, _temporary_mr{upstream}, _failing_mr{[](std::size_t, cuda::stream_ref, void*) -> void* { + print_allocation_stacktrace(); throw rmm::bad_alloc{"Unexpected allocation from the current device resource"}; }, [](void*, std::size_t, cuda::stream_ref, void*) {}} diff --git a/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp b/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp index ae83a6104ac0..50531b2b6448 100644 --- a/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp +++ b/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp @@ -1549,3 +1549,71 @@ TYPED_TEST(ListColumnWrapperTestTyped, LargeListsOfStructsWithValidity) CUDF_TEST_EXPECT_COLUMNS_EQUAL(*expected_struct_column, cudf::lists_column_view(*lists_column).child()); } + +// Harness-scoped construction via lists_column_initializer. +// Multi-row nested Init still routes through cudf::concatenate temporaries on the current +// resource; keep fail_on_current scopes on leaf / single-child paths until concatenate is ported. +struct ListsColumnInitializerHarnessTest : public cudf::test::BaseFixtureWithHarness {}; + +TEST_F(ListsColumnInitializerHarnessTest, LeafInitUsesExplicitResources) +{ + using Init = cudf::test::lists_column_initializer; + using LCW = cudf::test::lists_column_wrapper; + + auto const st = this->stream(); + auto const mr = this->resources(); + + std::unique_ptr built; + { + auto fail_on_current = this->fail_on_current_device_resource_use(); + LCW list{Init{{1, 2, 3, 4}}, st, mr}; + this->_harness.synchronize(st); + built = list.release(); + } + + LCW expected{Init{{1, 2, 3, 4}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(*built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); +} + +TEST_F(ListsColumnInitializerHarnessTest, LeafNullableInitUsesExplicitResources) +{ + using Init = cudf::test::lists_column_initializer; + using LCW = cudf::test::lists_column_wrapper; + using cudf::test::iterators::null_at; + + auto const st = this->stream(); + auto const mr = this->resources(); + + std::unique_ptr built; + { + auto fail_on_current = this->fail_on_current_device_resource_use(); + LCW list{Init{{{1, 2, 3, 4}, null_at(1)}}, st, mr}; + this->_harness.synchronize(st); + built = list.release(); + } + + LCW expected{Init{{{1, 2, 3, 4}, null_at(1)}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); +} + +TEST_F(ListsColumnInitializerHarnessTest, SingleChildNestedInitUsesExplicitResources) +{ + using Init = cudf::test::lists_column_initializer; + using LCW = cudf::test::lists_column_wrapper; + + auto const st = this->stream(); + auto const mr = this->resources(); + + // One outer row whose only child is a leaf list: both levels avoid concatenate. + std::unique_ptr built; + { + auto fail_on_current = this->fail_on_current_device_resource_use(); + LCW list{Init{{{{1, 2, 3}}}}, st, mr}; + this->_harness.synchronize(st); + built = list.release(); + } + + LCW expected{Init{{{{1, 2, 3}}}}, st, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(*built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); +} From 9da3e46fd4e505ea590307d1f0f656ada8a73641 Mon Sep 17 00:00:00 2001 From: Niranda Perera Date: Fri, 14 Aug 2026 17:19:54 -0700 Subject: [PATCH 2/5] Fix Init nesting in segmented gather list test ports Correct over-nested lists_column_initializer constructions and restore base empty-row brace patterns so list/segmented gather harness tests pass. --- .../copying/segmented_gather_list_tests.cpp | 52 +++++++++---------- .../lists_column_wrapper_tests.cpp | 4 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/cpp/tests/copying/segmented_gather_list_tests.cpp b/cpp/tests/copying/segmented_gather_list_tests.cpp index a3e2bcac2825..cf041519fe0a 100644 --- a/cpp/tests/copying/segmented_gather_list_tests.cpp +++ b/cpp/tests/copying/segmented_gather_list_tests.cpp @@ -71,7 +71,7 @@ TYPED_TEST(SegmentedGatherTest, Gather) // Nullify out-of-bounds values. auto const gather_map = LCW{Init{{3, 2, 4, 0}, {0}, {0, -3}, {0, 2, 1}}, st, mr}; auto const expected = - LCW{Init{{{{4, 3, 2, 1}, null_at(2)}, {5}, {{6, 7}, null_at(1)}, {8, 10, 9}}}, st, mr}; + LCW{Init{{{4, 3, 2, 1}, null_at(2)}, {5}, {{6, 7}, null_at(1)}, {8, 10, 9}}, st, mr}; auto const results = cudf::lists::segmented_gather( cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( @@ -99,30 +99,29 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) } // List> { - auto const list = LCW{Init{{{1, 2, 3, 4}, {5}}, {{6, 7}}, {Init{}, {8, 9, 10}}}, st, mr}; - auto const gather_map = LCW{{LCW{}, LCW{}, LCW{}}, st, mr}; + // Keep base brace nesting for empty-row hierarchy (Init empty encoding differs). + auto const list = LCW{{{1, 2, 3, 4}, {5}}, {{6, 7}}, {LCW{}, {8, 9, 10}}}; + auto const gather_map = LCW{LCW{}, LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // hack to get column of empty list of list - auto const expected_dummy = - LCW{{LCW{Init{{{1, 2, 3, 4}, {5}}}, st, mr}, LCW{}, LCW{}, LCW{}}, st, mr}; - auto const expected = cudf::split(expected_dummy, {1}, st)[1]; + auto const expected_dummy = LCW{{{1, 2, 3, 4}, {5}}, LCW{}, LCW{}, LCW{}}; + auto const expected = cudf::split(expected_dummy, {1}, st)[1]; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List>> { - auto const list = LCW{Init{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}, st, mr}; - auto const gather_map = LCW{{LCW{}, LCW{}}, st, mr}; + auto const list = LCW{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}; + auto const gather_map = LCW{LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // hack to get column of empty list of list of list - auto const expected_dummy = - LCW{{LCW{Init{{{{1, 2, 3, 4}}}}, st, mr}, LCW{}, LCW{}}, st, mr}; - auto const expected = cudf::split(expected_dummy, {1}, st)[1]; + auto const expected_dummy = LCW{{{{1, 2, 3, 4}}}, LCW{}, LCW{}}; + auto const expected = cudf::split(expected_dummy, {1}, st)[1]; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); @@ -178,7 +177,7 @@ TYPED_TEST(SegmentedGatherTest, GatherNulls) cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); auto const expected = - LCW{Init{{{{1, 2}, valids}, Init{}, {{7}, valids + 1}, {{10, 9, 8}, valids}}}, st, mr}; + LCW{Init{{{1, 2}, valids}, Init{}, {{7}, valids + 1}, {{10, 9, 8}, valids}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -188,7 +187,7 @@ TYPED_TEST(SegmentedGatherTest, GatherNulls) auto const results = cudf::lists::segmented_gather( cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); auto const expected = LCW{ - Init{{{{0, 0}, nulls_at({0, 1})}, Init{}, {{7}, valids + 1}, {{10, 0, 8}, null_at(1)}}}, + Init{{{0, 0}, nulls_at({0, 1})}, Init{}, {{7}, valids + 1}, {{10, 0, 8}, null_at(1)}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( @@ -227,9 +226,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNested) auto const gather_map = LCW{Init{{0, 2, -2}, {1}, {1, 0, -1, -6}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); - auto const expected = LCW{Init{{{{{2, 3}, Init{}, {2, 3}}, null_at(1)}, + auto const expected = LCW{Init{{{{2, 3}, Init{}, {2, 3}}, null_at(1)}, {{9, 10, 11}}, - {{{17, 18}, {15, 16}, {-17, -18}, Init{}}, null_at(3)}}}, st, mr}; + {{{17, 18}, {15, 16}, {-17, -18}, Init{}}, null_at(3)}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } @@ -246,11 +245,11 @@ TYPED_TEST(SegmentedGatherTest, GatherNested) {{{10, 20}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}}, st, mr}; auto const gather_map = LCW{Init{{1}, Init{}, {0}, {1}, {0, -1, 1}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - auto const expected = LCW{Init{{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + auto const expected = LCW{Init{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, Init{}, {{Init{0}}}, {{{0, 1, 3}, {5}}}, - {{{10, 20}}, {{40, 50}, {60, 70, 80}}, {Init{30}}}}}, st, mr}; + {{{10, 20}}, {{40, 50}, {60, 70, 80}}, {Init{30}}}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL(results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); // clang-format on } @@ -270,11 +269,11 @@ TYPED_TEST(SegmentedGatherTest, GatherNested) auto const results = cudf::lists::segmented_gather( cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); auto const expected = - LCW{Init{{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, + LCW{Init{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, Init{}, {{Init{0}}}, {{{0, 1, 3}, {5}}}, - {{{{10, 20}}, {{40, 50}, {60, 70, 80}}, Init{}, Init{}}, nulls_at({2, 3})}}}, + {{{{10, 20}}, {{40, 50}, {60, 70, 80}}, Init{}, Init{}}, nulls_at({2, 3})}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( @@ -411,14 +410,13 @@ TYPED_TEST(SegmentedGatherTest, GatherNestedWithEmpties) auto const st = this->stream(); auto const mr = this->resources(); - auto const list = - LCW{Init{{{2, 3}, Init{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {Init{}}}, st, mr}; - auto const gather_map = LCW{Init{{0}, {0}, {0}}, st, mr}; + auto const list = LCW{{{2, 3}, LCW{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {LCW{}}}; + auto const gather_map = LCW{LCW{0}, LCW{0}, LCW{0}}; auto results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); auto const expected = - LCW{Init{{{2, 3}}, {{6, 7, 8}}, {Init{}}}, st, mr}; // skip one null, gather one null. + LCW{{{2, 3}}, {{6, 7, 8}}, {LCW{}}}; // skip one null, gather one null. CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -609,9 +607,9 @@ TEST_F(SegmentedGatherTestString, StringGather) auto const gather_map = cudf::test::lists_column_wrapper{ I8Init{{0, 1, 3, 4}, {1, -5, 3, 2}, I8Init{}}, st, mr}; auto const expected = - LCW{StrInit{{{{"a", "b", "d", "c"}, cudf::test::iterators::null_at(3)}, + LCW{StrInit{{{"a", "b", "d", "c"}, cudf::test::iterators::null_at(3)}, {{"22", "1", "4", "333"}, cudf::test::iterators::null_at(1)}, - StrInit{}}}, + StrInit{}}, st, mr}; auto result = cudf::lists::segmented_gather( @@ -682,7 +680,7 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) auto const gather_map = LCW{Init{{3, -5, 1, 0}, {0}, {0, 1}, {0, 2, 3}, {0}, {1}}, st, mr}; // gather_map.offset: 0, 4, 5, 7, 10, 11, 12 auto const expected = - LCW{Init{{{{4, 0, 2, 1}, null_at(1)}, {5}, {6, 7}, {{8, 10, 9}, null_at(2)}, {11}, {14}}}, + LCW{Init{{{4, 0, 2, 1}, null_at(1)}, {5}, {6, 7}, {{8, 10, 9}, null_at(2)}, {11}, {14}}, st, mr}; auto results = cudf::lists::segmented_gather( @@ -755,7 +753,7 @@ TEST_F(SegmentedGatherTestFloat, Fails) auto valids = cudf::test::iterators::valids_at_multiples_of(2); cudf::test::lists_column_wrapper nulls_map{ - I8Init{{{{3, 2, 1, 0}, {0}, {0}, {0, 1}}, valids}}, st, mr}; + I8Init{{{3, 2, 1, 0}, {0}, {0}, {0, 1}}, valids}, st, mr}; // Nulls are not supported in the gather map. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, diff --git a/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp b/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp index 50531b2b6448..efde223fcc68 100644 --- a/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp +++ b/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp @@ -1587,12 +1587,12 @@ TEST_F(ListsColumnInitializerHarnessTest, LeafNullableInitUsesExplicitResources) std::unique_ptr built; { auto fail_on_current = this->fail_on_current_device_resource_use(); - LCW list{Init{{{1, 2, 3, 4}, null_at(1)}}, st, mr}; + LCW list{Init{{1, 2, 3, 4}, null_at(1)}, st, mr}; this->_harness.synchronize(st); built = list.release(); } - LCW expected{Init{{{1, 2, 3, 4}, null_at(1)}}, st, mr}; + LCW expected{Init{{1, 2, 3, 4}, null_at(1)}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } From e607cb19912c50bf176dbcb89f09e1def3c26c35 Mon Sep 17 00:00:00 2001 From: Niranda Perera Date: Mon, 17 Aug 2026 14:28:15 -0700 Subject: [PATCH 3/5] reorder ctrs --- cpp/include/cudf_test/column_wrapper.hpp | 88 ++++++++++++------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/cpp/include/cudf_test/column_wrapper.hpp b/cpp/include/cudf_test/column_wrapper.hpp index 8ac30e57b0f0..c9889822665c 100644 --- a/cpp/include/cudf_test/column_wrapper.hpp +++ b/cpp/include/cudf_test/column_wrapper.hpp @@ -1693,30 +1693,6 @@ class lists_column_wrapper : public detail::column_wrapper { fixed_width_column_wrapper(elements, stream, mr).release(), stream, mr); } - /** - * @brief Construct a lists column containing a single list of strings. - * - * Example: - * @code{.cpp} - * // Creates a LIST column with 1 list composed of 2 total strings - * // [{"abc", "def"}] - * lists_column_wrapper s{"abc", "def"}; - * @endcode - * - * @param elements The list of strings - * @param stream CUDA stream used for device memory operations - * @param mr Memory resources used to allocate the returned column - */ - template - lists_column_wrapper(std::initializer_list elements, - rmm::cuda_stream_view stream = cudf::test::get_default_stream(), - cudf::memory_resources mr = cudf::get_current_device_resource_ref()) - requires(std::is_same_v) - : column_wrapper{} - { - build_from_non_nested(strings_column_wrapper(elements, stream, mr).release(), stream, mr); - } - /** * @brief Construct a lists column containing a single list from an iterator range. * @@ -1773,60 +1749,84 @@ class lists_column_wrapper : public detail::column_wrapper { } /** - * @brief Construct a lists column containing a single list of strings and a - * validity iterator. + * @brief Construct a lists column containing a single list from an iterator + * range and a validity iterator. * * Example: * @code{.cpp} + * // Creates a LIST column with 1 list composed of 5 total integers + * auto elements = make_counting_transform_iterator(0, [](auto i){return i*2;}); * auto validity = make_counting_transform_iterator(0, [](auto i){return i%2;}); - * // [{"abc", NULL}] - * lists_column_wrapper l{{"abc", "def"}, validity}; + * // [{0, NULL, 2, NULL, 4}] + * lists_column_wrapper l(elements, elements+5, validity); * @endcode * - * @param elements The list of strings + * @param begin Beginning of the sequence + * @param end End of the sequence * @param v The validity iterator * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template - lists_column_wrapper(std::initializer_list elements, + template + lists_column_wrapper(InputIterator begin, + InputIterator end, ValidityIterator v, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} + { + build_from_non_nested(leaf_wrapper_t(begin, end, v, stream, mr).release(), stream, mr); + } + + /** + * @brief Construct a lists column containing a single list of strings. + * + * Example: + * @code{.cpp} + * // Creates a LIST column with 1 list composed of 2 total strings + * // [{"abc", "def"}] + * lists_column_wrapper s{"abc", "def"}; + * @endcode + * + * @param elements The list of strings + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column + */ + template + lists_column_wrapper(std::initializer_list elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) requires(std::is_same_v) : column_wrapper{} { - build_from_non_nested(strings_column_wrapper(elements, v, stream, mr).release(), stream, mr); + build_from_non_nested(strings_column_wrapper(elements, stream, mr).release(), stream, mr); } /** - * @brief Construct a lists column containing a single list from an iterator - * range and a validity iterator. + * @brief Construct a lists column containing a single list of strings and a + * validity iterator. * * Example: * @code{.cpp} - * // Creates a LIST column with 1 list composed of 5 total integers - * auto elements = make_counting_transform_iterator(0, [](auto i){return i*2;}); * auto validity = make_counting_transform_iterator(0, [](auto i){return i%2;}); - * // [{0, NULL, 2, NULL, 4}] - * lists_column_wrapper l(elements, elements+5, validity); + * // [{"abc", NULL}] + * lists_column_wrapper l{{"abc", "def"}, validity}; * @endcode * - * @param begin Beginning of the sequence - * @param end End of the sequence + * @param elements The list of strings * @param v The validity iterator * @param stream CUDA stream used for device memory operations * @param mr Memory resources used to allocate the returned column */ - template - lists_column_wrapper(InputIterator begin, - InputIterator end, + template + lists_column_wrapper(std::initializer_list elements, ValidityIterator v, rmm::cuda_stream_view stream = cudf::test::get_default_stream(), cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + requires(std::is_same_v) : column_wrapper{} { - build_from_non_nested(leaf_wrapper_t(begin, end, v, stream, mr).release(), stream, mr); + build_from_non_nested(strings_column_wrapper(elements, v, stream, mr).release(), stream, mr); } /** From 8402bb66bd26507113cf3d4c176871f185a563a0 Mon Sep 17 00:00:00 2001 From: niranda perera Date: Tue, 18 Aug 2026 11:22:25 -0700 Subject: [PATCH 4/5] precommit Signed-off-by: niranda perera --- cpp/tests/copying/gather_list_tests.cpp | 67 +++---- .../copying/segmented_gather_list_tests.cpp | 170 ++++++++++++------ .../lists_column_wrapper_tests.cpp | 8 +- 3 files changed, 159 insertions(+), 86 deletions(-) diff --git a/cpp/tests/copying/gather_list_tests.cpp b/cpp/tests/copying/gather_list_tests.cpp index 2e9ff3fdfed6..2f8ad7db254b 100644 --- a/cpp/tests/copying/gather_list_tests.cpp +++ b/cpp/tests/copying/gather_list_tests.cpp @@ -49,8 +49,8 @@ TYPED_TEST(GatherTestListTyped, Gather) cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{1, 2, 3, 4}, {6, 7}}, st, mr}; @@ -71,8 +71,8 @@ TYPED_TEST(GatherTestListTyped, GatherNothing) cudf::test::fixed_width_column_wrapper gather_map{}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected; @@ -87,8 +87,8 @@ TYPED_TEST(GatherTestListTyped, GatherNothing) cudf::test::fixed_width_column_wrapper gather_map{}; cudf::table_view source_table({list}); - auto result = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -120,8 +120,8 @@ TYPED_TEST(GatherTestListTyped, GatherNulls) cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{{1, 2, 3, 4}, valids}, {{6, 7}, valids}}, st, mr}; @@ -146,8 +146,8 @@ TYPED_TEST(GatherTestListTyped, GatherNested) cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ Init{{{2, 3}, {4, 5}}, {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, st, mr}; @@ -170,8 +170,8 @@ TYPED_TEST(GatherTestListTyped, GatherNested) cudf::test::fixed_width_column_wrapper gather_map{{1, 2, 4}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{{{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}}, {{Init{0}}}, @@ -201,8 +201,8 @@ TYPED_TEST(GatherTestListTyped, GatherOutOfOrder) cudf::test::fixed_width_column_wrapper gather_map{{1, 2, 0}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {{15, 16}, {17, 18}, {17, 18}, {17, 18}, {17, 18}}, @@ -237,8 +237,8 @@ TYPED_TEST(GatherTestListTyped, GatherNestedNulls) cudf::test::fixed_width_column_wrapper gather_map{{0, 1, 3}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ Init{{{{2, 3}, valids}, {4, 5}}, @@ -266,8 +266,8 @@ TYPED_TEST(GatherTestListTyped, GatherNestedNulls) cudf::test::fixed_width_column_wrapper gather_map{{1, 2, 4}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{{{15, 16}, {{27, 28}, valids}, {{37, 38}, valids}, {47, 48}, {57, 58}}}, {{Init{0}}}, @@ -291,8 +291,8 @@ TYPED_TEST(GatherTestListTyped, GatherNestedWithEmpties) cudf::test::fixed_width_column_wrapper gather_map{{0, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{{2, 3}, Init{}}, {Init{}}}, st, mr}; @@ -317,8 +317,8 @@ TYPED_TEST(GatherTestListTyped, GatherDetailInvalidIndex) cudf::test::fixed_width_column_wrapper gather_map{{0, 15, 16, 2}, st, mr}; cudf::table_view source_table({list}); - auto results = - cudf::gather(source_table, gather_map, cudf::out_of_bounds_policy::NULLIFY, st, mr.get_output_mr()); + auto results = cudf::gather( + source_table, gather_map, cudf::out_of_bounds_policy::NULLIFY, st, mr.get_output_mr()); std::vector expected_validity{1, 0, 0, 1}; LCW expected{ @@ -346,8 +346,8 @@ TEST_F(GatherTestList, GatherIncompleteHierarchies) cudf::table_view source_table({list}); cudf::test::fixed_width_column_wrapper row1_map{{1}, st, mr}; - auto result = - cudf::gather(source_table, row1_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result = cudf::gather( + source_table, row1_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -372,8 +372,8 @@ TEST_F(GatherTestList, GatherIncompleteHierarchies) cudf::table_view source_table({list}); cudf::test::fixed_width_column_wrapper empty_map{}; - auto result = - cudf::gather(source_table, empty_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result = cudf::gather( + source_table, empty_map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); // the result should preserve the full List>> hierarchy // even though it is empty past the first level @@ -416,7 +416,8 @@ TYPED_TEST(GatherTestListTyped, GatherSliced) cudf::table_view tbl1({split_a[1]}); cudf::test::fixed_width_column_wrapper map0{{1, 2}, st, mr}; - auto result0 = cudf::gather(tbl0, map0, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result0 = + cudf::gather(tbl0, map0, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected0{Init{ {{4, 4, 4}, {5, 5}, {6, 6}}, {{7, 7, 7}, {8, 8}, {9, 9}}, @@ -430,7 +431,8 @@ TYPED_TEST(GatherTestListTyped, GatherSliced) mr); cudf::test::fixed_width_column_wrapper map1{{0, 3}, st, mr}; - auto result1 = cudf::gather(tbl1, map1, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result1 = + cudf::gather(tbl1, map1, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected1{Init{ {{10, 10, 10}, {11, 11}, {12, 12}}, {{50, 50, 50, 50}, {6, 13}}, @@ -475,7 +477,8 @@ TYPED_TEST(GatherTestListTyped, GatherSliced) cudf::table_view tbl({sliced[0]}); cudf::test::fixed_width_column_wrapper map{{0}, st, mr}; - auto result = cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result = + cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->get_column(0).view(), @@ -490,7 +493,8 @@ TYPED_TEST(GatherTestListTyped, GatherSliced) cudf::table_view tbl({sliced[1]}); cudf::test::fixed_width_column_wrapper map{{1, 2, 0, 1}, st, mr}; - auto result = cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result = + cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ Init{ {{{10}, {20, 30, 40, 50}, {60, 70, 80}}, @@ -520,7 +524,8 @@ TYPED_TEST(GatherTestListTyped, GatherSliced) cudf::table_view tbl({sliced[2]}); cudf::test::fixed_width_column_wrapper map{{1, 0, 0, 1, 1, 0}, st, mr}; - auto result = cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + auto result = + cudf::gather(tbl, map, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); LCW expected{ Init{{{{{10, 20, 30}}, {Init{30}}, {{{20, 30}, valids}, {62, 72, 82}}}, valids}, {{{{{10, 20}, valids}}, {Init{30}}, {{40, 50}, {60, 70, 80}}}, valids}, diff --git a/cpp/tests/copying/segmented_gather_list_tests.cpp b/cpp/tests/copying/segmented_gather_list_tests.cpp index cf041519fe0a..712a96ec82b2 100644 --- a/cpp/tests/copying/segmented_gather_list_tests.cpp +++ b/cpp/tests/copying/segmented_gather_list_tests.cpp @@ -62,7 +62,9 @@ TYPED_TEST(SegmentedGatherTest, Gather) auto const expected = LCW{Init{{4, 3, 2, 1}, {5}, {6, 7}, {8, 10, 9}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -72,8 +74,11 @@ TYPED_TEST(SegmentedGatherTest, Gather) auto const gather_map = LCW{Init{{3, 2, 4, 0}, {0}, {0, -3}, {0, 2, 1}}, st, mr}; auto const expected = LCW{Init{{{4, 3, 2, 1}, null_at(2)}, {5}, {{6, 7}, null_at(1)}, {8, 10, 9}}, st, mr}; - auto const results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, + cudf::lists_column_view{gather_map}, + NULLIFY, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -92,7 +97,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) auto const gather_map = LCW{{LCW{}, LCW{}, LCW{}, LCW{}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); auto const expected = LCW{{LCW{}, LCW{}, LCW{}, LCW{}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); @@ -104,7 +111,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) auto const gather_map = LCW{LCW{}, LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); // hack to get column of empty list of list auto const expected_dummy = LCW{{{1, 2, 3, 4}, {5}}, LCW{}, LCW{}, LCW{}}; @@ -118,7 +127,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) auto const gather_map = LCW{LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); // hack to get column of empty list of list of list auto const expected_dummy = LCW{{{{1, 2, 3, 4}}}, LCW{}, LCW{}}; auto const expected = cudf::split(expected_dummy, {1}, st)[1]; @@ -152,7 +163,9 @@ TEST_F(SegmentedGatherTestSingle, GatherEmpty) auto const expected = LCW{}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -175,7 +188,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNulls) auto const gather_map = LCW{Init{{0, 1}, Init{}, {1}, {2, 1, 0}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); auto const expected = LCW{Init{{{1, 2}, valids}, Init{}, {{7}, valids + 1}, {{10, 9, 8}, valids}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( @@ -184,12 +199,15 @@ TYPED_TEST(SegmentedGatherTest, GatherNulls) { // Test gathering on lists that contain nulls, with out-of-bounds indices. auto const gather_map = LCW{Init{{10, -10}, Init{}, {1}, {2, -10, 0}}, st, mr}; - auto const results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); - auto const expected = LCW{ - Init{{{0, 0}, nulls_at({0, 1})}, Init{}, {{7}, valids + 1}, {{10, 0, 8}, null_at(1)}}, - st, - mr}; + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, + cudf::lists_column_view{gather_map}, + NULLIFY, + st, + mr.get_output_mr()); + auto const expected = + LCW{Init{{{0, 0}, nulls_at({0, 1})}, Init{}, {{7}, valids + 1}, {{10, 0, 8}, null_at(1)}}, + st, + mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -266,14 +284,17 @@ TYPED_TEST(SegmentedGatherTest, GatherNested) st, mr}; auto const gather_map = LCW{Init{{1}, Init{}, {0}, {1}, {0, -1, 3, -4}}, st, mr}; - auto const results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, + cudf::lists_column_view{gather_map}, + NULLIFY, + st, + mr.get_output_mr()); auto const expected = LCW{Init{{{{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}, - Init{}, - {{Init{0}}}, - {{{0, 1, 3}, {5}}}, - {{{{10, 20}}, {{40, 50}, {60, 70, 80}}, Init{}, Init{}}, nulls_at({2, 3})}}, + Init{}, + {{Init{0}}}, + {{{0, 1, 3}, {5}}}, + {{{{10, 20}}, {{40, 50}, {60, 70, 80}}, Init{}, Init{}}, nulls_at({2, 3})}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( @@ -414,7 +435,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNestedWithEmpties) auto const gather_map = LCW{LCW{0}, LCW{0}, LCW{0}}; auto results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); auto const expected = LCW{{{2, 3}}, {{6, 7, 8}}, {LCW{}}}; // skip one null, gather one null. CUDF_TEST_EXPECT_COLUMNS_EQUAL( @@ -448,7 +471,9 @@ TYPED_TEST(SegmentedGatherTest, GatherSliced) auto const gather_map = cudf::lists_column_view{list}; auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{split_a[0]}, gather_map, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); auto const expected = LCW{Init{ {{2, 2}, {3, 3}}, {{4, 4, 4}, {6, 6}}, @@ -465,7 +490,9 @@ TYPED_TEST(SegmentedGatherTest, GatherSliced) auto const gather_map = cudf::lists_column_view{list}; auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{split_a[1]}, gather_map, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); auto const expected = LCW{Init{{{10, 10, 10}, {11, 11}}, Init{}, Init{}, {{50, 50, 50, 50}, {6, 13}}, Init{}}, st, @@ -506,7 +533,9 @@ TYPED_TEST(SegmentedGatherTest, GatherSliced) LCW map{Init{{0, 1}}, st, mr}; auto result = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[0]}, cudf::lists_column_view{map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); LCW expected{Init{{{{2, 3}, {4, 5}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}}}, st, mr}; CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected, result->view(), @@ -521,7 +550,9 @@ TYPED_TEST(SegmentedGatherTest, GatherSliced) LCW map{Init{{0}, {1, 2, 0, 1}, {0, 1, 2}}, st, mr}; auto result = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[1]}, cudf::lists_column_view{map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); LCW expected{ Init{ {{Init{0}}}, @@ -548,7 +579,9 @@ TYPED_TEST(SegmentedGatherTest, GatherSliced) LCW map{Init{{1, 0, 0, 1, 1, 0}, {1, 0, 0, 1, 1, 2}}, st, mr}; auto result = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[2]}, cudf::lists_column_view{map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); std::vector expected_valids = {false, true, true, false, false, true}; LCW expected{Init{{{{Init{30}}, @@ -595,7 +628,9 @@ TEST_F(SegmentedGatherTestString, StringGather) LCW{StrInit{{"a", "b", "d", "c"}, {"22", "1", "4", "333"}, StrInit{}}, st, mr}; auto const result = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( expected, result->view(), cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -608,12 +643,15 @@ TEST_F(SegmentedGatherTestString, StringGather) I8Init{{0, 1, 3, 4}, {1, -5, 3, 2}, I8Init{}}, st, mr}; auto const expected = LCW{StrInit{{{"a", "b", "d", "c"}, cudf::test::iterators::null_at(3)}, - {{"22", "1", "4", "333"}, cudf::test::iterators::null_at(1)}, - StrInit{}}, + {{"22", "1", "4", "333"}, cudf::test::iterators::null_at(1)}, + StrInit{}}, st, mr}; - auto result = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto result = cudf::lists::segmented_gather(cudf::lists_column_view{list}, + cudf::lists_column_view{gather_map}, + NULLIFY, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( expected, result->view(), cudf::test::debug_output_level::FIRST_ERROR, st, mr); } @@ -636,7 +674,9 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) auto const expected = LCW{Init{{4, 3, 2, 1}, {5}, {6, 7}, {8, 10, 9}, {11}, {14}}, st, mr}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); @@ -646,7 +686,9 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) auto result0 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[0]}, cudf::lists_column_view{split_m[0]}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[0], result0->view(), cudf::test::debug_output_level::FIRST_ERROR, @@ -655,7 +697,9 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) mr); auto result1 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[1]}, cudf::lists_column_view{split_m[1]}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[1], result1->view(), cudf::test::debug_output_level::FIRST_ERROR, @@ -664,7 +708,9 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) mr); auto result2 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[2]}, cudf::lists_column_view{split_m[2]}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[2], result2->view(), cudf::test::debug_output_level::FIRST_ERROR, @@ -679,12 +725,13 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) LCW{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}, {11, 12}, {13, 14, 15, 16}}, st, mr}; auto const gather_map = LCW{Init{{3, -5, 1, 0}, {0}, {0, 1}, {0, 2, 3}, {0}, {1}}, st, mr}; // gather_map.offset: 0, 4, 5, 7, 10, 11, 12 - auto const expected = - LCW{Init{{{4, 0, 2, 1}, null_at(1)}, {5}, {6, 7}, {{8, 10, 9}, null_at(2)}, {11}, {14}}, - st, - mr}; - auto results = cudf::lists::segmented_gather( - cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, NULLIFY, st, mr.get_output_mr()); + auto const expected = LCW{ + Init{{{4, 0, 2, 1}, null_at(1)}, {5}, {6, 7}, {{8, 10, 9}, null_at(2)}, {11}, {14}}, st, mr}; + auto results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, + cudf::lists_column_view{gather_map}, + NULLIFY, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); @@ -692,24 +739,33 @@ TEST_F(SegmentedGatherTestFloat, GatherMapSliced) auto const split_m = cudf::split(gather_map, {1, 4}, st); auto const split_e = cudf::split(expected, {1, 4}, st); - auto const result0 = cudf::lists::segmented_gather( - cudf::lists_column_view{sliced[0]}, cudf::lists_column_view{split_m[0]}, NULLIFY, st, mr.get_output_mr()); + auto const result0 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[0]}, + cudf::lists_column_view{split_m[0]}, + NULLIFY, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[0], result0->view(), cudf::test::debug_output_level::FIRST_ERROR, cudf::test::default_ulp, st, mr); - auto const result1 = cudf::lists::segmented_gather( - cudf::lists_column_view{sliced[1]}, cudf::lists_column_view{split_m[1]}, NULLIFY, st, mr.get_output_mr()); + auto const result1 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[1]}, + cudf::lists_column_view{split_m[1]}, + NULLIFY, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[1], result1->view(), cudf::test::debug_output_level::FIRST_ERROR, cudf::test::default_ulp, st, mr); - auto const result2 = cudf::lists::segmented_gather( - cudf::lists_column_view{sliced[2]}, cudf::lists_column_view{split_m[2]}, NULLIFY, st, mr.get_output_mr()); + auto const result2 = cudf::lists::segmented_gather(cudf::lists_column_view{sliced[2]}, + cudf::lists_column_view{split_m[2]}, + NULLIFY, + st, + mr.get_output_mr()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(split_e[2], result2->view(), cudf::test::debug_output_level::FIRST_ERROR, @@ -738,17 +794,23 @@ TEST_F(SegmentedGatherTestFloat, Fails) // strings, or lists containing anything other than integers. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{nonlist_map0}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()), cudf::logic_error); EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{nonlist_map1}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()), cudf::logic_error); EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{nonlist_map2}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()), cudf::logic_error); auto valids = cudf::test::iterators::valids_at_multiples_of(2); @@ -758,13 +820,17 @@ TEST_F(SegmentedGatherTestFloat, Fails) // Nulls are not supported in the gather map. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{nulls_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()), std::invalid_argument); // Gather map and list column sizes must be the same. EXPECT_THROW(cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{size_mismatch_map}, - cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()), + cudf::out_of_bounds_policy::DONT_CHECK, + st, + mr.get_output_mr()), cudf::logic_error); } diff --git a/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp b/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp index efde223fcc68..e8085b1cb3b2 100644 --- a/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp +++ b/cpp/tests/utilities_tests/lists_column_wrapper_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -1572,7 +1572,8 @@ TEST_F(ListsColumnInitializerHarnessTest, LeafInitUsesExplicitResources) } LCW expected{Init{{1, 2, 3, 4}}, st, mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } TEST_F(ListsColumnInitializerHarnessTest, LeafNullableInitUsesExplicitResources) @@ -1615,5 +1616,6 @@ TEST_F(ListsColumnInitializerHarnessTest, SingleChildNestedInitUsesExplicitResou } LCW expected{Init{{{{1, 2, 3}}}}, st, mr}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *built, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } From 60c8c7efb147101bd11d4b25aa04dd475adbd0d9 Mon Sep 17 00:00:00 2001 From: niranda perera Date: Tue, 18 Aug 2026 13:30:16 -0700 Subject: [PATCH 5/5] fix tests --- .../copying/segmented_gather_list_tests.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp/tests/copying/segmented_gather_list_tests.cpp b/cpp/tests/copying/segmented_gather_list_tests.cpp index 712a96ec82b2..472c82adfb35 100644 --- a/cpp/tests/copying/segmented_gather_list_tests.cpp +++ b/cpp/tests/copying/segmented_gather_list_tests.cpp @@ -94,20 +94,19 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) // List { auto const list = LCW{Init{{1, 2, 3, 4}, {5}, {6, 7}, {8, 9, 10}}, st, mr}; - auto const gather_map = LCW{{LCW{}, LCW{}, LCW{}, LCW{}}, st, mr}; + auto const gather_map = LCW{LCW{}, LCW{}, LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, cudf::out_of_bounds_policy::DONT_CHECK, st, mr.get_output_mr()); - auto const expected = LCW{{LCW{}, LCW{}, LCW{}, LCW{}}, st, mr}; + auto const expected = LCW{LCW{}, LCW{}, LCW{}, LCW{}}; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List> { - // Keep base brace nesting for empty-row hierarchy (Init empty encoding differs). - auto const list = LCW{{{1, 2, 3, 4}, {5}}, {{6, 7}}, {LCW{}, {8, 9, 10}}}; + auto const list = LCW{Init{{{1, 2, 3, 4}, {5}}, {{6, 7}}, {Init{}, {8, 9, 10}}}, st, mr}; auto const gather_map = LCW{LCW{}, LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, @@ -116,14 +115,14 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) mr.get_output_mr()); // hack to get column of empty list of list - auto const expected_dummy = LCW{{{1, 2, 3, 4}, {5}}, LCW{}, LCW{}, LCW{}}; + auto const expected_dummy = LCW{Init{{{1, 2, 3, 4}, {5}}, Init{}, Init{}, Init{}}, st, mr}; auto const expected = cudf::split(expected_dummy, {1}, st)[1]; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); } // List>> { - auto const list = LCW{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}; + auto const list = LCW{Init{{{{1, 2, 3, 4}, {5}}}, {{{6, 7}, {8, 9, 10}}}}, st, mr}; auto const gather_map = LCW{LCW{}, LCW{}}; auto const results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, @@ -131,7 +130,7 @@ TYPED_TEST(SegmentedGatherTest, GatherNothing) st, mr.get_output_mr()); // hack to get column of empty list of list of list - auto const expected_dummy = LCW{{{{1, 2, 3, 4}}}, LCW{}, LCW{}}; + auto const expected_dummy = LCW{Init{{{{1, 2, 3, 4}}}, Init{}, Init{}}, st, mr}; auto const expected = cudf::split(expected_dummy, {1}, st)[1]; CUDF_TEST_EXPECT_COLUMNS_EQUAL( *results, expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); @@ -431,7 +430,9 @@ TYPED_TEST(SegmentedGatherTest, GatherNestedWithEmpties) auto const st = this->stream(); auto const mr = this->resources(); - auto const list = LCW{{{2, 3}, LCW{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {LCW{}}}; + auto const list = + LCW{Init{{{2, 3}, Init{}}, {{6, 7, 8}, {9, 10, 11}, {12, 13, 14}}, {Init{}}}, st, mr}; + // Per-row singleton lists: brace LCWs (Init{{0},{0},{0}} flattens to one list of three). auto const gather_map = LCW{LCW{0}, LCW{0}, LCW{0}}; auto results = cudf::lists::segmented_gather(cudf::lists_column_view{list}, cudf::lists_column_view{gather_map}, @@ -439,7 +440,7 @@ TYPED_TEST(SegmentedGatherTest, GatherNestedWithEmpties) st, mr.get_output_mr()); auto const expected = - LCW{{{2, 3}}, {{6, 7, 8}}, {LCW{}}}; // skip one null, gather one null. + LCW{Init{{{2, 3}}, {{6, 7, 8}}, {Init{}}}, st, mr}; // skip one null, gather one null. CUDF_TEST_EXPECT_COLUMNS_EQUAL( results->view(), expected, cudf::test::debug_output_level::FIRST_ERROR, st, mr); }