[test] Add projection tests for hpx::ranges::{unique_copy, partition_copy, remove_copy, remove_copy_if}#7259
Conversation
|
Can one of the admins verify this patch? |
8323713 to
01df0e5
Compare
Up to standards ✅🟢 Issues
|
|
@aneek22112007-tech some of the newly added tests fail to compile, could you please have a look? Also, inspect complains abut non-ASCII characters in the tests: |
|
@hkaiser Thanks for the review! I've pushed a fix in commit 1. Compile failure (projection tests): The root cause was in two places:
The All tests now compile and pass locally with |
d630a56 to
89838ee
Compare
|
@aneek22112007-tech Could you please watch the Cis yourself? Currently we see compilation errors. You may have to rebase onto master in order to fix part of them. |
|
@aneek22112007-tech ping? |
Add dedicated projection-aware tests to the range-based container
algorithm test suite for four copy-classification algorithms:
unique_copy, partition_copy, remove_copy, and remove_copy_if.
All four algorithms accept an optional Proj parameter in their CPO
layer (container_algorithms/unique.hpp, container_algorithms/
remove_copy.hpp), but their existing range test files exercised only
the default hpx::identity projection path, leaving the user-supplied
projection code path completely untested.
Changes:
- unique_copy_range.cpp: add test_unique_copy_projection() that
projects user_defined_type::val and verifies consecutive-equal
elements are correctly deduplicated across seq, par, par_unseq,
seq(task), and par(task) policies. Results are cross-checked
against std::unique_copy with an equivalent lambda predicate.
- partition_copy_range.cpp: add test_partition_copy_projection()
that projects user_defined_type::val to int and applies a plain
integer threshold predicate (distinct from the name-aware
operator< used by existing tests), verifying both true and false
output partitions against std::partition_copy across all policies.
- remove_copy_range.cpp: introduce a projected_element{key, tag}
helper struct and add test_remove_copy_projection() that removes
by projected key equality using a deterministic input (keys 0-4
cycling). Results are verified against a hand-built expected
vector across all policies including async task variants.
- remove_copy_if_range.cpp: same projected_element helper and
test_remove_copy_if_projection() that removes elements with odd
projected keys via a unary predicate, verified across all six
policy variants.
These additions close a silent testing gap: any future refactor that
accidentally breaks projection threading in the internal copy/
remove_copy dispatch would now be caught by CI.
Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
- Replace UTF-8 em-dash (U+2014) with ASCII hyphen in comments across partition_copy_range.cpp, remove_copy_if_range.cpp, remove_copy_range.cpp and unique_copy_range.cpp (flagged by maintainer CI checks) - Fix hpx::ranges::remove_copy_if CPO: change the predicate invocability constraint from is_invocable_v<Pred, value_type> to is_indirect_callable_v<..., projected<Proj, I>> so that predicates operating on the projected type (not the raw element type) are correctly accepted. This is consistent with how partition_copy, unique_copy and other range algorithms express the same constraint. Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
The parallel path of hpx::parallel::detail::remove_copy_if used a lambda with parameter type 'value_type const&' (the raw iterator_traits::value_type) to wrap the user predicate. When copy_if applies the projection and passes the projected value to this lambda, the types do not match when a non-identity projection is in use (e.g. projected_element -> int), causing a hard compile error. Fix: use 'auto&&' as the lambda parameter so the wrapper accepts whatever copy_if passes after applying the projection. Also remove the now-redundant 'using value_type' alias. In hpx::ranges::remove_copy, the four tag_fallback_invoke overloads similarly used 'type const&' (from iterator_traits) instead of 'T const&' (the projected value type deduced from projected<I, Proj>::value_type). Fix: replace all four lambda parameter types from 'type' to 'T' and remove the dead 'using type' aliases. Also fix three overly-strict test assertions in test_remove_copy_projection: the parallel (par, par_unseq, par(task)) overloads do not guarantee res.in == std::end(c) -- the input iterator position in the parallel path is implementation-defined. Remove those assertions to match the convention used in the existing non-projection parallel tests in this file. Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
…ique_copy
The 'result_projected' and 'base_projected' local variables in
sequential_unique (true_type and false_type paths) were declared with
element_type (i.e. the iterator's value_type), but were assigned the
result of HPX_INVOKE(proj, *iter). When a non-identity projection is
used (e.g. proj: T -> int), the projection return type differs from
value_type, causing a type mismatch and compilation failure.
Fix by introducing projected_type = std::invoke_result_t<Proj, element_type>
and using it for the cached projection result in all three places:
- sequential_unique (result_projected)
- sequential_unique_copy/true_type (base_projected)
- sequential_unique_copy/false_type (base_projected)
This allows the predicate to compare projected values of the correct
type (e.g. int for proj = [](T const& t) -> int { return t.val; }).
Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
89838ee to
92930f3
Compare
….hpp Collapse two-line 'using projected_type = ...' aliases onto a single line to comply with the project's clang-format rules, and reflow the tag_fallback_invoke return-type / parameter list in remove_copy.hpp to match the formatter's expected wrapping. No logic changes. Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
The two tag_fallback_invoke signatures returning ::type in remove_copy.hpp are formatted differently between clang-format versions (20 vs 22). Wrap them in clang-format off/on guards so the style is fixed regardless of which formatter version is used, matching the existing HPX pattern for version-sensitive return-type wrapping. No logic changes. Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
This commit corrects a bug in the parallel implementation of copy_if where the returned input iterator was incorrectly advanced by the output distance (number of elements copied) instead of the input distance (total number of elements evaluated). This fixes incorrect ranges::in_out_result returns for parallel remove_copy and remove_copy_if. Additionally, it cleans up unused typedefs in unique.hpp from a previous projection fix. Signed-off-by: Aneek22112007 <das.aneek007@gmail.com>
Proposed Changes
test_unique_copy_projection()tounique_copy_range.cpp— exercises theProjparameter of
hpx::ranges::unique_copyacrossseq,par,par_unseq,seq(task),and
par(task)policies usinguser_defined_type::valas the projected key,cross-checked against
std::unique_copytest_partition_copy_projection()topartition_copy_range.cpp— exercises theProjparameter ofhpx::ranges::partition_copywith a simple integer thresholdpredicate applied to the projected
valfield, verified againststd::partition_copyacross all policies
projected_element{key, tag}helper struct andtest_remove_copy_projection()/test_remove_copy_if_projection()toremove_copy_range.cppandremove_copy_if_range.cpp— exercises theProjparameter ofhpx::ranges::remove_copyandhpx::ranges::remove_copy_ifacross all executionpolicies including async task variants
Any background context you want to provide?
All four algorithms (
unique_copy,partition_copy,remove_copy,remove_copy_if)accept an optional
Projparameter in their CPO layer(
container_algorithms/unique.hpp,container_algorithms/remove_copy.hpp) and correctlythread it to the internal dispatch. However, their existing range test files exercised
only the default
hpx::identityprojection, leaving the user-supplied projectioncode path completely untested — a silent gap that would allow future refactors breaking
projection support to pass CI undetected.
This brings these algorithms in line with the projection testing standard already
established for
is_partitioned(is_partitioned_projection_range.cpp),is_sorted,and
minmax_element.No production code was changed. All additions are pure test code following existing
patterns (
HPX_TEST,test::equal).clang-format --dry-run --Werrorpasses withzero violations.
Checklist
Not all points below apply to all pull requests.
that random numbers generated are valid inputs for the tests.