| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/containers/to_vector.h" |
| |
| #include <ranges> |
| #include <set> |
| |
| #include "base/containers/adapters.h" |
| #include "base/containers/flat_set.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace base::test { |
| |
| template <class C> |
| void IdentityTest() { |
| C c = {1, 2, 3, 4, 5}; |
| auto vec = ToVector(c); |
| EXPECT_THAT(vec, testing::ElementsAre(1, 2, 3, 4, 5)); |
| } |
| |
| template <class C> |
| void ProjectionTest() { |
| C c = {1, 2, 3, 4, 5}; |
| auto vec = ToVector(c, [](int x) { return x + 1; }); |
| EXPECT_THAT(vec, testing::ElementsAre(2, 3, 4, 5, 6)); |
| } |
| |
| TEST(ToVectorTest, Identity) { |
| IdentityTest<std::vector<int>>(); |
| IdentityTest<std::set<int>>(); |
| IdentityTest<int[]>(); |
| IdentityTest<base::flat_set<int>>(); |
| } |
| |
| TEST(ToVectorTest, Projection) { |
| ProjectionTest<std::vector<int>>(); |
| ProjectionTest<std::set<int>>(); |
| ProjectionTest<int[]>(); |
| ProjectionTest<base::flat_set<int>>(); |
| } |
| |
| TEST(ToVectorTest, MoveOnly) { |
| std::vector<std::unique_ptr<int>> v; |
| v.push_back(std::make_unique<int>(1)); |
| v.push_back(std::make_unique<int>(2)); |
| v.push_back(std::make_unique<int>(3)); |
| |
| auto v2 = base::ToVector(base::RangeAsRvalues(std::move(v))); |
| EXPECT_THAT(v2, testing::ElementsAre(testing::Pointee(1), testing::Pointee(2), |
| testing::Pointee(3))); |
| |
| // The old vector should be consumed. The standard guarantees that a |
| // moved-from std::unique_ptr will be null. |
| // NOLINT(bugprone-use-after-move) |
| EXPECT_THAT(v, testing::ElementsAre(testing::IsNull(), testing::IsNull(), |
| testing::IsNull())); |
| |
| // Another method which is more verbose so not preferable. |
| auto v3 = base::ToVector( |
| std::move(v2), [](std::unique_ptr<int>& p) { return std::move(p); }); |
| EXPECT_THAT(v3, testing::ElementsAre(testing::Pointee(1), testing::Pointee(2), |
| testing::Pointee(3))); |
| // NOLINT(bugprone-use-after-move) |
| EXPECT_THAT(v2, testing::ElementsAre(testing::IsNull(), testing::IsNull(), |
| testing::IsNull())); |
| } |
| |
| template <typename C, typename Proj, typename T> |
| constexpr bool CorrectlyProjected = |
| std::is_same_v<T, |
| typename decltype(ToVector( |
| std::declval<C>(), |
| std::declval<Proj>()))::value_type>; |
| |
| TEST(ToVectorTest, CorrectlyProjected) { |
| // Tests that projected types are deduced correctly. |
| constexpr auto proj = [](const auto& value) -> const auto& { return value; }; |
| static_assert(CorrectlyProjected<std::vector<std::string>, decltype(proj), |
| std::string>); |
| static_assert( |
| CorrectlyProjected<std::set<std::string>, decltype(&std::string::length), |
| std::size_t>); |
| } |
| |
| } // namespace base::test |